From b6c2cfe3d4786cd6fb8df13f25a6f88882fe772e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=E4mer?= Date: Fri, 5 Oct 2012 09:54:08 +0200 Subject: [PATCH 0001/1476] Fixing the instructions in the readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index a2f700b7e..2b10d9092 100644 --- a/readme.md +++ b/readme.md @@ -16,7 +16,7 @@ The plugin is pretty easy to set up, all you need to do is to copy it to you app or - ./Console/cake Migrations.migration all --plugin Users + ./Console/cake Migrations.migration run all --plugin Users You will also need the [CakeDC Search plugin](http://github.com/CakeDC/search), just grab it and put it into your application's plugin folder. From db6623a64a5b5a780bc23759bc7f07bd700cd81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=E4mer?= Date: Fri, 5 Oct 2012 09:54:20 +0200 Subject: [PATCH 0002/1476] Fixing a syntax error --- Controller/UsersAppController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/UsersAppController.php b/Controller/UsersAppController.php index 2c90c3a38..c54f477d6 100644 --- a/Controller/UsersAppController.php +++ b/Controller/UsersAppController.php @@ -28,7 +28,7 @@ class UsersAppController extends AppController { * @return boolean True if allowed */ public function isAuthorized() { - return parent::isAuthorized; + return parent::isAuthorized(); } } From ec9343093e8c0e0e9dc912f77bd9cef7efd6be23 Mon Sep 17 00:00:00 2001 From: Callum Macdonald Date: Wed, 17 Oct 2012 15:45:56 +0300 Subject: [PATCH 0003/1476] Make the text Remember Me a label for the checkbox Using FormHelper::input() instead of FormHelper::checkbox() allows the text "Remember Me" to be supplied as a label, and so the text is clickable instead of just the checkbox. --- View/Users/login.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/View/Users/login.ctp b/View/Users/login.ctp index 460e1255d..46c642502 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -21,7 +21,7 @@ echo $this->Form->input('password', array( 'label' => __d('users', 'Password'))); - echo '

' . __d('users', 'Remember Me') . $this->Form->checkbox('remember_me') . '

'; + echo '

' . $this->Form->input('remember_me', array('type' => 'checkbox', 'label' => __d('users', 'Remember Me'))) . '

'; echo '

' . $this->Html->link(__d('users', 'I forgot my password'), array('action' => 'reset_password')) . '

'; echo $this->Form->hidden('User.return_to', array( From b049129fc9af015b9dda0e57ba3eaee5fa4c4f12 Mon Sep 17 00:00:00 2001 From: Callum Macdonald Date: Wed, 17 Oct 2012 17:04:06 +0300 Subject: [PATCH 0004/1476] Remember me cookie name / key were swapped According to the readme the cookie name is Users and the key is rememberMe, rather than the other way round. --- Controller/UsersController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index b0a8269b6..1b6af2248 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -652,13 +652,13 @@ protected function _sendPasswordReset($admin = null, $options = array()) { * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html */ - protected function _setCookie($options = array(), $cookieKey = 'User') { + protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { if (empty($this->request->data[$this->modelClass]['remember_me'])) { $this->Cookie->delete($cookieKey); } else { $validProperties = array('domain', 'key', 'name', 'path', 'secure', 'time'); $defaults = array( - 'name' => 'rememberMe'); + 'name' => 'Users'); $options = array_merge($defaults, $options); foreach ($options as $key => $value) { From ed62e880229f1c8b648c13478cb1aa96d97520ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 17 Oct 2012 18:01:57 +0200 Subject: [PATCH 0005/1476] Correcting the rememberMe cookie instructions in the readme.md --- readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 2b10d9092..624cd3176 100644 --- a/readme.md +++ b/readme.md @@ -44,10 +44,10 @@ To use the "remember me" checkbox which sets a cookie on the login page you will public function restoreLoginFromCookie() { $this->Cookie->name = 'Users'; $cookie = $this->Cookie->read('rememberMe'); - if (!empty($cookie) && !$this->Auth->user()) { - $data['User'][$this->Auth->fields['username']] = $cookie[$this->Auth->fields['username']]; - $data['User'][$this->Auth->fields['password']] = $cookie[$this->Auth->fields['password']]; - $this->Auth->login($data); + if (!empty($cookie)) { + $this->request->data['User'][$this->Auth->fields['username']] = $cookie[$this->Auth->fields['username']]; + $this->request->data['User'][$this->Auth->fields['password']] = $cookie[$this->Auth->fields['password']]; + $this->Auth->login(); } } From 7d92ed26e5c1c98fd2370c51bf1ba23675929142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 17 Oct 2012 18:03:12 +0200 Subject: [PATCH 0006/1476] Started refactoring the remember me feature --- Controller/Component/RememberMeComponent.php | 123 +++++++++++++++++++ Controller/UsersController.php | 30 ++--- 2 files changed, 132 insertions(+), 21 deletions(-) create mode 100644 Controller/Component/RememberMeComponent.php diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php new file mode 100644 index 000000000..9cae1d28b --- /dev/null +++ b/Controller/Component/RememberMeComponent.php @@ -0,0 +1,123 @@ + true, + 'userModel' => 'User', + 'cookieKey' => 'rememberMe', + 'cookieName' => 'Users', + 'fields' => array( + 'email', + 'username', + 'password', + ), + ); + +/** + * Constructor + * + * @param ComponentCollection $collection A ComponentCollection for this component + * @param array $settings Array of settings. + */ + public function __construct(ComponentCollection $collection, $settings = array()) { + parent::__construct($collection, $settings); + + $this->settings = Set::merge($this->_defaults, $settings); + $this->Controller = $collection->getController(); + $this->request = $this->Controller->request; + } + +/** + * + * + * @param Controller $controller + * @return void + */ + public function initialize(Controller $controller) { + if ($this->settings['autoLogin'] == true && !$this->Auth->loggedIn()) { + $this->restoreLoginFromCookie(); + } + } + +/** + * + */ + public function restoreLoginFromCookie() { + extract($this->settings); + + $this->Cookie->name = $cookieName; + $cookie = $this->Cookie->read($cookieKey); + + if (!empty($cookie)) { + foreach ($fields as $field) { + if (!empty($cookie[$field])) { + $this->request->data[$userModel][$field] = $cookie[$field]; + } + } + $this->Auth->login(); + } + } + +/** + * + */ + public function setCookie($options = array()) { + extract($this->settings); + + $validProperties = array('domain', 'key', 'name', 'path', 'secure', 'time'); + $defaults = array( + 'name' => 'Users'); + + $options = array_merge($defaults, $options); + + foreach ($options as $key => $value) { + if (in_array($key, $validProperties)) { + $this->Cookie->{$key} = $value; + } + } + + $cookieData = array(); + foreach ($fields as $field) { + if (isset($this->request->data[$userModel][$field]) && !empty($this->request->data[$userModel][$field])) { + $cookieData[$field] = $this->request->data[$userModel][$field]; + } + } + + $this->Cookie->write($cookieKey, $cookieData, true, '1 Month'); + } + + public function destroyCookie() { + extract($this->settings); + $this->Cookie->name = $cookieName; + $this->Cookie->destroy(); + } + +} \ No newline at end of file diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 1b6af2248..2b9401d7b 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -22,6 +22,7 @@ * @property SecurityComponent $Security * @property SessionComponent $Session * @property User $User + * @property RememberMeComponent $RememberMe */ class UsersController extends UsersAppController { @@ -56,6 +57,7 @@ class UsersController extends UsersAppController { 'Paginator', 'Security', 'Search.Prg', + 'Users.RememberMe', ); /** @@ -358,7 +360,11 @@ public function login() { $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged in'), $this->Auth->user('username'))); if (!empty($this->request->data)) { $data = $this->request->data[$this->modelClass]; - $this->_setCookie(); + if (empty($this->request->data[$this->modelClass]['remember_me'])) { + $this->RememberMe->destroyCookie(); + } else { + $this->_setCookie(); + } } if (empty($data['return_to'])) { @@ -431,6 +437,7 @@ public function logout() { $user = $this->Auth->user(); $this->Session->destroy(); $this->Cookie->destroy(); + $this->RememberMe->destroyCookie(); $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged out'), $user[$this->{$this->modelClass}->displayField])); $this->redirect($this->Auth->logout()); } @@ -653,26 +660,7 @@ protected function _sendPasswordReset($admin = null, $options = array()) { * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html */ protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { - if (empty($this->request->data[$this->modelClass]['remember_me'])) { - $this->Cookie->delete($cookieKey); - } else { - $validProperties = array('domain', 'key', 'name', 'path', 'secure', 'time'); - $defaults = array( - 'name' => 'Users'); - - $options = array_merge($defaults, $options); - foreach ($options as $key => $value) { - if (in_array($key, $validProperties)) { - $this->Cookie->{$key} = $value; - } - } - - $cookieData = array( - 'email' => $this->request->data[$this->modelClass]['email'], - 'password' => $this->request->data[$this->modelClass]['password']); - $this->Cookie->write($cookieKey, $cookieData, true, '1 Month'); - } - unset($this->request->data[$this->modelClass]['remember_me']); + $this->RememberMe->setCookie($options); } /** From b757d07c7defa8f2558a1534775c16868a06e4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 18 Oct 2012 00:34:43 +0200 Subject: [PATCH 0007/1476] Working on making the remember me functionality a component --- Controller/Component/RememberMeComponent.php | 71 ++++++++++++------- Controller/UsersController.php | 7 +- .../Component/RememberMeComponentTest.php | 4 ++ 3 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 Test/Case/Controller/Component/RememberMeComponentTest.php diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 9cae1d28b..863a7dbab 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -14,7 +14,6 @@ class RememberMeComponent extends Component { * @var array */ public $components = array( - 'Auth', 'Cookie'); /** @@ -24,6 +23,13 @@ class RememberMeComponent extends Component { */ public $request; +/** + * Settings + * + * @var array + */ + public $settings = array(); + /** * Default settings * @@ -33,7 +39,8 @@ class RememberMeComponent extends Component { 'autoLogin' => true, 'userModel' => 'User', 'cookieKey' => 'rememberMe', - 'cookieName' => 'Users', + 'cookie' => array( + 'name' => 'Users'), 'fields' => array( 'email', 'username', @@ -49,10 +56,8 @@ class RememberMeComponent extends Component { */ public function __construct(ComponentCollection $collection, $settings = array()) { parent::__construct($collection, $settings); - $this->settings = Set::merge($this->_defaults, $settings); - $this->Controller = $collection->getController(); - $this->request = $this->Controller->request; + $this->configureCookie($this->settings['cookie']); } /** @@ -61,19 +66,24 @@ public function __construct(ComponentCollection $collection, $settings = array() * @param Controller $controller * @return void */ - public function initialize(Controller $controller) { + public function startup(Controller $controller) { + $this->Controller = $controller; + $this->request = $this->Controller->request; + $this->response = $this->Controller->response; + $this->Auth = $this->Controller->Auth; + if ($this->settings['autoLogin'] == true && !$this->Auth->loggedIn()) { $this->restoreLoginFromCookie(); } } /** + * Logs the user again in based on the cookie data * + * @return boolean True on login success, false on failure */ public function restoreLoginFromCookie() { extract($this->settings); - - $this->Cookie->name = $cookieName; $cookie = $this->Cookie->read($cookieKey); if (!empty($cookie)) { @@ -82,28 +92,19 @@ public function restoreLoginFromCookie() { $this->request->data[$userModel][$field] = $cookie[$field]; } } - $this->Auth->login(); + return $this->Auth->login(); } } /** + * Sets the cookie with the specified fields * + * @param options + * @return void */ - public function setCookie($options = array()) { + public function setCookie() { extract($this->settings); - $validProperties = array('domain', 'key', 'name', 'path', 'secure', 'time'); - $defaults = array( - 'name' => 'Users'); - - $options = array_merge($defaults, $options); - - foreach ($options as $key => $value) { - if (in_array($key, $validProperties)) { - $this->Cookie->{$key} = $value; - } - } - $cookieData = array(); foreach ($fields as $field) { if (isset($this->request->data[$userModel][$field]) && !empty($this->request->data[$userModel][$field])) { @@ -111,13 +112,35 @@ public function setCookie($options = array()) { } } - $this->Cookie->write($cookieKey, $cookieData, true, '1 Month'); + $this->Cookie->write($cookieKey, $cookieData, true); } public function destroyCookie() { extract($this->settings); - $this->Cookie->name = $cookieName; $this->Cookie->destroy(); } +/** + * Configures the cookie component instance + * + * @param array $options + * @throws InvalidArgumentException Thrown if an invalid option key was passed + * @return void + */ + public function configureCookie($options = array()) { + $validProperties = array('domain', 'key', 'name', 'path', 'secure', 'time'); + $defaults = array( + 'time' => '1 month', + 'name' => 'Users'); + + $options = array_merge($defaults, $options); + + foreach ($options as $key => $value) { + if (in_array($key, $validProperties)) { + $this->Cookie->{$key} = $value; + } else { + throw new InvalidArgumentException(__('users', 'Invalid options %s', $key)); + } + } + } } \ No newline at end of file diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 2b9401d7b..b1f243d8b 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -655,11 +655,14 @@ protected function _sendPasswordReset($admin = null, $options = array()) { * Sets the cookie to remember the user * * @param array Cookie component properties as array, like array('domain' => 'yourdomain.com') - * @param string Cookie data keyname for the userdata, its default is "User". This is set to User and NOT using the model alias to make sure it works with different apps with different user models across different (sub)domains. + * @param string $cookieKey * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html + * @deprecated Use the RememberMe Component */ - protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { + protected function _setCookie($options = array(), $cookieKey) { + $this->RememberMe->settings['cookieKey'] = $cookieKey; + $this->RememberMe->configureCookie($options); $this->RememberMe->setCookie($options); } diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php new file mode 100644 index 000000000..114a4fb6e --- /dev/null +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -0,0 +1,4 @@ + Date: Thu, 18 Oct 2012 00:38:22 +0200 Subject: [PATCH 0008/1476] Updating the copyright headers --- Config/Migration/001_initialize_users_schema.php | 2 +- Config/Migration/002_renaming.php | 2 +- Config/Migration/map.php | 2 +- Config/Schema/schema.php | 2 +- Controller/Component/RememberMeComponent.php | 12 ++++++++++++ Controller/UserDetailsController.php | 4 ++-- Controller/UsersAppController.php | 4 ++-- Controller/UsersController.php | 4 ++-- Model/User.php | 4 ++-- Model/UserDetail.php | 4 ++-- Model/UsersAppModel.php | 4 ++-- Test/Case/Controller/UserDetailsControllerTest.php | 4 ++-- Test/Case/Controller/UsersControllerTest.php | 4 ++-- Test/Case/Model/UserDetailTest.php | 4 ++-- Test/Case/Model/UserTest.php | 4 ++-- Test/Fixture/UserDetailFixture.php | 4 ++-- Test/Fixture/UserFixture.php | 4 ++-- View/Elements/pagination.ctp | 4 ++-- View/Emails/text/account_verification.ctp | 4 ++-- View/Emails/text/new_password.ctp | 4 ++-- View/Emails/text/password_reset_request.ctp | 4 ++-- View/UserDetails/add.ctp | 4 ++-- View/UserDetails/admin_add.ctp | 4 ++-- View/UserDetails/admin_edit.ctp | 4 ++-- View/UserDetails/admin_index.ctp | 4 ++-- View/UserDetails/admin_view.ctp | 4 ++-- View/UserDetails/edit.ctp | 4 ++-- View/UserDetails/index.ctp | 4 ++-- View/UserDetails/view.ctp | 4 ++-- View/Users/add.ctp | 4 ++-- View/Users/admin_add.ctp | 4 ++-- View/Users/admin_edit.ctp | 4 ++-- View/Users/admin_index.ctp | 4 ++-- View/Users/admin_view.ctp | 4 ++-- View/Users/change_password.ctp | 4 ++-- View/Users/dashboard.ctp | 4 ++-- View/Users/edit.ctp | 4 ++-- View/Users/index.ctp | 4 ++-- View/Users/login.ctp | 4 ++-- View/Users/request_password_change.ctp | 4 ++-- View/Users/search.ctp | 4 ++-- View/Users/view.ctp | 4 ++-- 42 files changed, 90 insertions(+), 78 deletions(-) diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php index 643d44a9d..612c7fbe0 100644 --- a/Config/Migration/001_initialize_users_schema.php +++ b/Config/Migration/001_initialize_users_schema.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2012, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Config/Migration/002_renaming.php b/Config/Migration/002_renaming.php index cd39be85e..a975b078c 100644 --- a/Config/Migration/002_renaming.php +++ b/Config/Migration/002_renaming.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2012, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Config/Migration/map.php b/Config/Migration/map.php index 4ebb86efd..2881b9c44 100644 --- a/Config/Migration/map.php +++ b/Config/Migration/map.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2012, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php index 6736df080..a58c54e8f 100644 --- a/Config/Schema/schema.php +++ b/Config/Schema/schema.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2012, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 863a7dbab..078c2068a 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -1,4 +1,16 @@ diff --git a/View/Emails/text/account_verification.ctp b/View/Emails/text/account_verification.ctp index 057d6d62e..15135681b 100644 --- a/View/Emails/text/account_verification.ctp +++ b/View/Emails/text/account_verification.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_add.ctp b/View/UserDetails/admin_add.ctp index cda182e8a..fc5577fee 100644 --- a/View/UserDetails/admin_add.ctp +++ b/View/UserDetails/admin_add.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_edit.ctp b/View/UserDetails/admin_edit.ctp index 29df7c009..dc83e7d26 100644 --- a/View/UserDetails/admin_edit.ctp +++ b/View/UserDetails/admin_edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_index.ctp b/View/UserDetails/admin_index.ctp index a4f04f30b..0434adf68 100644 --- a/View/UserDetails/admin_index.ctp +++ b/View/UserDetails/admin_index.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_view.ctp b/View/UserDetails/admin_view.ctp index f7c26d43f..35a900cc4 100644 --- a/View/UserDetails/admin_view.ctp +++ b/View/UserDetails/admin_view.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/edit.ctp b/View/UserDetails/edit.ctp index c9e9dea81..eb1559d89 100644 --- a/View/UserDetails/edit.ctp +++ b/View/UserDetails/edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/index.ctp b/View/UserDetails/index.ctp index f2ad92870..9c0c563a4 100644 --- a/View/UserDetails/index.ctp +++ b/View/UserDetails/index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/add.ctp b/View/Users/add.ctp index e85fbd86d..8a329ef9b 100644 --- a/View/Users/add.ctp +++ b/View/Users/add.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_add.ctp b/View/Users/admin_add.ctp index 37b523324..95d194160 100644 --- a/View/Users/admin_add.ctp +++ b/View/Users/admin_add.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_edit.ctp b/View/Users/admin_edit.ctp index 569466f91..9d5214b5f 100644 --- a/View/Users/admin_edit.ctp +++ b/View/Users/admin_edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index 4039e6e75..b3fb92649 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_view.ctp b/View/Users/admin_view.ctp index 6c98bce43..629591fbe 100644 --- a/View/Users/admin_view.ctp +++ b/View/Users/admin_view.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/change_password.ctp b/View/Users/change_password.ctp index 187d7a796..08660ad39 100644 --- a/View/Users/change_password.ctp +++ b/View/Users/change_password.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/dashboard.ctp b/View/Users/dashboard.ctp index 29b1c2819..54c915137 100644 --- a/View/Users/dashboard.ctp +++ b/View/Users/dashboard.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/edit.ctp b/View/Users/edit.ctp index 912b4e355..134539fb4 100644 --- a/View/Users/edit.ctp +++ b/View/Users/edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/index.ctp b/View/Users/index.ctp index 84a00b8fd..58e7ff085 100644 --- a/View/Users/index.ctp +++ b/View/Users/index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/login.ctp b/View/Users/login.ctp index 46c642502..ef12db24b 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/request_password_change.ctp b/View/Users/request_password_change.ctp index 54d989701..9b80201ca 100644 --- a/View/Users/request_password_change.ctp +++ b/View/Users/request_password_change.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/search.ctp b/View/Users/search.ctp index 019fc1714..11f7ffb69 100644 --- a/View/Users/search.ctp +++ b/View/Users/search.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/view.ctp b/View/Users/view.ctp index 4b1a98f18..991f1ed79 100644 --- a/View/Users/view.ctp +++ b/View/Users/view.ctp @@ -1,11 +1,11 @@ From e8e8b92efcf7e7045680d59e88c665718859d740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 18 Oct 2012 23:01:33 +0200 Subject: [PATCH 0009/1476] Adding tests for the new RememberMeComponent --- Controller/Component/RememberMeComponent.php | 26 +++-- .../Component/RememberMeComponentTest.php | 110 ++++++++++++++++++ 2 files changed, 127 insertions(+), 9 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 078c2068a..bf98d7c42 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -56,9 +56,7 @@ class RememberMeComponent extends Component { 'fields' => array( 'email', 'username', - 'password', - ), - ); + 'password')); /** * Constructor @@ -73,7 +71,7 @@ public function __construct(ComponentCollection $collection, $settings = array() } /** - * + * startup * * @param Controller $controller * @return void @@ -111,25 +109,35 @@ public function restoreLoginFromCookie() { /** * Sets the cookie with the specified fields * - * @param options + * @param array Optional, login credentials array in the form of Model.field, if empty this->request[''] will be used * @return void */ - public function setCookie() { + public function setCookie($data = array()) { extract($this->settings); + if (empty($data)) { + $data = $this->request->data; + } + $cookieData = array(); + foreach ($fields as $field) { - if (isset($this->request->data[$userModel][$field]) && !empty($this->request->data[$userModel][$field])) { - $cookieData[$field] = $this->request->data[$userModel][$field]; + if (isset($data[$userModel][$field]) && !empty($data[$userModel][$field])) { + $cookieData[$field] = $data[$userModel][$field]; } } $this->Cookie->write($cookieKey, $cookieData, true); } +/** + * Destroys the remember me cookie + * + * @return void + */ public function destroyCookie() { extract($this->settings); - $this->Cookie->destroy(); + $this->Cookie->destroy($cookie['name']); } /** diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php index 114a4fb6e..b95c79058 100644 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -1,4 +1,114 @@ Controller = new RememberMeComponentTestController(new CakeRequest(), new CakeResponse()); + $this->Controller->constructClasses(); + + $this->RememberMe = $this->Controller->RememberMe; + $this->RememberMe->Cookie = $this->getMock('CookieComponent', + array(), + array($this->Controller->Components)); + $this->RememberMe->Auth = $this->getMock('AuthComponent', + array(), + array($this->Controller->Components)); + } + +/** + * testSetCookie + * + * @return void + */ + public function testSetCookie() { + $this->RememberMe->Cookie->expects($this->once()) + ->method('write') + ->with('rememberMe', array( + 'email' => 'email', + 'password' => 'password'), true); + + $this->RememberMe->setCookie(array( + 'User' => array( + 'email' => 'email', + 'password' => 'password'))); + } + +/** + * testRestoreLoginFromCookie + * + * @return void + */ + public function testRestoreLoginFromCookie() { + $this->RememberMe->Cookie->expects($this->once()) + ->method('read') + ->with($this->equalTo('rememberMe')) + ->will($this->returnValue(array( + 'email' => 'email', + 'password' => 'password'))); + + $this->RememberMe->Auth->expects($this->once()) + ->method('login'); + + $this->RememberMe->restoreLoginFromCookie(); + + $this->assertEqual($this->RememberMe->request->data, array( + 'User' => array( + 'email' => 'email', + 'password' => 'password'))); + } + +/** + * testDestroyCookie + * + * @return void + */ + public function testDestroyCookie() { + $this->RememberMe->Cookie->expects($this->once()) + ->method('destroy') + ->with($this->equalTo('Users')); + $this->RememberMe->destroyCookie(); + } + } \ No newline at end of file From b44a4a72fcbc041bccdcf512ab00d72067062892 Mon Sep 17 00:00:00 2001 From: J Miller Date: Mon, 22 Oct 2012 00:59:42 -0700 Subject: [PATCH 0010/1476] Dispatch Users.afterLogin event Allows your application to listen for this event and perform actions after a user logs in. Passes the boolean isFirstLogin, so you can perform unique actions only on the first time a user logs in. http://book.cakephp.org/2.0/en/core-libraries/events.html --- Controller/UsersController.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 1b6af2248..083706f89 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -349,6 +349,10 @@ public function add() { public function login() { if ($this->request->is('post')) { if ($this->Auth->login()) { + $this->getEventManager()->dispatch(new CakeEvent('Users.afterLogin', $this, array( + 'isFirstLogin' => !$this->Auth->user('last_login') + ))); + $this->User->id = $this->Auth->user('id'); $this->User->saveField('last_login', date('Y-m-d H:i:s')); From 2be3d890348d80410ed91e9540ae417d97ea0ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 22 Oct 2012 23:42:50 +0200 Subject: [PATCH 0011/1476] Fixing coding standards, commas vs tabs --- Test/Case/Controller/UsersControllerTest.php | 178 +++++++++---------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 293f05fac..6434a93a8 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -64,7 +64,7 @@ public function beforeFilter() { * Public interface to _setCookie */ public function setCookie($options = array()) { - parent::_setCookie($options); + parent::_setCookie($options); } /** @@ -205,20 +205,20 @@ public function startTest() { $this->Users->CakeEmail = $this->getMock('CakeEmail'); $this->Users->CakeEmail->expects($this->any()) - ->method('to') - ->will($this->returnSelf()); + ->method('to') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('from') - ->will($this->returnSelf()); + ->method('from') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('subject') - ->will($this->returnSelf()); + ->method('subject') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('template') - ->will($this->returnSelf()); + ->method('template') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('viewVars') - ->will($this->returnSelf()); + ->method('viewVars') + ->will($this->returnSelf()); $this->Users->Components->disable('Security'); } @@ -243,28 +243,28 @@ public function testUserLogin() { $this->Users->request->url = '/users/users/login'; $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Auth = $this->getMock('AuthComponent', array('login', 'user', 'redirect'), array($this->Collection)); - $this->Users->Auth->expects($this->once()) - ->method('login') - ->will($this->returnValue(true)); - $this->Users->Auth->staticExpects($this->at(0)) - ->method('user') - ->with('id') - ->will($this->returnValue(1)); - $this->Users->Auth->staticExpects($this->at(1)) - ->method('user') - ->with('username') - ->will($this->returnValue('adminuser')); - $this->Users->Auth->expects($this->once()) - ->method('redirect') - ->with(null) - ->will($this->returnValue(Router::normalize('/'))); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Auth = $this->getMock('AuthComponent', array('login', 'user', 'redirect'), array($this->Collection)); + $this->Users->Auth->expects($this->once()) + ->method('login') + ->will($this->returnValue(true)); + $this->Users->Auth->staticExpects($this->at(0)) + ->method('user') + ->with('id') + ->will($this->returnValue(1)); + $this->Users->Auth->staticExpects($this->at(1)) + ->method('user') + ->with('username') + ->will($this->returnValue('adminuser')); + $this->Users->Auth->expects($this->once()) + ->method('redirect') + ->with(null) + ->will($this->returnValue(Router::normalize('/'))); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); $this->Users->Session->expects($this->any()) ->method('setFlash') ->with(__d('users', 'adminuser you have successfully logged in')); $this->Users->login(); - $this->assertEqual(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); + $this->assertEqual(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); } /** @@ -277,10 +277,10 @@ public function testUserLoginGet() { $this->__setGet(); $this->Users->login(); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->never()) - ->method('setFlash'); + $this->Collection = $this->getMock('ComponentCollection'); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Session->expects($this->never()) + ->method('setFlash'); } /** @@ -292,15 +292,15 @@ public function testFailedUserLogin() { $this->Users->request->params['action'] = 'login'; $this->__setPost(array('User' => $this->usersData['invalidUser'])); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Auth = $this->getMock('AuthComponent', array('flash', 'login'), array($this->Collection)); - $this->Users->Auth->expects($this->once()) - ->method('login') - ->will($this->returnValue(false)); - $this->Users->Auth->expects($this->once()) - ->method('flash') - ->with(__d('users', 'Invalid e-mail / password combination. Please try again')); - $this->Users->login(); + $this->Collection = $this->getMock('ComponentCollection'); + $this->Users->Auth = $this->getMock('AuthComponent', array('flash', 'login'), array($this->Collection)); + $this->Users->Auth->expects($this->once()) + ->method('login') + ->will($this->returnValue(false)); + $this->Users->Auth->expects($this->once()) + ->method('flash') + ->with(__d('users', 'Invalid e-mail / password combination. Please try again')); + $this->Users->login(); } /** @@ -321,13 +321,13 @@ public function testAdd() { 'temppassword' => 'password', 'tos' => 1))); $this->Users->beforeFilter(); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login.')); + $this->Collection = $this->getMock('ComponentCollection'); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Session->expects($this->once()) + ->method('setFlash') + ->with(__d('users', 'Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login.')); - $this->Users->add(); + $this->Users->add(); $this->__setPost(array( 'User' => array( @@ -337,11 +337,11 @@ public function testAdd() { 'temppassword' => '', 'tos' => 0))); $this->Users->beforeFilter(); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Your account could not be created. Please, try again.')); - $this->Users->add(); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Session->expects($this->once()) + ->method('setFlash') + ->with(__d('users', 'Your account could not be created. Please, try again.')); + $this->Users->add(); } /** @@ -353,21 +353,21 @@ public function testVerify() { $this->Users->beforeFilter(); $this->Users->User->id = '37ea303a-3bdc-4251-b315-1316c0b300fa'; $this->Users->User->saveField('email_token_expires', date('Y-m-d H:i:s', strtotime('+1 year'))); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Your e-mail has been validated!')); + $this->Collection = $this->getMock('ComponentCollection'); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Session->expects($this->once()) + ->method('setFlash') + ->with(__d('users', 'Your e-mail has been validated!')); - $this->Users->verify('email', 'testtoken2'); + $this->Users->verify('email', 'testtoken2'); $this->Users->beforeFilter(); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Invalid token, please check the email you were sent, and retry the verification link.')); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Session->expects($this->once()) + ->method('setFlash') + ->with(__d('users', 'Invalid token, please check the email you were sent, and retry the verification link.')); - $this->Users->verify('email', 'invalid-token');; + $this->Users->verify('email', 'invalid-token');; } /** @@ -378,21 +378,21 @@ public function testVerify() { public function testLogout() { $this->Users->beforeFilter(); $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Cookie = $this->getMock('CookieComponent', array('destroy'), array($this->Collection)); - $this->Users->Cookie->expects($this->once()) - ->method('destroy'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'testuser you have successfully logged out')); - $this->Users->Auth = $this->getMock('AuthComponent', array('logout', 'user'), array($this->Collection)); - $this->Users->Auth->expects($this->once()) - ->method('logout') - ->will($this->returnValue('/')); - $this->Users->Auth->staticExpects($this->at(0)) - ->method('user') - ->will($this->returnValue($this->usersData['validUser'])); - $this->Users->logout(); + $this->Users->Cookie = $this->getMock('CookieComponent', array('destroy'), array($this->Collection)); + $this->Users->Cookie->expects($this->once()) + ->method('destroy'); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Session->expects($this->once()) + ->method('setFlash') + ->with(__d('users', 'testuser you have successfully logged out')); + $this->Users->Auth = $this->getMock('AuthComponent', array('logout', 'user'), array($this->Collection)); + $this->Users->Auth->expects($this->once()) + ->method('logout') + ->will($this->returnValue('/')); + $this->Users->Auth->staticExpects($this->at(0)) + ->method('user') + ->will($this->returnValue($this->usersData['validUser'])); + $this->Users->logout(); $this->assertEqual($this->Users->redirectUrl, '/'); } @@ -537,21 +537,21 @@ public function testAdminDelete() { * @return void */ public function testSetCookie() { - $this->__setPost(array( - 'User' => array( - 'remember_me' => 1, - 'email' => 'testuser@cakedc.com', - 'username' => 'test', - 'password' => 'testtest') - )); + $this->__setPost(array( + 'User' => array( + 'remember_me' => 1, + 'email' => 'testuser@cakedc.com', + 'username' => 'test', + 'password' => 'testtest') + )); $this->Users->setCookie(array( 'name' => 'userTestCookie')); $this->Users->Cookie->name = 'userTestCookie'; $result = $this->Users->Cookie->read('User'); - $this->assertEqual($result, array( + $this->assertEqual($result, array( 'password' => 'testtest', - 'email' => 'testuser@cakedc.com', - )); + 'email' => 'testuser@cakedc.com', + )); } /** From 9db9da6c8bb9c38c8f4aa3ac825c9120e10a99f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 23 Oct 2012 00:07:40 +0200 Subject: [PATCH 0012/1476] Working on getting the UsersControllerTest to work with the RememberMeComponent changes --- Controller/Component/RememberMeComponent.php | 20 +++++++++------ Controller/UsersController.php | 8 +++--- .../Component/RememberMeComponentTest.php | 6 ++--- Test/Case/Controller/UsersControllerTest.php | 25 +++++++++++++------ 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index bf98d7c42..524c99c53 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -52,7 +52,7 @@ class RememberMeComponent extends Component { 'userModel' => 'User', 'cookieKey' => 'rememberMe', 'cookie' => array( - 'name' => 'Users'), + 'name' => 'User'), 'fields' => array( 'email', 'username', @@ -70,6 +70,17 @@ public function __construct(ComponentCollection $collection, $settings = array() $this->configureCookie($this->settings['cookie']); } +/** + * Initializes RememberMeComponent for use in the controller + * + * @param Controller $controller A reference to the instantiating controller object + * @return void + */ + public function initialize(Controller $controller) { + $this->request = $controller->request; + $this->Auth = $this->Controller->Auth; + } + /** * startup * @@ -77,11 +88,6 @@ public function __construct(ComponentCollection $collection, $settings = array() * @return void */ public function startup(Controller $controller) { - $this->Controller = $controller; - $this->request = $this->Controller->request; - $this->response = $this->Controller->response; - $this->Auth = $this->Controller->Auth; - if ($this->settings['autoLogin'] == true && !$this->Auth->loggedIn()) { $this->restoreLoginFromCookie(); } @@ -151,7 +157,7 @@ public function configureCookie($options = array()) { $validProperties = array('domain', 'key', 'name', 'path', 'secure', 'time'); $defaults = array( 'time' => '1 month', - 'name' => 'Users'); + 'name' => 'User'); $options = array_merge($defaults, $options); diff --git a/Controller/UsersController.php b/Controller/UsersController.php index f44246d8f..f5e254d22 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -654,16 +654,16 @@ protected function _sendPasswordReset($admin = null, $options = array()) { /** * Sets the cookie to remember the user * - * @param array Cookie component properties as array, like array('domain' => 'yourdomain.com') - * @param string $cookieKey + * @param array RememberMe (Cookie) component properties as array, like array('domain' => 'yourdomain.com') + * @param string Cookie data keyname for the userdata, its default is "User". This is set to User and NOT using the model alias to make sure it works with different apps with different user models across different (sub)domains. * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html * @deprecated Use the RememberMe Component */ - protected function _setCookie($options = array(), $cookieKey) { + protected function _setCookie($options = array(), $cookieKey = 'User') { $this->RememberMe->settings['cookieKey'] = $cookieKey; $this->RememberMe->configureCookie($options); - $this->RememberMe->setCookie($options); + $this->RememberMe->setCookie(); } /** diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php index b95c79058..73ef1176f 100644 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -66,8 +66,8 @@ public function testSetCookie() { $this->RememberMe->Cookie->expects($this->once()) ->method('write') ->with('rememberMe', array( - 'email' => 'email', - 'password' => 'password'), true); + 'email' => 'email', + 'password' => 'password'), true); $this->RememberMe->setCookie(array( 'User' => array( @@ -107,7 +107,7 @@ public function testRestoreLoginFromCookie() { public function testDestroyCookie() { $this->RememberMe->Cookie->expects($this->once()) ->method('destroy') - ->with($this->equalTo('Users')); + ->with($this->equalTo('User')); $this->RememberMe->destroyCookie(); } diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 6434a93a8..36bdf7812 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -14,6 +14,7 @@ App::uses('AuthComponent', 'Controller/Component'); App::uses('CookieComponent', 'Controller/Component'); App::uses('SessionComponent', 'Controller/Component'); +App::uses('RememberMeComponent', 'Users.Controller/Component'); App::uses('Security', 'Utility'); app::uses('CakeEmail', 'Network/Email'); @@ -263,6 +264,10 @@ public function testUserLogin() { $this->Users->Session->expects($this->any()) ->method('setFlash') ->with(__d('users', 'adminuser you have successfully logged in')); + $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); + $this->Users->RememberMe->expects($this->any()) + ->method('destroyCookie'); + $this->Users->login(); $this->assertEqual(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); } @@ -392,6 +397,10 @@ public function testLogout() { $this->Users->Auth->staticExpects($this->at(0)) ->method('user') ->will($this->returnValue($this->usersData['validUser'])); + $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); + $this->Users->RememberMe->expects($this->any()) + ->method('destroyCookie'); + $this->Users->logout(); $this->assertEqual($this->Users->redirectUrl, '/'); } @@ -542,18 +551,19 @@ public function testSetCookie() { 'remember_me' => 1, 'email' => 'testuser@cakedc.com', 'username' => 'test', - 'password' => 'testtest') - )); + 'password' => 'testtest'))); + $this->Users->setCookie(array( 'name' => 'userTestCookie')); - $this->Users->Cookie->name = 'userTestCookie'; - $result = $this->Users->Cookie->read('User'); + + $this->Users->RememberMe->Cookie->name = 'userTestCookie'; + $result = $this->Users->RememberMe->Cookie->read('User'); + $this->assertEqual($result, array( 'password' => 'testtest', - 'email' => 'testuser@cakedc.com', - )); + 'email' => 'testuser@cakedc.com')); } - + /** * Test getting default and setted email instance config * @@ -570,7 +580,6 @@ public function testGetMailInstance() { $this->setExpectedException('ConfigureException'); Configure::write('Users.emailConfig', 'doesnotexist'); $anotherConfig = $this->Users->getMailInstance()->config(); - } /** From 10b3788419654685e22beddbd87c3dcb7f866b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 23 Oct 2012 00:32:13 +0200 Subject: [PATCH 0013/1476] Fixing the UsersControllerTest::testSetCookie case to reflect and test the changes related to the cookie component --- Test/Case/Controller/UsersControllerTest.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 36bdf7812..6e2954239 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -553,15 +553,18 @@ public function testSetCookie() { 'username' => 'test', 'password' => 'testtest'))); + $this->Collection = $this->getMock('ComponentCollection'); + $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); + $this->Users->RememberMe->expects($this->once()) + ->method('configureCookie') + ->with(array('name' => 'userTestCookie')); + $this->Users->RememberMe->expects($this->once()) + ->method('setCookie'); + $this->Users->setCookie(array( 'name' => 'userTestCookie')); - $this->Users->RememberMe->Cookie->name = 'userTestCookie'; - $result = $this->Users->RememberMe->Cookie->read('User'); - - $this->assertEqual($result, array( - 'password' => 'testtest', - 'email' => 'testuser@cakedc.com')); + $this->assertEqual($this->Users->RememberMe->settings['cookieKey'], 'User'); } /** From dcf41f6f2e1dc1fad2bca6b5a97fee2599bf224b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 29 Oct 2012 17:00:36 +0000 Subject: [PATCH 0014/1476] fixing remember me reference to Auth component --- Controller/Component/RememberMeComponent.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 524c99c53..3a182ba4e 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -78,7 +78,7 @@ public function __construct(ComponentCollection $collection, $settings = array() */ public function initialize(Controller $controller) { $this->request = $controller->request; - $this->Auth = $this->Controller->Auth; + $this->Auth = $controller->Auth; } /** @@ -169,4 +169,4 @@ public function configureCookie($options = array()) { } } } -} \ No newline at end of file +} From abc6bd8452d924ab13f48728755c0213fddd0bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 28 Nov 2012 10:57:55 +0100 Subject: [PATCH 0015/1476] Changing some code back to work with 2.x versions before 2.2. https://github.com/CakeDC/users/issues/87 --- Controller/UsersController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 28b74e556..5d6a72cf3 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -220,8 +220,8 @@ public function edit() { */ public function admin_index() { $this->Prg->commonProcess(); - $this->User->validator()->remove('username'); - $this->User->validator()->remove('email'); + unset($this->User->validate['username']); + unset($this->User->validate['email']); $this->{$this->modelClass}->data[$this->modelClass] = $this->passedArgs; if ($this->{$this->modelClass}->Behaviors->attached('Searchable')) { $parsedConditions = $this->{$this->modelClass}->parseCriteria($this->passedArgs); From 1c8fcf022011eb88c918b9e6755cd076f2516147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 29 Nov 2012 12:08:17 +0100 Subject: [PATCH 0016/1476] More fixes related to the RememberMeComponent --- Controller/Component/RememberMeComponent.php | 16 ++++++++++++---- Controller/UsersController.php | 5 ++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 524c99c53..94c2bade2 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -26,7 +26,8 @@ class RememberMeComponent extends Component { * @var array */ public $components = array( - 'Cookie'); + 'Cookie', + 'Auth'); /** * Request object @@ -78,7 +79,6 @@ public function __construct(ComponentCollection $collection, $settings = array() */ public function initialize(Controller $controller) { $this->request = $controller->request; - $this->Auth = $this->Controller->Auth; } /** @@ -100,6 +100,7 @@ public function startup(Controller $controller) { */ public function restoreLoginFromCookie() { extract($this->settings); + $cookie = $this->Cookie->read($cookieKey); if (!empty($cookie)) { @@ -116,13 +117,20 @@ public function restoreLoginFromCookie() { * Sets the cookie with the specified fields * * @param array Optional, login credentials array in the form of Model.field, if empty this->request[''] will be used - * @return void + * @return boolean */ public function setCookie($data = array()) { extract($this->settings); if (empty($data)) { $data = $this->request->data; + if (empty($data)) { + $data = $this->Auth->user(); + } + } + + if (empty($data)) { + return false; } $cookieData = array(); @@ -133,7 +141,7 @@ public function setCookie($data = array()) { } } - $this->Cookie->write($cookieKey, $cookieData, true); + return $this->Cookie->write($cookieKey, $cookieData, true, '+99 years'); } /** diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 5d6a72cf3..b07f71d1e 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -57,8 +57,7 @@ class UsersController extends UsersAppController { 'Paginator', 'Security', 'Search.Prg', - 'Users.RememberMe', - ); + 'Users.RememberMe'); /** * Preset vars @@ -664,7 +663,7 @@ protected function _sendPasswordReset($admin = null, $options = array()) { * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html * @deprecated Use the RememberMe Component */ - protected function _setCookie($options = array(), $cookieKey = 'User') { + protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { $this->RememberMe->settings['cookieKey'] = $cookieKey; $this->RememberMe->configureCookie($options); $this->RememberMe->setCookie(); From 824547dc40077ae559c0366670d3f42586deb14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Fri, 30 Nov 2012 00:53:02 +0100 Subject: [PATCH 0017/1476] Updating the readme.md with the new infos about how to use the "remember me" feature --- readme.md | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/readme.md b/readme.md index 624cd3176..d787be12c 100644 --- a/readme.md +++ b/readme.md @@ -37,21 +37,31 @@ The plugin itself is already capable of: The default password reset process requires the user to enter his email address, an email is sent to the user with a link and a token. When the user accesses the URL with the token he can enter a new password. -### Using the "remember me" cookie ### +### Using the "remember me" functionality ### -To use the "remember me" checkbox which sets a cookie on the login page you will need to put this code or method call in your AppController::beforeFilter() method. +To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. - public function restoreLoginFromCookie() { - $this->Cookie->name = 'Users'; - $cookie = $this->Cookie->read('rememberMe'); - if (!empty($cookie)) { - $this->request->data['User'][$this->Auth->fields['username']] = $cookie[$this->Auth->fields['username']]; - $this->request->data['User'][$this->Auth->fields['password']] = $cookie[$this->Auth->fields['password']]; - $this->Auth->login(); - } + public $components = array( + 'Users.RemembeMe'); + +If you are using another user model than 'User' you'll have to configure it: + + public $components = array( + 'Users.RemembeMe' => array( + 'userModel' => 'AppUser'); + +And add this line + + $this->RememberMe->restoreLoginFromCookie() + +to your controllers beforeFilter() callack + + public function beforeFilter() { + parent::beforeFilter(); + $this->RememberMe->restoreLoginFromCookie(); } -The code will read the login credentials from the cookie and log the user in based on that information. Do not forget to change the cookie name or fields to what you are using if you have changed them in your application! +The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. ## How to extend the plugin ## From ec1979dbf6d25e195b047b27d437e200e477feff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 2 Dec 2012 23:58:32 +0100 Subject: [PATCH 0018/1476] Changing RememberMe component to not always read the cookie --- Controller/Component/RememberMeComponent.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 94c2bade2..5fb56f046 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -96,11 +96,15 @@ public function startup(Controller $controller) { /** * Logs the user again in based on the cookie data * + * @param boolean $checkLoginStatus * @return boolean True on login success, false on failure */ - public function restoreLoginFromCookie() { - extract($this->settings); + public function restoreLoginFromCookie($checkLoginStatus = true) { + if ($checkLoginStatus && $this->Auth->loggedIn()) { + return true; + } + extract($this->settings); $cookie = $this->Cookie->read($cookieKey); if (!empty($cookie)) { @@ -109,7 +113,10 @@ public function restoreLoginFromCookie() { $this->request->data[$userModel][$field] = $cookie[$field]; } } - return $this->Auth->login(); + + $result = $this->Auth->login(); + unset($this->request->data[$userModel]); + return $result; } } From e3d8a400d43152a16a696c27b8e1e2d64b5e58b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 4 Dec 2012 21:44:45 +0100 Subject: [PATCH 0019/1476] Fixing coding standards --- Controller/Component/RememberMeComponent.php | 1 + Controller/UserDetailsController.php | 12 +-- Controller/UsersController.php | 19 +++-- Model/User.php | 83 +++++++++++--------- Model/UserDetail.php | 15 ++-- 5 files changed, 69 insertions(+), 61 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 5fb56f046..ec12b940b 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -20,6 +20,7 @@ * @property AuthComponent $Auth */ class RememberMeComponent extends Component { + /** * Components * diff --git a/Controller/UserDetailsController.php b/Controller/UserDetailsController.php index 1881fa1a4..93cb0fe07 100644 --- a/Controller/UserDetailsController.php +++ b/Controller/UserDetailsController.php @@ -39,13 +39,13 @@ class UserDetailsController extends UsersAppController { * @return void */ public function index() { - $user_details = $this->UserDetail->find('all', array( + $userDetails = $this->UserDetail->find('all', array( 'contain' => array(), 'conditions' => array( 'UserDetail.user_id' => $this->Auth->user('id'), 'UserDetail.field LIKE' => 'user.%'), 'order' => 'UserDetail.position DESC')); - $this->set('user_details', $user_details); + $this->set('user_details', $userDetails); } /** @@ -70,8 +70,8 @@ public function view($id = null) { public function add() { if (!empty($this->request->data)) { $userId = $this->Auth->user('id'); - foreach($this->request->data as $group => $options) { - foreach($options as $key => $value) { + foreach ($this->request->data as $group => $options) { + foreach ($options as $key => $value) { $field = $group . '.' . $key; $this->UserDetail->updateAll( array('Detail.value' => "'$value'"), @@ -102,8 +102,8 @@ public function edit($section = 'user') { } if (empty($this->request->data)) { - $detail = $this->UserDetail->getSection($this->Auth->user('id'), $section); - $this->request->data['UserDetail'] = $detail[$section]; + $detail = $this->UserDetail->getSection($this->Auth->user('id'), $section); + $this->request->data['UserDetail'] = $detail[$section]; } $this->set('section', $section); diff --git a/Controller/UsersController.php b/Controller/UsersController.php index b07f71d1e..f5ea57e42 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -88,7 +88,7 @@ public function __construct($request, $response) { * * @return void * @link https://github.com/CakeDC/search - */ + */ protected function _setupComponents() { if (App::import('Component', 'Search.Prg')) { $this->components[] = 'Search.Prg'; @@ -99,7 +99,7 @@ protected function _setupComponents() { * Setup helpers based on plugin availability * * @return void - */ + */ protected function _setupHelpers() { if (App::import('Helper', 'Goodies.Gravatar')) { $this->helpers[] = 'Goodies.Gravatar'; @@ -141,7 +141,7 @@ protected function _setupAuth() { 'fields' => array( 'username' => 'email', 'password' => 'password'), - 'userModel' => 'Users.User', + 'userModel' => 'Users.User', 'scope' => array( 'User.active' => 1, 'User.email_verified' => 1))); @@ -160,7 +160,7 @@ public function index() { $this->paginate = array( 'limit' => 12, 'conditions' => array( - $this->modelClass . '.active' => 1, + $this->modelClass . '.active' => 1, $this->modelClass . '.email_verified' => 1)); $this->set('users', $this->paginate($this->modelClass)); } @@ -205,7 +205,7 @@ public function edit() { } } else { $data = $this->User->UserDetail->getSection($this->Auth->user('id'), 'User'); - if (!isset($data['User'])){ + if (!isset($data['User'])) { $data['User'] = array(); } $this->request->data['UserDetail'] = $data['User']; @@ -391,6 +391,7 @@ public function login() { /** * Search - Requires the CakeDC Search plugin to work * + * @throws MissingPluginException * @return void * @link https://github.com/CakeDC/search */ @@ -472,6 +473,7 @@ public function verify($type = 'email', $token = null) { * This method will send a new password to the user * * @param string $token Token + * @throws NotFoundException * @return void */ public function request_new_password($token = null) { @@ -561,7 +563,8 @@ public function reset_password($token = null, $user = null) { * Sets a list of languages to the view which can be used in selects * * @deprecated No fallback provided, use the Utils plugin in your app directly - * @param string View variable name, default is languages + * @param string $viewVar View variable name, default is languages + * @throws MissingPluginException * @return void * @link https://github.com/CakeDC/utils */ @@ -589,7 +592,7 @@ protected function _sendVerificationEmail($userData, $options = array()) { 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Account verification'), 'template' => 'Users.account_verification', - 'layout'=> 'default'); + 'layout' => 'default'); $options = array_merge($defaults, $options); @@ -617,7 +620,7 @@ protected function _sendPasswordReset($admin = null, $options = array()) { 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Password Reset'), 'template' => 'Users.password_reset_request', - 'layout'=> 'default'); + 'layout' => 'default'); $options = array_merge($defaults, $options); diff --git a/Model/User.php b/Model/User.php index a255e2a27..1e2f13447 100644 --- a/Model/User.php +++ b/Model/User.php @@ -83,7 +83,7 @@ class User extends UsersAppModel { 'rule' => array('alphaNumeric'), 'message' => 'The username must be alphanumeric.'), 'unique_username' => array( - 'rule'=>array('isUnique', 'username'), + 'rule' => array('isUnique', 'username'), 'message' => 'This username is already in use.'), 'username_min' => array( 'rule' => array('minLength', '3'), @@ -246,7 +246,7 @@ public function afterFind($results, $primary = false) { * @param string $string String to hash * @param string $type Method to use (sha1/sha256/md5) * @param boolean $salt If true, automatically appends the application's salt - * value to $string (Security.salt) + * value to $string (Security.salt) * @return string Hash */ public function hash($string, $type = null, $salt = false) { @@ -287,6 +287,7 @@ public function confirmEmail($email = null) { * Verifies a users email by a token that was sent to him via email and flags the user record as active * * @param string $token The token that wa sent to the user + * @throws RuntimeException * @return array On success it returns the user data record */ public function verifyEmail($token = null) { @@ -402,7 +403,7 @@ public function passwordReset($postData = array()) { $user = $this->save($user, false); $this->data = $user; return $user; - } elseif (!empty($user) && $user[$this->alias]['email_verified'] == 0){ + } elseif (!empty($user) && $user[$this->alias]['email_verified'] == 0) { $this->invalidate('email', __d('users', 'This Email Address exists but was never validated.')); } else { $this->invalidate('email', __d('users', 'This Email Address does not exist in the system.')); @@ -444,7 +445,7 @@ public function resetPassword($postData = array()) { 'new_password' => $tmp['password'], 'confirm_password' => array( 'required' => array( - 'rule' => array('compareFields', 'new_password', 'confirm_password'), + 'rule' => array('compareFields', 'new_password', 'confirm_password'), 'message' => __d('users', 'The passwords are not equal.')))); $this->set($postData); @@ -483,7 +484,8 @@ public function changePassword($postData = array()) { /** * Validation method to check the old password * - * @param array $password + * @param array $password + * @throws OutOfBoundsException * @return boolean True on success */ public function validateOldPassword($password) { @@ -508,7 +510,8 @@ public function compareFields($field1, $field2) { if (is_array($field1)) { $field1 = key($field1); } - if (isset($this->data[$this->alias][$field1]) && isset($this->data[$this->alias][$field2]) && + + if (isset($this->data[$this->alias][$field1]) && isset($this->data[$this->alias][$field2]) && $this->data[$this->alias][$field1] == $this->data[$this->alias][$field2]) { return true; } @@ -519,6 +522,7 @@ public function compareFields($field1, $field2) { * Returns all data about a user * * @param string $slug user slug or the uuid of a user + * @throws OutOfBoundsException * @return array */ public function view($slug = null) { @@ -673,14 +677,14 @@ protected function _beforeRegistration($postData = array(), $useEmailVerificatio } else { $postData[$this->alias]['email_verified'] = 1; } - $postData[$this->alias]['active'] = 1; - $defaultRole = Configure::read('Users.defaultRole'); - if ($defaultRole) { - $postData[$this->alias]['role'] = $defaultRole; - } else { - $postData[$this->alias]['role'] = 'registered'; - } - return $postData; + $postData[$this->alias]['active'] = 1; + $defaultRole = Configure::read('Users.defaultRole'); + if ($defaultRole) { + $postData[$this->alias]['role'] = $defaultRole; + } else { + $postData[$this->alias]['role'] = 'registered'; + } + return $postData; } /** @@ -688,7 +692,8 @@ protected function _beforeRegistration($postData = array(), $useEmailVerificatio * * @param string $state Find State * @param string $query Query options - * @param string $results Result data + * @param array|string $results Result data + * @throws MissingPluginException * @return array * @link https://github.com/CakeDC/search */ @@ -767,7 +772,7 @@ protected function _findSearch($state, $query, $results = array()) { * @param array $extra Extra options * @return array */ - function paginateCount($conditions = array(), $recursive = 0, $extra = array()) { + public function paginateCount($conditions = array(), $recursive = 0, $extra = array()) { $parameters = compact('conditions'); if ($recursive != $this->recursive) { $parameters['recursive'] = $recursive; @@ -788,29 +793,29 @@ function paginateCount($conditions = array(), $recursive = 0, $extra = array()) */ public function add($postData = null) { if (!empty($postData)) { - $this->data = $postData; - if ($this->validates()) { - if (empty($postData[$this->alias]['role'])) { - if (empty($postData[$this->alias]['is_admin'])) { - $defaultRole = Configure::read('Users.defaultRole'); - if ($defaultRole) { - $postData[$this->alias]['role'] = $defaultRole; - } else { - $postData[$this->alias]['role'] = 'registered'; - } - } else { - $postData[$this->alias]['role'] = 'admin'; - } - } - $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); - $this->create(); - $result = $this->save($postData, false); - if ($result) { - $result[$this->alias][$this->primaryKey] = $this->id; - $this->data = $result; - return true; - } - } + $this->data = $postData; + if ($this->validates()) { + if (empty($postData[$this->alias]['role'])) { + if (empty($postData[$this->alias]['is_admin'])) { + $defaultRole = Configure::read('Users.defaultRole'); + if ($defaultRole) { + $postData[$this->alias]['role'] = $defaultRole; + } else { + $postData[$this->alias]['role'] = 'registered'; + } + } else { + $postData[$this->alias]['role'] = 'admin'; + } + } + $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); + $this->create(); + $result = $this->save($postData, false); + if ($result) { + $result[$this->alias][$this->primaryKey] = $this->id; + $this->data = $result; + return true; + } + } } return false; } diff --git a/Model/UserDetail.php b/Model/UserDetail.php index f27ad0bbc..05a2e2871 100644 --- a/Model/UserDetail.php +++ b/Model/UserDetail.php @@ -147,7 +147,7 @@ public function getSection($userId = null, $section = null) { "{$this->alias}.user_id" => $userId); if (!is_null($section)) { - $conditions["{$this->alias}.field LIKE"] = $section . '.%'; + $conditions["{$this->alias}.field LIKE"] = $section . '.%'; } $results = $this->find('all', array( @@ -156,7 +156,7 @@ public function getSection($userId = null, $section = null) { 'fields' => array("{$this->alias}.field", "{$this->alias}.value"))); if (!empty($results)) { - foreach($results as $result) { + foreach ($results as $result) { list($prefix, $field) = explode('.', $result[$this->alias]['field']); $userDetails[$prefix][$field] = $result[$this->alias]['value']; } @@ -190,9 +190,9 @@ public function saveSection($userId = null, $data = null, $section = null) { if (!empty($this->sectionSchema[$section])) { $this->activeSectionSchema = $section; - foreach($data as $model => $userDetails) { + foreach ($data as $model => $userDetails) { if ($model == $this->alias) { - foreach($userDetails as $key => $value) { + foreach ($userDetails as $key => $value) { $data[$model][$key] = $this->deconstruct($key, $value); } } @@ -214,10 +214,10 @@ public function saveSection($userId = null, $data = null, $section = null) { } if (!empty($data) && is_array($data)) { - foreach($data as $model => $userDetails) { + foreach ($data as $model => $userDetails) { if ($model == $this->alias) { // Save the details - foreach($userDetails as $key => $value) { + foreach ($userDetails as $key => $value) { $newUserDetail = array(); $field = $section . '.' . $key; $userDetail = $this->find('first', array( @@ -256,5 +256,4 @@ public function saveSection($userId = null, $data = null, $section = null) { } return true; } -} -; \ No newline at end of file +} \ No newline at end of file From 38ce1965b79db323bdbb91c16673f32357b31a76 Mon Sep 17 00:00:00 2001 From: Callum Macdonald Date: Tue, 8 Jan 2013 17:52:14 +0700 Subject: [PATCH 0020/1476] Correct tos link The tos link was /users/pages/tos/ instead of /pages/tos/, adding `'plugin' => null` to the link array fixes. --- View/Users/add.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/View/Users/add.ctp b/View/Users/add.ctp index 8a329ef9b..87f393ecd 100644 --- a/View/Users/add.ctp +++ b/View/Users/add.ctp @@ -26,11 +26,11 @@ echo $this->Form->input('temppassword', array( 'label' => __d('users', 'Password (confirm)'), 'type' => 'password')); - $tosLink = $this->Html->link(__d('users', 'Terms of Service'), array('controller' => 'pages', 'action' => 'tos')); + $tosLink = $this->Html->link(__d('users', 'Terms of Service'), array('controller' => 'pages', 'action' => 'tos', 'plugin' => null)); echo $this->Form->input('tos', array( 'label' => __d('users', 'I have read and agreed to ') . $tosLink)); echo $this->Form->end(__d('users', 'Submit')); ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users/sidebar'); ?> From 0b6caad0cd80973a0d218de0a8bc8b0912ecc552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 14 Jan 2013 11:11:51 +0100 Subject: [PATCH 0021/1476] Fixing notices coming up from the cookie component when calling RememberMe::destroy --- Controller/Component/RememberMeComponent.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index ec12b940b..baff22f95 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -159,7 +159,10 @@ public function setCookie($data = array()) { */ public function destroyCookie() { extract($this->settings); - $this->Cookie->destroy($cookie['name']); + if (isset($_COOKIE[$cookie['name']])) { + $this->Cookie->name = $cookie['name']; + $this->Cookie->destroy(); + } } /** From b556f2989ee772d60ff4e21b3177eb564ee4adeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 15 Jan 2013 17:20:53 +0100 Subject: [PATCH 0022/1476] Fixing unit tests --- Test/Case/AllUsersPluginTest.php | 11 +++++++++++ Test/Case/Controller/UsersControllerTest.php | 12 ++++++++---- Test/Case/Model/UserTest.php | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Test/Case/AllUsersPluginTest.php b/Test/Case/AllUsersPluginTest.php index fd51ab258..fbb56d448 100644 --- a/Test/Case/AllUsersPluginTest.php +++ b/Test/Case/AllUsersPluginTest.php @@ -1,4 +1,14 @@ addTestFile($basePath . 'Controller' . DS . 'UserDetailsControllerTest.php'); $suite->addTestFile($basePath . 'Controller' . DS . 'UsersControllerTest.php'); diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 6e2954239..02e44b613 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -250,9 +250,13 @@ public function testUserLogin() { ->will($this->returnValue(true)); $this->Users->Auth->staticExpects($this->at(0)) ->method('user') - ->with('id') + ->with('last_login') ->will($this->returnValue(1)); $this->Users->Auth->staticExpects($this->at(1)) + ->method('user') + ->with('id') + ->will($this->returnValue(1)); + $this->Users->Auth->staticExpects($this->at(2)) ->method('user') ->with('username') ->will($this->returnValue('adminuser')); @@ -262,8 +266,8 @@ public function testUserLogin() { ->will($this->returnValue(Router::normalize('/'))); $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); $this->Users->Session->expects($this->any()) - ->method('setFlash') - ->with(__d('users', 'adminuser you have successfully logged in')); + ->method('setFlash') + ->with(__d('users', 'adminuser you have successfully logged in')); $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); $this->Users->RememberMe->expects($this->any()) ->method('destroyCookie'); @@ -564,7 +568,7 @@ public function testSetCookie() { $this->Users->setCookie(array( 'name' => 'userTestCookie')); - $this->assertEqual($this->Users->RememberMe->settings['cookieKey'], 'User'); + $this->assertEqual($this->Users->RememberMe->settings['cookieKey'], 'rememberMe'); } /** diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index 45f64f688..4250782be 100644 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -60,6 +60,7 @@ public function tearDown() { unset($this->User); ClassRegistry::flush(); } + /** * * From 46664ba89989541048cc6c2092a50f040983f66d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 15 Jan 2013 17:24:43 +0100 Subject: [PATCH 0023/1476] Improving the users controller to make user of $this->plugin for loading elements and models, less overriding should be needed now for some methods --- Controller/UsersController.php | 38 +++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index f5ea57e42..b96a2f057 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -33,6 +33,13 @@ class UsersController extends UsersAppController { */ public $name = 'Users'; +/** + * If the controller is a plugin controller set the plugin name + * + * @var mixed + */ + public $plugin = null; + /** * Helpers * @@ -83,6 +90,18 @@ public function __construct($request, $response) { parent::__construct($request, $response); } +/** + * Returns $this->plugin with a dot, used for plugin loading using the dot notation + * + * @return mixed string|null + */ + protected function _pluginDot() { + if (is_string($this->plugin)) { + return $this->plugin . '.'; + } + return $this->plugin; + } + /** * Setup components based on plugin availability * @@ -141,14 +160,14 @@ protected function _setupAuth() { 'fields' => array( 'username' => 'email', 'password' => 'password'), - 'userModel' => 'Users.User', + 'userModel' => $this->_pluginDot() . $this->modelClass, 'scope' => array( - 'User.active' => 1, - 'User.email_verified' => 1))); + $this->modelClass . '.active' => 1, + $this->modelClass . '.email_verified' => 1))); $this->Auth->loginRedirect = '/'; - $this->Auth->logoutRedirect = array('plugin' => 'users', 'controller' => 'users', 'action' => 'login'); - $this->Auth->loginAction = array('admin' => false, 'plugin' => 'users', 'controller' => 'users', 'action' => 'login'); + $this->Auth->logoutRedirect = array('plugin' => $this->plugin, 'controller' => 'users', 'action' => 'login'); + $this->Auth->loginAction = array('admin' => false, 'plugin' => $this->plugin, 'controller' => 'users', 'action' => 'login'); } /** @@ -351,8 +370,7 @@ public function login() { if ($this->request->is('post')) { if ($this->Auth->login()) { $this->getEventManager()->dispatch(new CakeEvent('Users.afterLogin', $this, array( - 'isFirstLogin' => !$this->Auth->user('last_login') - ))); + 'isFirstLogin' => !$this->Auth->user('last_login')))); $this->User->id = $this->Auth->user('id'); $this->User->saveField('last_login', date('Y-m-d H:i:s')); @@ -514,7 +532,7 @@ protected function _sendNewPassword($userData) { ->replyTo(Configure::read('App.defaultEmail')) ->return(Configure::read('App.defaultEmail')) ->subject(env('HTTP_HOST') . ' ' . __d('users', 'Password Reset')) - ->template('new_password') + ->template($this->_pluginDot() . 'new_password') ->viewVars(array( 'model' => $this->modelClass, 'userData' => $userData)) @@ -591,7 +609,7 @@ protected function _sendVerificationEmail($userData, $options = array()) { $defaults = array( 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Account verification'), - 'template' => 'Users.account_verification', + 'template' => $this->_pluginDot() . 'account_verification', 'layout' => 'default'); $options = array_merge($defaults, $options); @@ -619,7 +637,7 @@ protected function _sendPasswordReset($admin = null, $options = array()) { $defaults = array( 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Password Reset'), - 'template' => 'Users.password_reset_request', + 'template' => $this->_pluginDot() . 'password_reset_request', 'layout' => 'default'); $options = array_merge($defaults, $options); From 6ddc83501a2526e92e1f2c0456236a8136d1a83d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 15 Jan 2013 17:28:55 +0100 Subject: [PATCH 0024/1476] Updating the copyright year in doc blocks --- Config/Migration/001_initialize_users_schema.php | 2 +- Config/Migration/002_renaming.php | 2 +- Config/Migration/map.php | 2 +- Config/Schema/schema.php | 2 +- Controller/Component/RememberMeComponent.php | 4 ++-- Controller/UserDetailsController.php | 4 ++-- Controller/UsersAppController.php | 4 ++-- Controller/UsersController.php | 4 ++-- Model/User.php | 4 ++-- Model/UserDetail.php | 4 ++-- Model/UsersAppModel.php | 4 ++-- Test/Case/AllUsersPluginTest.php | 4 ++-- Test/Case/Controller/Component/RememberMeComponentTest.php | 4 ++-- Test/Case/Controller/UserDetailsControllerTest.php | 4 ++-- Test/Case/Controller/UsersControllerTest.php | 4 ++-- Test/Case/Model/UserDetailTest.php | 4 ++-- Test/Case/Model/UserTest.php | 4 ++-- Test/Fixture/UserDetailFixture.php | 4 ++-- Test/Fixture/UserFixture.php | 4 ++-- View/Elements/pagination.ctp | 4 ++-- View/Emails/text/account_verification.ctp | 4 ++-- View/Emails/text/new_password.ctp | 4 ++-- View/Emails/text/password_reset_request.ctp | 4 ++-- View/UserDetails/add.ctp | 4 ++-- View/UserDetails/admin_add.ctp | 4 ++-- View/UserDetails/admin_edit.ctp | 4 ++-- View/UserDetails/admin_index.ctp | 4 ++-- View/UserDetails/admin_view.ctp | 4 ++-- View/UserDetails/edit.ctp | 4 ++-- View/UserDetails/index.ctp | 4 ++-- View/UserDetails/view.ctp | 4 ++-- View/Users/add.ctp | 4 ++-- View/Users/admin_add.ctp | 4 ++-- View/Users/admin_edit.ctp | 4 ++-- View/Users/admin_index.ctp | 4 ++-- View/Users/admin_view.ctp | 4 ++-- View/Users/change_password.ctp | 4 ++-- View/Users/dashboard.ctp | 4 ++-- View/Users/edit.ctp | 4 ++-- View/Users/index.ctp | 4 ++-- View/Users/login.ctp | 4 ++-- View/Users/request_password_change.ctp | 4 ++-- View/Users/search.ctp | 4 ++-- View/Users/view.ctp | 4 ++-- 44 files changed, 84 insertions(+), 84 deletions(-) diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php index 612c7fbe0..8e2406413 100644 --- a/Config/Migration/001_initialize_users_schema.php +++ b/Config/Migration/001_initialize_users_schema.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2012, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Config/Migration/002_renaming.php b/Config/Migration/002_renaming.php index a975b078c..beabeec48 100644 --- a/Config/Migration/002_renaming.php +++ b/Config/Migration/002_renaming.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2012, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Config/Migration/map.php b/Config/Migration/map.php index 2881b9c44..c3d8d709f 100644 --- a/Config/Migration/map.php +++ b/Config/Migration/map.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2012, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php index a58c54e8f..fdccd1747 100644 --- a/Config/Schema/schema.php +++ b/Config/Schema/schema.php @@ -2,7 +2,7 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2012, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index baff22f95..0bbc93916 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -1,11 +1,11 @@ diff --git a/View/Emails/text/account_verification.ctp b/View/Emails/text/account_verification.ctp index 15135681b..611eb687d 100644 --- a/View/Emails/text/account_verification.ctp +++ b/View/Emails/text/account_verification.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_add.ctp b/View/UserDetails/admin_add.ctp index fc5577fee..064854c91 100644 --- a/View/UserDetails/admin_add.ctp +++ b/View/UserDetails/admin_add.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_edit.ctp b/View/UserDetails/admin_edit.ctp index dc83e7d26..ab19c6261 100644 --- a/View/UserDetails/admin_edit.ctp +++ b/View/UserDetails/admin_edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_index.ctp b/View/UserDetails/admin_index.ctp index 0434adf68..aa80adc7e 100644 --- a/View/UserDetails/admin_index.ctp +++ b/View/UserDetails/admin_index.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_view.ctp b/View/UserDetails/admin_view.ctp index 35a900cc4..1b919b94a 100644 --- a/View/UserDetails/admin_view.ctp +++ b/View/UserDetails/admin_view.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/edit.ctp b/View/UserDetails/edit.ctp index eb1559d89..949db3f57 100644 --- a/View/UserDetails/edit.ctp +++ b/View/UserDetails/edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/index.ctp b/View/UserDetails/index.ctp index 9c0c563a4..c2ee3cfce 100644 --- a/View/UserDetails/index.ctp +++ b/View/UserDetails/index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/add.ctp b/View/Users/add.ctp index 8a329ef9b..20065e71b 100644 --- a/View/Users/add.ctp +++ b/View/Users/add.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_add.ctp b/View/Users/admin_add.ctp index 95d194160..c1f9e623f 100644 --- a/View/Users/admin_add.ctp +++ b/View/Users/admin_add.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_edit.ctp b/View/Users/admin_edit.ctp index 9d5214b5f..270139c6f 100644 --- a/View/Users/admin_edit.ctp +++ b/View/Users/admin_edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index b3fb92649..bc534a510 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_view.ctp b/View/Users/admin_view.ctp index 629591fbe..dcacbdf44 100644 --- a/View/Users/admin_view.ctp +++ b/View/Users/admin_view.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/change_password.ctp b/View/Users/change_password.ctp index 08660ad39..bc4530440 100644 --- a/View/Users/change_password.ctp +++ b/View/Users/change_password.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/dashboard.ctp b/View/Users/dashboard.ctp index 54c915137..f510421a6 100644 --- a/View/Users/dashboard.ctp +++ b/View/Users/dashboard.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/edit.ctp b/View/Users/edit.ctp index 134539fb4..699bad37c 100644 --- a/View/Users/edit.ctp +++ b/View/Users/edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/index.ctp b/View/Users/index.ctp index 58e7ff085..1dbbcbc2d 100644 --- a/View/Users/index.ctp +++ b/View/Users/index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/login.ctp b/View/Users/login.ctp index ef12db24b..e803fe2b9 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/request_password_change.ctp b/View/Users/request_password_change.ctp index 9b80201ca..5cf7b1ed7 100644 --- a/View/Users/request_password_change.ctp +++ b/View/Users/request_password_change.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/search.ctp b/View/Users/search.ctp index 11f7ffb69..b051e6d9b 100644 --- a/View/Users/search.ctp +++ b/View/Users/search.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/view.ctp b/View/Users/view.ctp index 991f1ed79..cc8edaf5d 100644 --- a/View/Users/view.ctp +++ b/View/Users/view.ctp @@ -1,11 +1,11 @@ From c50c6e5db3694c9743e49167dbc48aab71a4cd4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 16 Jan 2013 12:01:03 +0100 Subject: [PATCH 0025/1476] Fixing a case where the restoreFromCookie in the RememberMeComponent can cause wrong data in the request when the login via cookie failed. --- Controller/Component/RememberMeComponent.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 0bbc93916..41d84fb73 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -109,6 +109,8 @@ public function restoreLoginFromCookie($checkLoginStatus = true) { $cookie = $this->Cookie->read($cookieKey); if (!empty($cookie)) { + $request = $this->request->data; + foreach ($fields as $field) { if (!empty($cookie[$field])) { $this->request->data[$userModel][$field] = $cookie[$field]; @@ -116,7 +118,11 @@ public function restoreLoginFromCookie($checkLoginStatus = true) { } $result = $this->Auth->login(); - unset($this->request->data[$userModel]); + + if (!$result) { + $this->request->data = $request; + } + return $result; } } From 0a2831c219b9673aaebf605285085c4783bc1703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 20 Jan 2013 23:46:19 +0100 Subject: [PATCH 0026/1476] Providing backward compatibility to a fix that was just made recently to the core for users that want to upgrade the plugin but not the core, see http://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3550-inherited-controllers-get-wrong-property-names --- Controller/UsersController.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index e3266cbff..068623dd1 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -88,6 +88,23 @@ public function __construct($request, $response) { $this->_setupComponents(); $this->_setupHelpers(); parent::__construct($request, $response); + $this->_reInitControllerName(); + } + +/** + * Providing backward compatibility to a fix that was just made recently to the core + * for users that want to upgrade the plugin but not the core + * + * @link http://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3550-inherited-controllers-get-wrong-property-names + * @return void + */ + protected function _reInitControllerName() { + $name = substr(get_class($this), 0, -10); + if ($this->name === null) { + $this->name = $name; + } elseif ($name !== $this->name) { + $this->name = $name; + } } /** From 2d1050207256beebd6b12a563bac71728f423a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 21 Jan 2013 00:00:04 +0100 Subject: [PATCH 0027/1476] Changing $this->User to $this->{$this->modelClass} so that everything works fine when the controller gets inherited and the model class changes --- Controller/UsersController.php | 62 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 068623dd1..f4c1c31fe 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -207,7 +207,7 @@ public function index() { * @return void */ public function dashboard() { - $user = $this->User->read(null, $this->Auth->user('id')); + $user = $this->{$this->modelClass}->read(null, $this->Auth->user('id')); $this->set('user', $user); } @@ -219,7 +219,7 @@ public function dashboard() { */ public function view($slug = null) { try { - $this->set('user', $this->User->view($slug)); + $this->set('user', $this->{$this->modelClass}->view($slug)); } catch (Exception $e) { $this->Session->setFlash($e->getMessage()); $this->redirect('/'); @@ -234,17 +234,17 @@ public function view($slug = null) { */ public function edit() { if (!empty($this->request->data)) { - if ($this->User->UserDetail->saveSection($this->Auth->user('id'), $this->request->data, 'User')) { + if ($this->{$this->modelClass}->UserDetail->saveSection($this->Auth->user('id'), $this->request->data, 'User')) { $this->Session->setFlash(__d('users', 'Profile saved.')); } else { $this->Session->setFlash(__d('users', 'Could not save your profile.')); } } else { - $data = $this->User->UserDetail->getSection($this->Auth->user('id'), 'User'); - if (!isset($data['User'])) { - $data['User'] = array(); + $data = $this->{$this->modelClass}->UserDetail->getSection($this->Auth->user('id'), 'User'); + if (!isset($data[$this->modelClass])) { + $data[$this->modelClass] = array(); } - $this->request->data['UserDetail'] = $data['User']; + $this->request->data['UserDetail'] = $data[$this->modelClass]; } } @@ -255,8 +255,8 @@ public function edit() { */ public function admin_index() { $this->Prg->commonProcess(); - unset($this->User->validate['username']); - unset($this->User->validate['email']); + unset($this->{$this->modelClass}->validate['username']); + unset($this->{$this->modelClass}->validate['email']); $this->{$this->modelClass}->data[$this->modelClass] = $this->passedArgs; if ($this->{$this->modelClass}->Behaviors->attached('Searchable')) { $parsedConditions = $this->{$this->modelClass}->parseCriteria($this->passedArgs); @@ -281,7 +281,7 @@ public function admin_view($id = null) { $this->Session->setFlash(__d('users', 'Invalid User.')); $this->redirect(array('action' => 'index')); } - $this->set('user', $this->User->read(null, $id)); + $this->set('user', $this->{$this->modelClass}->read(null, $id)); } /** @@ -291,10 +291,10 @@ public function admin_view($id = null) { */ public function admin_add() { if (!empty($this->request->data)) { - $this->request->data['User']['tos'] = true; - $this->request->data['User']['email_verified'] = true; + $this->request->data[$this->modelClass]['tos'] = true; + $this->request->data[$this->modelClass]['email_verified'] = true; - if ($this->User->add($this->request->data)) { + if ($this->{$this->modelClass}->add($this->request->data)) { $this->Session->setFlash(__d('users', 'The User has been saved')); $this->redirect(array('action' => 'index')); } @@ -310,7 +310,7 @@ public function admin_add() { */ public function admin_edit($userId = null) { try { - $result = $this->User->edit($userId, $this->request->data); + $result = $this->{$this->modelClass}->edit($userId, $this->request->data); if ($result === true) { $this->Session->setFlash(__d('users', 'User saved')); $this->redirect(array('action' => 'index')); @@ -323,7 +323,7 @@ public function admin_edit($userId = null) { } if (empty($this->request->data)) { - $this->request->data = $this->User->read(null, $userId); + $this->request->data = $this->{$this->modelClass}->read(null, $userId); } $this->set('roles', Configure::read('Users.roles')); } @@ -335,7 +335,7 @@ public function admin_edit($userId = null) { * @return void */ public function admin_delete($userId = null) { - if ($this->User->delete($userId)) { + if ($this->{$this->modelClass}->delete($userId)) { $this->Session->setFlash(__d('users', 'User deleted')); } else { $this->Session->setFlash(__d('users', 'Invalid User')); @@ -365,9 +365,9 @@ public function add() { } if (!empty($this->request->data)) { - $user = $this->User->register($this->request->data); + $user = $this->{$this->modelClass}->register($this->request->data); if ($user !== false) { - $this->_sendVerificationEmail($this->User->data); + $this->_sendVerificationEmail($this->{$this->modelClass}->data); $this->Session->setFlash(__d('users', 'Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login.')); $this->redirect(array('action' => 'login')); } else { @@ -389,8 +389,8 @@ public function login() { $this->getEventManager()->dispatch(new CakeEvent('Users.afterLogin', $this, array( 'isFirstLogin' => !$this->Auth->user('last_login')))); - $this->User->id = $this->Auth->user('id'); - $this->User->saveField('last_login', date('Y-m-d H:i:s')); + $this->{$this->modelClass}->id = $this->Auth->user('id'); + $this->{$this->modelClass}->saveField('last_login', date('Y-m-d H:i:s')); if ($this->here == $this->Auth->loginRedirect) { $this->Auth->loginRedirect = '/'; @@ -495,7 +495,7 @@ public function verify($type = 'email', $token = null) { } try { - $this->User->verifyEmail($token); + $this->{$this->modelClass}->verifyEmail($token); $this->Session->setFlash(__d('users', 'Your e-mail has been validated!')); return $this->redirect(array('action' => 'login')); } catch (RuntimeException $e) { @@ -516,7 +516,7 @@ public function request_new_password($token = null) { throw new NotFoundException(); } - $data = $this->User->validateToken($token, true); + $data = $this->{$this->modelClass}->validateToken($token, true); if (!$data) { $this->Session->setFlash(__d('users', 'The url you accessed is not longer valid')); @@ -526,7 +526,7 @@ public function request_new_password($token = null) { $email = $data[$this->modelClass]['email']; unset($data[$this->modelClass]['email']); - if ($this->User->save($data, array('validate' => false))) { + if ($this->{$this->modelClass}->save($data, array('validate' => false))) { $this->_sendNewPassword($data); $this->Session->setFlash(__d('users', 'Your password was sent to your registered email account')); return $this->redirect(array('action' => 'login')); @@ -545,7 +545,7 @@ public function request_new_password($token = null) { protected function _sendNewPassword($userData) { $Email = $this->_getMailInstance(); $Email->from(Configure::read('App.defaultEmail')) - ->to($data[$this->modelClass]['email']) + ->to($userData[$this->modelClass]['email']) ->replyTo(Configure::read('App.defaultEmail')) ->return(Configure::read('App.defaultEmail')) ->subject(env('HTTP_HOST') . ' ' . __d('users', 'Password Reset')) @@ -553,7 +553,7 @@ protected function _sendNewPassword($userData) { ->viewVars(array( 'model' => $this->modelClass, 'userData' => $userData)) - ->send($content); + ->send(); } /** @@ -564,7 +564,7 @@ protected function _sendNewPassword($userData) { public function change_password() { if ($this->request->is('post')) { $this->request->data[$this->modelClass]['id'] = $this->Auth->user('id'); - if ($this->User->changePassword($this->request->data)) { + if ($this->{$this->modelClass}->changePassword($this->request->data)) { $this->Session->setFlash(__d('users', 'Password changed.')); $this->redirect('/'); } @@ -660,7 +660,7 @@ protected function _sendPasswordReset($admin = null, $options = array()) { $options = array_merge($defaults, $options); if (!empty($this->request->data)) { - $user = $this->User->passwordReset($this->request->data); + $user = $this->{$this->modelClass}->passwordReset($this->request->data); if (!empty($user)) { @@ -671,8 +671,8 @@ protected function _sendPasswordReset($admin = null, $options = array()) { ->template($options['template'], $options['layout']) ->viewVars(array( 'model' => $this->modelClass, - 'user' => $this->User->data, - 'token' => $this->User->data[$this->modelClass]['password_token'])) + 'user' => $this->{$this->modelClass}->data, + 'token' => $this->{$this->modelClass}->data[$this->modelClass]['password_token'])) ->send(); if ($admin) { @@ -714,13 +714,13 @@ protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { * @return void */ protected function _resetPassword($token) { - $user = $this->User->checkPasswordToken($token); + $user = $this->{$this->modelClass}->checkPasswordToken($token); if (empty($user)) { $this->Session->setFlash(__d('users', 'Invalid password reset token, try again.')); $this->redirect(array('action' => 'reset_password')); } - if (!empty($this->request->data) && $this->User->resetPassword(Set::merge($user, $this->request->data))) { + if (!empty($this->request->data) && $this->{$this->modelClass}->resetPassword(Set::merge($user, $this->request->data))) { $this->Session->setFlash(__d('users', 'Password changed, you can now login with your new password.')); $this->redirect($this->Auth->loginAction); } From b3f4271103db7607704f61031c220b9ca5152b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Fri, 1 Feb 2013 19:45:24 +0100 Subject: [PATCH 0028/1476] Fixing a php 5.4 strict notice, made the signature of UsersAppController::isAuthorized match the parent --- Controller/UsersAppController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Controller/UsersAppController.php b/Controller/UsersAppController.php index 16118af01..4d2dc1691 100644 --- a/Controller/UsersAppController.php +++ b/Controller/UsersAppController.php @@ -25,10 +25,11 @@ class UsersAppController extends AppController { * * This is called to see if a user (when logged in) is able to access an action * + * @param array $user * @return boolean True if allowed */ - public function isAuthorized() { - return parent::isAuthorized(); + public function isAuthorized($user) { + return parent::isAuthorized($user); } } From dd7c34b4902ecd378393e391b49e3c6a5026c949 Mon Sep 17 00:00:00 2001 From: dizyart Date: Sat, 2 Feb 2013 03:56:22 +0100 Subject: [PATCH 0029/1476] PHP5.4-strict inheritance in UsersControllerTestCase --- Test/Case/Controller/UsersControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 141076e00..f12200574 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -187,7 +187,7 @@ class UsersControllerTestCase extends CakeTestCase { * * @return void */ - public function startTest() { + public function startTest($method) { Configure::write('App.UserClass', null); $request = new CakeRequest(); @@ -597,7 +597,7 @@ private function __setGet() { * * @return void */ - public function endTest() { + public function endTest($method) { $this->Users->Session->destroy(); unset($this->Users); ClassRegistry::flush(); From 2ac27ed2e17ba2ccfca744f2bc20e7b9b18a8ba0 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 12 Feb 2013 23:58:05 +0400 Subject: [PATCH 0030/1476] Update license blocks. --- Config/Migration/001_initialize_users_schema.php | 4 ++-- Config/Migration/002_renaming.php | 4 ++-- Config/Migration/map.php | 4 ++-- Config/Schema/schema.php | 4 ++-- Controller/UserDetailsController.php | 4 ++-- Controller/UsersAppController.php | 4 ++-- Controller/UsersController.php | 4 ++-- Model/User.php | 7 +++---- Model/UserDetail.php | 4 ++-- Model/UsersAppModel.php | 4 ++-- Test/Case/Controller/UserDetailsControllerTest.php | 4 ++-- Test/Case/Controller/UsersControllerTest.php | 4 ++-- Test/Case/Model/UserDetailTest.php | 4 ++-- Test/Case/Model/UserTest.php | 4 ++-- Test/Fixture/UserDetailFixture.php | 4 ++-- Test/Fixture/UserFixture.php | 4 ++-- View/Elements/pagination.ctp | 4 ++-- View/Emails/text/account_verification.ctp | 4 ++-- View/Emails/text/new_password.ctp | 4 ++-- View/Emails/text/password_reset_request.ctp | 4 ++-- View/UserDetails/add.ctp | 4 ++-- View/UserDetails/admin_add.ctp | 4 ++-- View/UserDetails/admin_edit.ctp | 4 ++-- View/UserDetails/admin_index.ctp | 4 ++-- View/UserDetails/admin_view.ctp | 4 ++-- View/UserDetails/edit.ctp | 4 ++-- View/UserDetails/index.ctp | 4 ++-- View/UserDetails/view.ctp | 4 ++-- View/Users/add.ctp | 4 ++-- View/Users/admin_add.ctp | 4 ++-- View/Users/admin_edit.ctp | 4 ++-- View/Users/admin_index.ctp | 4 ++-- View/Users/admin_view.ctp | 4 ++-- View/Users/change_password.ctp | 4 ++-- View/Users/dashboard.ctp | 4 ++-- View/Users/edit.ctp | 4 ++-- View/Users/index.ctp | 4 ++-- View/Users/login.ctp | 4 ++-- View/Users/request_password_change.ctp | 4 ++-- View/Users/search.ctp | 4 ++-- View/Users/view.ctp | 4 ++-- license.txt | 2 +- 42 files changed, 84 insertions(+), 85 deletions(-) diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php index 8c6a7136e..3b1dc4f16 100644 --- a/Config/Migration/001_initialize_users_schema.php +++ b/Config/Migration/001_initialize_users_schema.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2011, Cake Development Corporation + * @Copyright 2010 - 2013, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.migrations * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Config/Migration/002_renaming.php b/Config/Migration/002_renaming.php index cd39be85e..d9874316b 100644 --- a/Config/Migration/002_renaming.php +++ b/Config/Migration/002_renaming.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2011, Cake Development Corporation + * @Copyright 2010 - 2013, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.migrations * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Config/Migration/map.php b/Config/Migration/map.php index 4ebb86efd..5d69f5f89 100644 --- a/Config/Migration/map.php +++ b/Config/Migration/map.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2011, Cake Development Corporation + * @Copyright 2010 - 2013, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.migrations * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php index 6736df080..6bbacbd0e 100644 --- a/Config/Schema/schema.php +++ b/Config/Schema/schema.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2011, Cake Development Corporation + * Copyright 2010 - 2013, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2011, Cake Development Corporation + * @Copyright 2010 - 2013, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.schema * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Controller/UserDetailsController.php b/Controller/UserDetailsController.php index 9dee9c783..50f7d6103 100644 --- a/Controller/UserDetailsController.php +++ b/Controller/UserDetailsController.php @@ -1,11 +1,11 @@ useDbConfig); + $db = ConnectionManager::getDataSource($this->useDbConfig); $by = $query['by']; $search = $query['search']; - $byQuoted = $db->value($search); $like = '%' . $query['search'] . '%'; switch ($by) { diff --git a/Model/UserDetail.php b/Model/UserDetail.php index 9ae7c9353..e12e7943c 100644 --- a/Model/UserDetail.php +++ b/Model/UserDetail.php @@ -1,11 +1,11 @@ diff --git a/View/Emails/text/account_verification.ctp b/View/Emails/text/account_verification.ctp index 057d6d62e..611eb687d 100644 --- a/View/Emails/text/account_verification.ctp +++ b/View/Emails/text/account_verification.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_add.ctp b/View/UserDetails/admin_add.ctp index cda182e8a..064854c91 100644 --- a/View/UserDetails/admin_add.ctp +++ b/View/UserDetails/admin_add.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_edit.ctp b/View/UserDetails/admin_edit.ctp index 29df7c009..ab19c6261 100644 --- a/View/UserDetails/admin_edit.ctp +++ b/View/UserDetails/admin_edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_index.ctp b/View/UserDetails/admin_index.ctp index a4f04f30b..aa80adc7e 100644 --- a/View/UserDetails/admin_index.ctp +++ b/View/UserDetails/admin_index.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/admin_view.ctp b/View/UserDetails/admin_view.ctp index f7c26d43f..1b919b94a 100644 --- a/View/UserDetails/admin_view.ctp +++ b/View/UserDetails/admin_view.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/edit.ctp b/View/UserDetails/edit.ctp index c9e9dea81..949db3f57 100644 --- a/View/UserDetails/edit.ctp +++ b/View/UserDetails/edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/UserDetails/index.ctp b/View/UserDetails/index.ctp index f2ad92870..c2ee3cfce 100644 --- a/View/UserDetails/index.ctp +++ b/View/UserDetails/index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/add.ctp b/View/Users/add.ctp index e85fbd86d..20065e71b 100644 --- a/View/Users/add.ctp +++ b/View/Users/add.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_add.ctp b/View/Users/admin_add.ctp index 37b523324..c1f9e623f 100644 --- a/View/Users/admin_add.ctp +++ b/View/Users/admin_add.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_edit.ctp b/View/Users/admin_edit.ctp index 569466f91..270139c6f 100644 --- a/View/Users/admin_edit.ctp +++ b/View/Users/admin_edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index 4039e6e75..bc534a510 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_view.ctp b/View/Users/admin_view.ctp index 6c98bce43..dcacbdf44 100644 --- a/View/Users/admin_view.ctp +++ b/View/Users/admin_view.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/change_password.ctp b/View/Users/change_password.ctp index 187d7a796..bc4530440 100644 --- a/View/Users/change_password.ctp +++ b/View/Users/change_password.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/dashboard.ctp b/View/Users/dashboard.ctp index 29b1c2819..f510421a6 100644 --- a/View/Users/dashboard.ctp +++ b/View/Users/dashboard.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/edit.ctp b/View/Users/edit.ctp index 912b4e355..699bad37c 100644 --- a/View/Users/edit.ctp +++ b/View/Users/edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/index.ctp b/View/Users/index.ctp index 84a00b8fd..1dbbcbc2d 100644 --- a/View/Users/index.ctp +++ b/View/Users/index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/login.ctp b/View/Users/login.ctp index 460e1255d..dbb1ddaef 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/request_password_change.ctp b/View/Users/request_password_change.ctp index 54d989701..5cf7b1ed7 100644 --- a/View/Users/request_password_change.ctp +++ b/View/Users/request_password_change.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/search.ctp b/View/Users/search.ctp index 019fc1714..b051e6d9b 100644 --- a/View/Users/search.ctp +++ b/View/Users/search.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/view.ctp b/View/Users/view.ctp index 4b1a98f18..cc8edaf5d 100644 --- a/View/Users/view.ctp +++ b/View/Users/view.ctp @@ -1,11 +1,11 @@ diff --git a/license.txt b/license.txt index 25e5ee24c..011c22241 100644 --- a/license.txt +++ b/license.txt @@ -1,6 +1,6 @@ The MIT License -Copyright 2009-2010 +Copyright 2009-2013 Cake Development Corporation 1785 E. Sahara Avenue, Suite 490-423 Las Vegas, Nevada 89104 From 4afd5d37d8412a79aa42cdb6897bdb09ce643a4c Mon Sep 17 00:00:00 2001 From: J Miller Date: Fri, 22 Feb 2013 21:58:01 -0800 Subject: [PATCH 0031/1476] Fix typo "RememberMe" not "RemembeMe" --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index d787be12c..a894fbcf9 100644 --- a/readme.md +++ b/readme.md @@ -42,12 +42,12 @@ The default password reset process requires the user to enter his email address, To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. public $components = array( - 'Users.RemembeMe'); + 'Users.RememberMe'); If you are using another user model than 'User' you'll have to configure it: public $components = array( - 'Users.RemembeMe' => array( + 'Users.RememberMe' => array( 'userModel' => 'AppUser'); And add this line From 944ecbd37f64e46241f9c0a20a380a9a480330f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 24 Feb 2013 23:42:11 +0100 Subject: [PATCH 0032/1476] Adding events, correcting the naming of an event, added documentation, fixed minor issues --- Controller/UsersController.php | 23 +++++++++++++++++------ Model/User.php | 26 +++++++++++++++++++++----- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index f4c1c31fe..7ab25e5b4 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -305,7 +305,7 @@ public function admin_add() { /** * Admin edit * - * @param string $id User ID + * @param null $userId * @return void */ public function admin_edit($userId = null) { @@ -367,6 +367,12 @@ public function add() { if (!empty($this->request->data)) { $user = $this->{$this->modelClass}->register($this->request->data); if ($user !== false) { + $Event = new CakeEvent('Users.UsersController.afterRegistration', $this, $this->request->data); + $this->getEventManager()->dispatch($Event); + if ($Event->isStopped()) { + $this->redirect(array('action' => 'login')); + } + $this->_sendVerificationEmail($this->{$this->modelClass}->data); $this->Session->setFlash(__d('users', 'Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login.')); $this->redirect(array('action' => 'login')); @@ -386,8 +392,9 @@ public function add() { public function login() { if ($this->request->is('post')) { if ($this->Auth->login()) { - $this->getEventManager()->dispatch(new CakeEvent('Users.afterLogin', $this, array( - 'isFirstLogin' => !$this->Auth->user('last_login')))); + $Event = new CakeEvent('Users.UsersController.afterLogin', $this, array( + 'isFirstLogin' => !$this->Auth->user('last_login'))); + $this->getEventManager()->dispatch($Event); $this->{$this->modelClass}->id = $this->Auth->user('id'); $this->{$this->modelClass}->saveField('last_login', date('Y-m-d H:i:s')); @@ -409,7 +416,12 @@ public function login() { $data['return_to'] = null; } - $this->redirect($this->Auth->redirect($data['return_to'])); + // Checking for 2.3 but keeping a fallback for older versions + if (method_exists($this->Auth, 'redirectUrl')) { + $this->redirect($this->Auth->redirectUrl($data['return_to'])); + } else { + $this->redirect($this->Auth->redirect($data['return_to'])); + } } else { $this->Auth->flash(__d('users', 'Invalid e-mail / password combination. Please try again')); } @@ -523,7 +535,6 @@ public function request_new_password($token = null) { return $this->redirect('/'); } - $email = $data[$this->modelClass]['email']; unset($data[$this->modelClass]['email']); if ($this->{$this->modelClass}->save($data, array('validate' => false))) { @@ -620,7 +631,7 @@ protected function _setLanguages($viewVar = 'languages') { * * @param string $to Receiver email address * @param array $options EmailComponent options - * @return boolean Success + * @return void */ protected function _sendVerificationEmail($userData, $options = array()) { $defaults = array( diff --git a/Model/User.php b/Model/User.php index 055adbad8..1cd3f8934 100644 --- a/Model/User.php +++ b/Model/User.php @@ -113,7 +113,7 @@ class User extends UsersAppModel { /** * Constructor * - * @param string $id ID + * @param bool|string $id ID * @param string $table Table * @param string $ds Datasource */ @@ -368,7 +368,7 @@ public function validateToken($token = null, $reset = false, $now = null) { /** * Updates the last activity field of a user * - * @param string $user User ID + * @param null $userId * @param string $field Default is "last_action", changing it allows you to use this method also for "last_login" for example * @return boolean True on success */ @@ -572,6 +572,12 @@ public function register($postData = array(), $options = array()) { $this->_removeExpiredRegistrations(); } + $Event = new CakeEvent('Users.User.beforeRegister', $this); + $this->getEventManager()->dispatch($Event); + if ($Event->isStopped()) { + return $Event->result; + } + $this->set($postData); if ($this->validates()) { $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); @@ -579,6 +585,11 @@ public function register($postData = array(), $options = array()) { $this->data = $this->save($postData, false); $this->data[$this->alias]['id'] = $this->id; if ($returnData) { + $Event = new CakeEvent('Users.User.afterRegister', $this, $this->request->data); + $this->getEventManager()->dispatch($Event); + if ($Event->isStopped()) { + return $Event->result; + } return $this->data; } return true; @@ -699,7 +710,7 @@ protected function _beforeRegistration($postData = array(), $useEmailVerificatio */ protected function _findSearch($state, $query, $results = array()) { if (!App::import('Lib', 'Utils.Languages')) { - throw new MissingPluginException(array('plugin' => 'Search')); + throw new MissingPluginException(array('plugin' => 'Utils')); } if ($state == 'before') { @@ -786,7 +797,10 @@ public function paginateCount($conditions = array(), $recursive = 0, $extra = ar } /** - * Adds a new user + * Adds a new user, to be called from admin like user roles or interfaces + * + * This method is not sending any email like the register() method, its simply + * adding a new user record and sets a default role. * * @param array post data, should be Controller->data * @return boolean True if the data was saved successfully. @@ -825,6 +839,7 @@ public function add($postData = null) { * * @param string $userId User ID * @param array $postData controller post data usually $this->data + * @throws NotFoundException * @return mixed True on successfully save else post data as array */ public function edit($userId = null, $postData = null) { @@ -835,7 +850,7 @@ public function edit($userId = null, $postData = null) { $this->set($user); if (empty($user)) { - throw new OutOfBoundsException(__d('users', 'Invalid User')); + throw new NotFoundException(__d('users', 'Invalid User')); } if (!empty($postData)) { @@ -862,4 +877,5 @@ protected function _removeExpiredRegistrations() { $this->alias . '.email_verified' => 0, $this->alias . '.email_token_expires <' => date('Y-m-d H:i:s'))); } + } From d3d48d22dc776ffa814c3fac85a0a69ea13c0eaf Mon Sep 17 00:00:00 2001 From: Callum Macdonald Date: Sun, 3 Mar 2013 21:27:01 +0700 Subject: [PATCH 0033/1476] Add the missing prev / next links A view element exists for prev / next links but was not included in the admin users view. --- View/Users/admin_index.ctp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index 4039e6e75..3f9c2f5e5 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -21,6 +21,7 @@ ?> element('paging'); ?> + element('pagination'); ?> @@ -62,5 +63,6 @@
Paginator->sort('username'); ?>
+ element('pagination'); ?> element('Users/admin_sidebar'); ?> From 76f4cc0881b6befb16001b10ab2314eb463df34d Mon Sep 17 00:00:00 2001 From: Paul Josephson Date: Sun, 10 Mar 2013 15:17:40 -0700 Subject: [PATCH 0034/1476] Update RememberMeComponent.php Adjusted SetCookie, cookie->write returns void not boolean --- Controller/Component/RememberMeComponent.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 41d84fb73..4336f8f46 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -155,7 +155,8 @@ public function setCookie($data = array()) { } } - return $this->Cookie->write($cookieKey, $cookieData, true, '+99 years'); + $this->Cookie->write($cookieKey, $cookieData, true, '+99 years'); + return true; } /** @@ -194,4 +195,4 @@ public function configureCookie($options = array()) { } } } -} \ No newline at end of file +} From fe8c3860543bd11b5216ca559cb32a047293a107 Mon Sep 17 00:00:00 2001 From: Paul Josephson Date: Sun, 10 Mar 2013 15:19:41 -0700 Subject: [PATCH 0035/1476] Update RememberMeComponent.php restoreLoginFromCookie needs to return a false on fail --- Controller/Component/RememberMeComponent.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 4336f8f46..81304b54d 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -125,6 +125,7 @@ public function restoreLoginFromCookie($checkLoginStatus = true) { return $result; } + return false; } /** @@ -195,4 +196,4 @@ public function configureCookie($options = array()) { } } } -} +} From 06c663668e7db1f5bbafe773f8f76e69b9e6ad2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 22 Apr 2013 13:40:19 +0100 Subject: [PATCH 0036/1476] destroying remember me cookie on password change for user, fixing tests --- Controller/UsersController.php | 2 + .../Component/RememberMeComponentTest.php | 69 ++++++++++++++++--- Test/Case/Controller/UsersControllerTest.php | 4 ++ 3 files changed, 65 insertions(+), 10 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index f4c1c31fe..fa3af63e2 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -566,6 +566,8 @@ public function change_password() { $this->request->data[$this->modelClass]['id'] = $this->Auth->user('id'); if ($this->{$this->modelClass}->changePassword($this->request->data)) { $this->Session->setFlash(__d('users', 'Password changed.')); + // we don't want to keep the cookie with the old password around + $this->RememberMe->destroyCookie(); $this->redirect('/'); } } diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php index d0c80d3a5..d45d003f5 100644 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -38,6 +38,18 @@ class RememberMeComponentTest extends CakeTestCase { */ public $Controller; +/** + * User data + * @var array + */ + public $usersData = array( + 'test' => array( + 'email' => 'test@cakedc.com', + 'password' => 'test'), + 'admin' => array( + 'email' => 'admin@cakedc.com', + 'password' => 'admin')); + /** * start * @@ -84,31 +96,68 @@ public function testRestoreLoginFromCookie() { $this->RememberMe->Cookie->expects($this->once()) ->method('read') ->with($this->equalTo('rememberMe')) - ->will($this->returnValue(array( - 'email' => 'email', - 'password' => 'password'))); + ->will($this->returnValue($this->usersData['admin'])); $this->RememberMe->Auth->expects($this->once()) - ->method('login'); - + ->method('login') + ->will($this->returnValue(true)); + + $this->__setPostData(array('User' => $this->usersData['test'])); + $this->RememberMe->restoreLoginFromCookie(); + // even if we post "test" user, we have a remember me cookie set and will priorize the cookie over the post + // NOTE we check if the user is logged in in the startup method of the Component $this->assertEqual($this->RememberMe->request->data, array( - 'User' => array( - 'email' => 'email', - 'password' => 'password'))); + 'User' => $this->usersData['admin'])); } +/** + * testRestoreLoginFromCookieIncorrectLogin + * + * We check the post request data is not modified when the cookie holds incorrect login credentials + * + * @return void + */ + public function testRestoreLoginFromCookieIncorrectLogin() { + // cookie will hold "admin" data, and post request will have "test" + $this->RememberMe->Cookie->expects($this->once()) + ->method('read') + ->with($this->equalTo('rememberMe')) + ->will($this->returnValue($this->usersData['admin'])); + + // admin will not login + $this->RememberMe->Auth->expects($this->once()) + ->method('login') + ->will($this->returnValue(false)); + + // post has "test" data + $this->__setPostData(array('User' => $this->usersData['test'])); + + $this->RememberMe->restoreLoginFromCookie(); + + $this->assertEqual($this->RememberMe->request->data, array( + 'User' => $this->usersData['test'])); + } + /** * testDestroyCookie * * @return void */ public function testDestroyCookie() { + $_COOKIE['User'] = 'defined'; $this->RememberMe->Cookie->expects($this->once()) - ->method('destroy') - ->with($this->equalTo('User')); + ->method('destroy'); $this->RememberMe->destroyCookie(); } +/** + * Set post data to the test controller + * @param type $data + */ + private function __setPostData($data = array()) { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $this->RememberMe->request->data = array_merge($data); + } } \ No newline at end of file diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 3f696f5cb..462b17cbc 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -450,6 +450,10 @@ public function testChangePassword() { 'new_password' => 'newpassword', 'confirm_password' => 'newpassword', 'old_password' => 'test'))); + $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); + $this->Users->RememberMe->expects($this->any()) + ->method('destroyCookie'); + $this->Users->change_password(); $this->assertEqual($this->Users->redirectUrl, '/'); } From 4cb60fed2948ecb613826d4a3b4568c7fafb9444 Mon Sep 17 00:00:00 2001 From: Guillermo Mansilla Date: Thu, 2 May 2013 14:43:56 -0400 Subject: [PATCH 0037/1476] Fix documentation to set controller name property and model name --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index a894fbcf9..be4021668 100644 --- a/readme.md +++ b/readme.md @@ -79,6 +79,7 @@ Declare the controller class App::uses('UsersController', 'Users.Controller'); class AppUsersController extends UsersController { + public $name = 'AppUsers'; } In the case you want to extend also the user model it's required to set the right user class in the beforeFilter() because the controller will use the inherited model which would be Users.User. @@ -86,6 +87,7 @@ In the case you want to extend also the user model it's required to set the righ public function beforeFilter() { parent::beforeFilter(); $this->User = ClassRegistry::init('AppUser'); + $this->set('model', 'AppUser'); } You can overwrite the render() method to fall back to the plugin views in the case you want to use some of them @@ -103,6 +105,8 @@ You can overwrite the render() method to fall back to the plugin views in the ca return parent::render($view, $layout); } +Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory + ### Overwriting the default auth settings provided by the plugin To use the basics the plugin already offers but changing some of the settings overwrite the _setupAuth() method in the extending controller. From f8c9bd930d30334192ca3b22dfc19ee9c56d757b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 31 May 2013 08:50:58 -0500 Subject: [PATCH 0038/1476] Allowing to send html emails --- Controller/UsersController.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index fa3af63e2..9d7c05404 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -629,13 +629,16 @@ protected function _sendVerificationEmail($userData, $options = array()) { 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Account verification'), 'template' => $this->_pluginDot() . 'account_verification', - 'layout' => 'default'); + 'layout' => 'default', + 'emailFormat' => CakeEmail::MESSAGE_TEXT + ); $options = array_merge($defaults, $options); $Email = $this->_getMailInstance(); $Email->to($userData[$this->modelClass]['email']) ->from($options['from']) + ->emailFormat($options['emailFormat']) ->subject($options['subject']) ->template($options['template'], $options['layout']) ->viewVars(array( @@ -657,7 +660,9 @@ protected function _sendPasswordReset($admin = null, $options = array()) { 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Password Reset'), 'template' => $this->_pluginDot() . 'password_reset_request', - 'layout' => 'default'); + 'emailFormat' => CakeEmail::MESSAGE_TEXT, + 'layout' => 'default' + ); $options = array_merge($defaults, $options); @@ -669,6 +674,7 @@ protected function _sendPasswordReset($admin = null, $options = array()) { $Email = $this->_getMailInstance(); $Email->to($user[$this->modelClass]['email']) ->from($options['from']) + ->emailFormat($options['emailFormat']) ->subject($options['subject']) ->template($options['template'], $options['layout']) ->viewVars(array( From c2af317134e2912bdb5d33a3b3f2f73ffe00a163 Mon Sep 17 00:00:00 2001 From: "Angel S. Moreno" Date: Mon, 3 Jun 2013 03:02:01 -0300 Subject: [PATCH 0039/1476] $this->plugin should be underscore when used in an url --- Controller/UsersController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 9d7c05404..53cd4c62c 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -183,8 +183,8 @@ protected function _setupAuth() { $this->modelClass . '.email_verified' => 1))); $this->Auth->loginRedirect = '/'; - $this->Auth->logoutRedirect = array('plugin' => $this->plugin, 'controller' => 'users', 'action' => 'login'); - $this->Auth->loginAction = array('admin' => false, 'plugin' => $this->plugin, 'controller' => 'users', 'action' => 'login'); + $this->Auth->logoutRedirect = array('plugin' => Inflector::underscore($this->plugin), 'controller' => 'users', 'action' => 'login'); + $this->Auth->loginAction = array('admin' => false, 'plugin' => Inflector::underscore($this->plugin), 'controller' => 'users', 'action' => 'login'); } /** From 461193d64371717d9c910f65d8fd9614c15d6839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 3 Jun 2013 15:27:22 +0200 Subject: [PATCH 0040/1476] Refs https://github.com/CakeDC/users/issues/113 Made the time configurable and dealing with the strtotime() issue on 32bit systems as long as its not fixed in the core --- Controller/Component/RememberMeComponent.php | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 81304b54d..79e982d5f 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -53,6 +53,7 @@ class RememberMeComponent extends Component { 'autoLogin' => true, 'userModel' => 'User', 'cookieKey' => 'rememberMe', + 'cookieLifeTime' => '+99 years', 'cookie' => array( 'name' => 'User'), 'fields' => array( @@ -68,10 +69,33 @@ class RememberMeComponent extends Component { */ public function __construct(ComponentCollection $collection, $settings = array()) { parent::__construct($collection, $settings); + + $this->_checkAndSetCookieLifeTime(); $this->settings = Set::merge($this->_defaults, $settings); $this->configureCookie($this->settings['cookie']); } +/** + * Check if the system is 32bit and uses DateTime() instead strtotime() to get + * an integer instead of a string that is passed on to CookieComponent::write() + * due to problems with strtotime() in CookieComponent::_expire(). See + * the link in this doc block. + * + * This method needs to be called in the constructor before the default config + * values are merged! + * + * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3868-cookiecomponent_expires-fails-on-dates-set-far-in-the-future-on-32bit-systems + * @link http://stackoverflow.com/questions/3266077/php-strtotime-is-returning-false-for-a-future-date + * @return void + */ + protected function _checkAndSetCookieLifeTime() { + $lifeTime = $this->_defaults['cookieLifeTime']; + if (is_string($lifeTime) && strtotime($lifeTime) === false) { + $Date = new DateTime($lifeTime); + $this->_defaults['cookieLifeTime'] = $Date->format('U'); + } + } + /** * Initializes RememberMeComponent for use in the controller * @@ -156,7 +180,7 @@ public function setCookie($data = array()) { } } - $this->Cookie->write($cookieKey, $cookieData, true, '+99 years'); + $this->Cookie->write($cookieKey, $cookieData, true, $cookieLifeTime); return true; } From 63d2a025ca4a7e32b84e19f265eb8d94524cf3cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 3 Jun 2013 15:34:56 +0200 Subject: [PATCH 0041/1476] Fixing the return_to's missing model index in Controller/UsersController.php --- Controller/UsersController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 9d7c05404..66bd7ceb0 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -405,11 +405,11 @@ public function login() { } } - if (empty($data['return_to'])) { - $data['return_to'] = null; + if (empty($data[$this->modelClass]['return_to'])) { + $data[$this->modelClass]['return_to'] = null; } - $this->redirect($this->Auth->redirect($data['return_to'])); + $this->redirect($this->Auth->redirect($data[$this->modelClass]['return_to'])); } else { $this->Auth->flash(__d('users', 'Invalid e-mail / password combination. Please try again')); } From e0f1e75edfdfa002018c985faa4e1d4cd7cc9145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 3 Jun 2013 15:43:02 +0200 Subject: [PATCH 0042/1476] Correcting the lower cased model name in UserDetail.php to upper cased --- Model/UserDetail.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Model/UserDetail.php b/Model/UserDetail.php index 9e485f162..ea5ed8cf0 100644 --- a/Model/UserDetail.php +++ b/Model/UserDetail.php @@ -74,52 +74,52 @@ public function __construct($id = false, $table = null, $ds = null) { public function createDefaults($userId) { $entries = array( array( - 'field' => 'user.firstname', + 'field' => 'User.firstname', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.middlename', + 'field' => 'User.middlename', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.lastname', + 'field' => 'User.lastname', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.abbr-country-name', + 'field' => 'User.abbr-country-name', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.abbr-region', + 'field' => 'User.abbr-region', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.country-name', + 'field' => 'User.country-name', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.location', + 'field' => 'User.location', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.postal-code', + 'field' => 'User.postal-code', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.region', + 'field' => 'User.region', 'value' => '', 'input' => 'text', 'data_type' => 'string'), array( - 'field' => 'user.timeoffset', + 'field' => 'User.timeoffset', 'value' => '', 'input' => 'text', 'data_type' => 'string')); From 1fda1f6444e7cef8ecfeec54b033d218986383af Mon Sep 17 00:00:00 2001 From: David Yell Date: Tue, 21 May 2013 11:54:07 +0100 Subject: [PATCH 0043/1476] Updated the model to use the latest params from the Search component. Removed duplication in the Search component configuration. Updated the Search config to use username as a like, to allow a looser match. Resolves #111 Resolves #112 --- Controller/UsersController.php | 5 +---- Model/User.php | 5 +++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index fa3af63e2..4c91245f5 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -72,10 +72,7 @@ class UsersController extends UsersAppController { * @var array $presetVars * @link https://github.com/CakeDC/search */ - public $presetVars = array( - array('field' => 'search', 'type' => 'value'), - array('field' => 'username', 'type' => 'value'), - array('field' => 'email', 'type' => 'value')); + public $presetVars = true; /** * Constructor diff --git a/Model/User.php b/Model/User.php index 62f5453d9..da51f72fd 100644 --- a/Model/User.php +++ b/Model/User.php @@ -41,8 +41,9 @@ class User extends UsersAppModel { * @link https://github.com/CakeDC/search */ public $filterArgs = array( - array('name' => 'username', 'type' => 'string'), - array('name' => 'email', 'type' => 'string')); + array('username', 'type' => 'like'), + array('email', 'type' => 'value') + ); /** * Displayfield From a69f140ea110cb1ec4cd16f99546773a749e7495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 4 Jun 2013 23:10:43 +0200 Subject: [PATCH 0044/1476] Working on a way to resend the email verification --- Controller/UsersController.php | 19 +++++++++- Model/User.php | 57 +++++++++++++++++++++++++++++- View/Users/resend_verification.ctp | 14 ++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 View/Users/resend_verification.ctp diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 5af64e9bc..7e98b8e87 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -164,7 +164,7 @@ public function beforeFilter() { * @return void */ protected function _setupAuth() { - $this->Auth->allow('add', 'reset', 'verify', 'logout', 'view', 'reset_password', 'login'); + $this->Auth->allow('add', 'reset', 'verify', 'logout', 'view', 'reset_password', 'login', 'resend_verification'); if (!is_null(Configure::read('Users.allowRegistration')) && !Configure::read('Users.allowRegistration')) { $this->Auth->deny('add'); } @@ -481,6 +481,23 @@ public function logout() { $this->redirect($this->Auth->logout()); } +/** + * Checks if an email is already verified and if not renews the expiration time + * + * @return void + */ + public function resend_verification() { + if ($this->request->is('post')) { + try { + if ($this->{$this->modelClass}->checkEmailVerification($this->request->data)) { + $this->_sendVerificationEmail($this->{$this->modelClass}->data); + } + } catch (Exception $e) { + $this->Session->setFlash($e->getMessage()); + } + } + } + /** * Confirm email action * diff --git a/Model/User.php b/Model/User.php index 62f5453d9..732b18a45 100644 --- a/Model/User.php +++ b/Model/User.php @@ -51,6 +51,13 @@ class User extends UsersAppModel { */ public $displayField = 'username'; +/** + * Time the email verification token is valid in seconds + * + * @var integer + */ + public $emailTokenExpirationTime = 86400; + /** * hasMany associations * @@ -543,6 +550,45 @@ public function view($slug = null) { return $user; } +/** + * Checks if an email is already verified and if not renews the expiration time + * + * @param array $postData the post data from the request + * @param boolean $renew + * @return bool True if the email was not already verified + */ + public function checkEmailVerification($postData = array(), $renew = true) { + $user = $this->find('first', array( + 'contain' => array(), + 'conditions' => array( + $this->alias . '.email' => $postData[$this->alias]['email'] + ) + )); + + if (empty($user)) { + $this->invalidate('email', __d('users', 'Invalid Email address.')); + return false; + } + + if ($user[$this->alias]['email_verified'] == 1) { + $this->invalidate('email', __d('users', 'This email is already verified.')); + return false; + } + + if ($user[$this->alias]['email_verified'] == 0) { + if ($renew === true) { + $user[$this->alias]['email_token_expires'] = $this->emailTokenExpirationTime(); + $this->save($user, array( + 'validate' => false, + 'callbacks' => false, + )); + } + $this->data = $user; + return true; + } + + } + /** * Registers a new user * @@ -619,11 +665,20 @@ public function resendVerification($postData = array()) { } $user[$this->alias]['email_token'] = $this->generateToken(); - $user[$this->alias]['email_token_expires'] = date('Y-m-d H:i:s', time() + 86400); + $user[$this->alias]['email_token_expires'] = $this->emailTokenExpirationTime(); return $this->save($user, false); } +/** + * Returns the time the email verification token expires + * + * @return string + */ + public function emailTokenExpirationTime() { + return date('Y-m-d H:i:s', time() + $this->emailTokenExpirationTime); + } + /** * Generates a password * diff --git a/View/Users/resend_verification.ctp b/View/Users/resend_verification.ctp new file mode 100644 index 000000000..a1fa56651 --- /dev/null +++ b/View/Users/resend_verification.ctp @@ -0,0 +1,14 @@ +
+

+
+ Form->create($model, array( + 'action' => 'login', + 'id' => 'ResendVerficationForm')); + echo $this->Form->input('email', array( + 'label' => __d('users', 'Email'))); + echo $this->Form->end(__d('users', 'Submit')); + ?> +
+
+element('Users/sidebar'); ?> \ No newline at end of file From 5c96ba506533ba364a3fe9f601c030fa519340d5 Mon Sep 17 00:00:00 2001 From: "Angel S. Moreno" Date: Wed, 5 Jun 2013 11:34:47 -0400 Subject: [PATCH 0045/1476] Moved "App::uses('CakeEmail', 'Network/Email')" to top of USersController to prevent "Class CakeEmail not found" error --- Controller/UsersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 5af64e9bc..7cdbef871 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -9,6 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +App::uses('CakeEmail', 'Network/Email'); App::uses('UsersAppController', 'Users.Controller'); /** @@ -743,7 +744,6 @@ protected function _resetPassword($token) { * @link http://book.cakephp.org/2.0/en/core-utility-libraries/email.html */ protected function _getMailInstance() { - App::uses('CakeEmail', 'Network/Email'); $emailConfig = Configure::read('Users.emailConfig'); if ($emailConfig) { return new CakeEmail($emailConfig); From b3e0700327105d7496777379e002a1fa1a4f8772 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Thu, 6 Jun 2013 08:45:30 -0500 Subject: [PATCH 0046/1476] Fixing a couple of issues with resend verification view and model --- Controller/UsersController.php | 7 ++++-- Model/User.php | 2 +- View/Users/resend_verification.ctp | 34 ++++++++++++++++++++---------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 7e98b8e87..4d615e698 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -491,6 +491,8 @@ public function resend_verification() { try { if ($this->{$this->modelClass}->checkEmailVerification($this->request->data)) { $this->_sendVerificationEmail($this->{$this->modelClass}->data); + } else { + $this->Session->setFlash(__d('users', 'The email could not be sent. Please check errors.')); } } catch (Exception $e) { $this->Session->setFlash($e->getMessage()); @@ -659,8 +661,9 @@ protected function _sendVerificationEmail($userData, $options = array()) { ->subject($options['subject']) ->template($options['template'], $options['layout']) ->viewVars(array( - 'model' => $this->modelClass, - 'user' => $userData)) + 'model' => $this->modelClass, + 'user' => $userData + )) ->send(); } diff --git a/Model/User.php b/Model/User.php index 732b18a45..8ffccaa7b 100644 --- a/Model/User.php +++ b/Model/User.php @@ -559,7 +559,7 @@ public function view($slug = null) { */ public function checkEmailVerification($postData = array(), $renew = true) { $user = $this->find('first', array( - 'contain' => array(), + 'contain' => array('Profile'), 'conditions' => array( $this->alias . '.email' => $postData[$this->alias]['email'] ) diff --git a/View/Users/resend_verification.ctp b/View/Users/resend_verification.ctp index a1fa56651..376c67c37 100644 --- a/View/Users/resend_verification.ctp +++ b/View/Users/resend_verification.ctp @@ -1,14 +1,26 @@ -
+ +

-
- Form->create($model, array( - 'action' => 'login', - 'id' => 'ResendVerficationForm')); - echo $this->Form->input('email', array( - 'label' => __d('users', 'Email'))); - echo $this->Form->end(__d('users', 'Submit')); - ?> -
+

+ Form->create($model, array( + 'url' => array( + 'admin' => false, + 'action' => 'resend_verification'))); + echo $this->Form->input('email', array( + 'label' => __d('users', 'Your Email'))); + echo $this->Form->submit(__d('users', 'Submit')); + echo $this->Form->end(); + ?>
element('Users/sidebar'); ?> \ No newline at end of file From 31fb4a16f82be8fa301c4d3a4e2ec3fc4759ba30 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Thu, 6 Jun 2013 08:52:47 -0500 Subject: [PATCH 0047/1476] Adding redirect and flash on email sent --- Controller/UsersController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 3cb1a1eb6..4908df0be 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -492,6 +492,8 @@ public function resend_verification() { try { if ($this->{$this->modelClass}->checkEmailVerification($this->request->data)) { $this->_sendVerificationEmail($this->{$this->modelClass}->data); + $this->Session->setFlash(__d('users', 'The email was resent. Please check your inbox.')); + $this->redirect('login'); } else { $this->Session->setFlash(__d('users', 'The email could not be sent. Please check errors.')); } From 6de4a599bfe36513f52cc1e34f0034fc44ab4379 Mon Sep 17 00:00:00 2001 From: "Angel S. Moreno" Date: Fri, 7 Jun 2013 14:43:48 -0400 Subject: [PATCH 0048/1476] Fixed typo - syntax when calling __d() --- Controller/Component/RememberMeComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 79e982d5f..91136ccf8 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -216,7 +216,7 @@ public function configureCookie($options = array()) { if (in_array($key, $validProperties)) { $this->Cookie->{$key} = $value; } else { - throw new InvalidArgumentException(__('users', 'Invalid options %s', $key)); + throw new InvalidArgumentException(__d('users', 'Invalid options %s', $key)); } } } From b434dba0e99252371ea114e9e938b3c971fb3ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 11 Jun 2013 20:47:05 +0200 Subject: [PATCH 0049/1476] Some cleanup and a minor change to the UsersControllerTest.php --- .travis.yml | 32 ++++++++++++++++++++ Test/Case/Controller/UsersControllerTest.php | 14 ++++----- 2 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..df0078024 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +language: php + +php: + - 5.2.8 + - 5.3 + - 5.4 + +before_script: + - git clone --depth 1 git://github.com/cakephp/cakephp ../cakephp && cd ../cakephp + - git clone --depth 1 --branch develop git://github.com/CakeDC/search plugins/search + - cd plugins/Search + - git submodule update --init --recursive + - cd ../../ + - mv ../Users plugins/Users + - sh -c "mysql -e 'CREATE DATABASE cakephp_test;'" + - chmod -R 777 ../cakephp/app/tmp + - echo " 'Database/Mysql', + 'database' => 'cakephp_test', + 'host' => '0.0.0.0', + 'login' => 'travis', + 'persistent' => false, + ); + }" > ../cakephp/app/Config/database.php + +script: + - ./lib/Cake/Console/cake test Users AllUsersPlugin --stderr + +notifications: + email: false \ No newline at end of file diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 462b17cbc..77a08d9ad 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -188,7 +188,9 @@ class UsersControllerTestCase extends CakeTestCase { * * @return void */ - public function startTest($method) { + public function setUp() { + parent::setUp(); + Configure::write('App.UserClass', null); $request = new CakeRequest(); @@ -220,6 +222,9 @@ public function startTest($method) { $this->Users->CakeEmail->expects($this->any()) ->method('viewVars') ->will($this->returnSelf()); + $this->Users->CakeEmail->expects($this->any()) + ->method('emailFormat') + ->will($this->returnSelf()); $this->Users->Components->disable('Security'); } @@ -541,13 +546,6 @@ public function testAdminDelete() { $this->assertEqual($this->Users->redirectUrl, array('action' => 'index')); } -// public function testMailInstance() { -// // default instance shoult be "default" -// $cakeMail = $this->Users->getMailInstance(); -// $this->assertFalse($cakeMail); -// // if configured, load the email config -// } - /** * Test setting the cookie * From 6b6eef381ade1d04d9f6a6566dfdcba2b39c0368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 11 Jun 2013 20:55:09 +0200 Subject: [PATCH 0050/1476] Changint the RememberMeComponent.php cookie setting to +1 year, should be enough and won't cause issues like 99 on some systems. --- Controller/Component/RememberMeComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 91136ccf8..ebf79137b 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -53,7 +53,7 @@ class RememberMeComponent extends Component { 'autoLogin' => true, 'userModel' => 'User', 'cookieKey' => 'rememberMe', - 'cookieLifeTime' => '+99 years', + 'cookieLifeTime' => '+1 year', 'cookie' => array( 'name' => 'User'), 'fields' => array( From 96544b9fbfa960e7832adf8686760d8383bbc138 Mon Sep 17 00:00:00 2001 From: David Yell Date: Wed, 12 Jun 2013 12:46:54 +0100 Subject: [PATCH 0051/1476] Fixed a bug in the filterArgs --- Model/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Model/User.php b/Model/User.php index 65e0aab9f..64e7ed99a 100644 --- a/Model/User.php +++ b/Model/User.php @@ -41,8 +41,8 @@ class User extends UsersAppModel { * @link https://github.com/CakeDC/search */ public $filterArgs = array( - array('username', 'type' => 'like'), - array('email', 'type' => 'value') + 'username' => array('type' => 'like'), + 'email' => array('type' => 'value') ); /** From 897d9166f9cf2159042590bf875cffa713e0599c Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Wed, 12 Jun 2013 23:35:32 +0400 Subject: [PATCH 0052/1476] Add check before destroy cookie --- Controller/UsersController.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 87bd2d6de..ab294d3e4 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -473,7 +473,9 @@ public function search() { public function logout() { $user = $this->Auth->user(); $this->Session->destroy(); - $this->Cookie->destroy(); + if (isset($_COOKIE[$this->Cookie->name])) { + $this->Cookie->destroy(); + } $this->RememberMe->destroyCookie(); $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged out'), $user[$this->{$this->modelClass}->displayField])); $this->redirect($this->Auth->logout()); From 9145be612c101c9159d8b0f6d9223f96a5407073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 14 Jul 2013 23:17:11 +0200 Subject: [PATCH 0053/1476] Loading AppModel instead Model in App::uses in the UsersAppModel.php --- Model/UsersAppModel.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Model/UsersAppModel.php b/Model/UsersAppModel.php index bd062bada..252a786d2 100644 --- a/Model/UsersAppModel.php +++ b/Model/UsersAppModel.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -App::uses('Model', 'Model'); +App::uses('AppModel', 'Model'); /** * Users App Model @@ -31,7 +31,9 @@ class UsersAppModel extends AppModel { * * @var array */ - public $actsAs = array('Containable'); + public $actsAs = array( + 'Containable' + ); /** * Customized paginateCount method @@ -41,7 +43,7 @@ class UsersAppModel extends AppModel { * @param array * @return */ - function paginateCount($conditions = array(), $recursive = 0, $extra = array()) { + public function paginateCount($conditions = array(), $recursive = 0, $extra = array()) { $parameters = compact('conditions'); if ($recursive != $this->recursive) { $parameters['recursive'] = $recursive; @@ -52,4 +54,5 @@ function paginateCount($conditions = array(), $recursive = 0, $extra = array()) } return $this->find('count', array_merge($parameters, $extra)); } + } From 3287fe5481617d226d6e58c1ac8094a13a36de04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 14 Jul 2013 23:29:13 +0200 Subject: [PATCH 0054/1476] Adding plugin prefixes to elements calls in the views --- View/UserDetails/admin_index.ctp | 2 +- View/Users/add.ctp | 2 +- View/Users/admin_add.ctp | 45 +++++++++++++------------- View/Users/admin_edit.ctp | 2 +- View/Users/admin_index.ctp | 8 ++--- View/Users/admin_view.ctp | 2 +- View/Users/change_password.ctp | 2 +- View/Users/edit.ctp | 2 +- View/Users/index.ctp | 4 +-- View/Users/login.ctp | 2 +- View/Users/request_password_change.ctp | 2 +- View/Users/resend_verification.ctp | 2 +- View/Users/reset_password.ctp | 2 +- View/Users/search.ctp | 4 +-- View/Users/view.ctp | 2 +- 15 files changed, 41 insertions(+), 42 deletions(-) diff --git a/View/UserDetails/admin_index.ctp b/View/UserDetails/admin_index.ctp index aa80adc7e..eb251218d 100644 --- a/View/UserDetails/admin_index.ctp +++ b/View/UserDetails/admin_index.ctp @@ -66,7 +66,7 @@ foreach ($user_details as $user_detail):
-element('pagination'); ?> +element('Users.pagination'); ?>
  • Html->link(__d('users', 'New User Detail'), array('action' => 'add')); ?>
  • diff --git a/View/Users/add.ctp b/View/Users/add.ctp index f87c8922c..e9eaefdb9 100644 --- a/View/Users/add.ctp +++ b/View/Users/add.ctp @@ -33,4 +33,4 @@ ?>
-element('Users/sidebar'); ?> +element('Users.Users/sidebar'); ?> diff --git a/View/Users/admin_add.ctp b/View/Users/admin_add.ctp index c1f9e623f..1e8a2945c 100644 --- a/View/Users/admin_add.ctp +++ b/View/Users/admin_add.ctp @@ -14,29 +14,28 @@
Form->input('username', array( - 'label' => __d('users', 'Username'))); - echo $this->Form->input('email', array( - 'label' => __d('users', 'E-mail (used as login)'), - 'error' => array('isValid' => __d('users', 'Must be a valid email address'), - 'isUnique' => __d('users', 'An account with that email already exists')))); - echo $this->Form->input('password', array( - 'label' => __d('users', 'Password'), - 'type' => 'password')); - echo $this->Form->input('temppassword', array( - 'label' => __d('users', 'Password (confirm)'), - 'type' => 'password')); - if (!empty($roles)) { - echo $this->Form->input('role', array( - 'label' => __d('users', 'Role'), 'values' => $roles)); - - } - echo $this->Form->input('is_admin', array( - 'label' => __d('users', 'Is Admin'))); - echo $this->Form->input('active', array( - 'label' => __d('users', 'Active'))); - ?> + echo $this->Form->input('username', array( + 'label' => __d('users', 'Username'))); + echo $this->Form->input('email', array( + 'label' => __d('users', 'E-mail (used as login)'), + 'error' => array('isValid' => __d('users', 'Must be a valid email address'), + 'isUnique' => __d('users', 'An account with that email already exists')))); + echo $this->Form->input('password', array( + 'label' => __d('users', 'Password'), + 'type' => 'password')); + echo $this->Form->input('temppassword', array( + 'label' => __d('users', 'Password (confirm)'), + 'type' => 'password')); + if (!empty($roles)) { + echo $this->Form->input('role', array( + 'label' => __d('users', 'Role'), 'values' => $roles)); + } + echo $this->Form->input('is_admin', array( + 'label' => __d('users', 'Is Admin'))); + echo $this->Form->input('active', array( + 'label' => __d('users', 'Active'))); + ?>
Form->end('Submit'); ?> -element('Users/admin_sidebar'); ?> \ No newline at end of file +element('Users.Users/admin_sidebar'); ?> \ No newline at end of file diff --git a/View/Users/admin_edit.ctp b/View/Users/admin_edit.ctp index 270139c6f..7c4b85f89 100644 --- a/View/Users/admin_edit.ctp +++ b/View/Users/admin_edit.ctp @@ -31,4 +31,4 @@ Form->end('Submit'); ?> -element('Users/admin_sidebar'); ?> \ No newline at end of file +element('Users.Users/admin_sidebar'); ?> \ No newline at end of file diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index 73dbb4ab0..28a30006d 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -20,8 +20,8 @@ echo $this->Form->end(__d('users', 'Search')); ?> - element('paging'); ?> - element('pagination'); ?> + element('Users.paging'); ?> + element('Users.pagination'); ?> @@ -63,6 +63,6 @@
Paginator->sort('username'); ?>
- element('pagination'); ?> + element('Users.pagination'); ?> -element('Users/admin_sidebar'); ?> +element('Users.Users/admin_sidebar'); ?> diff --git a/View/Users/admin_view.ctp b/View/Users/admin_view.ctp index dcacbdf44..5c37c8d2f 100644 --- a/View/Users/admin_view.ctp +++ b/View/Users/admin_view.ctp @@ -29,4 +29,4 @@ -element('Users/admin_sidebar'); ?> \ No newline at end of file +element('Users.Users/admin_sidebar'); ?> \ No newline at end of file diff --git a/View/Users/change_password.ctp b/View/Users/change_password.ctp index bc4530440..7dcaf378f 100644 --- a/View/Users/change_password.ctp +++ b/View/Users/change_password.ctp @@ -26,4 +26,4 @@ echo $this->Form->end(__d('users', 'Submit')); ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/edit.ctp b/View/Users/edit.ctp index 699bad37c..4cfbcbf5d 100644 --- a/View/Users/edit.ctp +++ b/View/Users/edit.ctp @@ -24,4 +24,4 @@ Form->end(__d('users', 'Submit')); ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/index.ctp b/View/Users/index.ctp index 1dbbcbc2d..77363618c 100644 --- a/View/Users/index.ctp +++ b/View/Users/index.ctp @@ -41,6 +41,6 @@ - element('pagination'); ?> + element('Users.pagination'); ?> -element('Users/sidebar'); ?> +element('Users.Users/sidebar'); ?> diff --git a/View/Users/login.ctp b/View/Users/login.ctp index e803fe2b9..182ef131a 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -30,4 +30,4 @@ ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/request_password_change.ctp b/View/Users/request_password_change.ctp index 5cf7b1ed7..4c566d1b2 100644 --- a/View/Users/request_password_change.ctp +++ b/View/Users/request_password_change.ctp @@ -23,4 +23,4 @@ echo $this->Form->end(); ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/resend_verification.ctp b/View/Users/resend_verification.ctp index 376c67c37..e48925de7 100644 --- a/View/Users/resend_verification.ctp +++ b/View/Users/resend_verification.ctp @@ -23,4 +23,4 @@ echo $this->Form->end(); ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/reset_password.ctp b/View/Users/reset_password.ctp index f55ab3901..325a2aa1b 100644 --- a/View/Users/reset_password.ctp +++ b/View/Users/reset_password.ctp @@ -15,4 +15,4 @@ echo $this->Form->end(); ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/search.ctp b/View/Users/search.ctp index b051e6d9b..fec064cae 100644 --- a/View/Users/search.ctp +++ b/View/Users/search.ctp @@ -58,6 +58,6 @@ - element('pagination'); ?> + element('Users.pagination'); ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/view.ctp b/View/Users/view.ctp index cc8edaf5d..d2f51d6ba 100644 --- a/View/Users/view.ctp +++ b/View/Users/view.ctp @@ -34,4 +34,4 @@ ?> -element('Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> \ No newline at end of file From ed5b3edc71f05a355c2a5a395437b33342a7e023 Mon Sep 17 00:00:00 2001 From: David Yell Date: Tue, 16 Jul 2013 10:10:31 +0100 Subject: [PATCH 0055/1476] Added session flash message to feedback to the user --- View/Users/login.ctp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/View/Users/login.ctp b/View/Users/login.ctp index 182ef131a..08c73cb29 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -11,6 +11,7 @@ ?>

+ Session->flash('auth');?>
Form->create($model, array( @@ -30,4 +31,4 @@ ?>
-element('Users.Users/sidebar'); ?> \ No newline at end of file +element('Users.Users/sidebar'); ?> From e9424769cd445ec3a09161e5e1b2205858bd4206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 23 Jul 2013 15:54:07 +0200 Subject: [PATCH 0056/1476] Updating more deprecated paginator calls --- Controller/UsersController.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index ab294d3e4..f6ad3d357 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -191,12 +191,12 @@ protected function _setupAuth() { * @return void */ public function index() { - $this->paginate = array( + $this->Paginator->settings = array( 'limit' => 12, 'conditions' => array( $this->modelClass . '.active' => 1, $this->modelClass . '.email_verified' => 1)); - $this->set('users', $this->paginate($this->modelClass)); + $this->set('users', $this->Paginator->paginate($this->modelClass)); } /** @@ -265,7 +265,7 @@ public function admin_index() { $this->Paginator->settings[$this->modelClass]['order'] = array($this->modelClass . '.created' => 'desc'); $this->{$this->modelClass}->recursive = 0; - $this->set('users', $this->paginate()); + $this->set('users', $this->Paginator->paginate()); } /** @@ -451,7 +451,7 @@ public function search() { } $this->request->data[$this->modelClass]['search'] = $searchTerm; - $this->paginate = array( + $this->Paginator->settings = array( 'search', 'limit' => 12, 'by' => $by, @@ -461,7 +461,7 @@ public function search() { $this->modelClass . '.active' => 1, $this->modelClass . '.email_verified' => 1))); - $this->set('users', $this->paginate($this->modelClass)); + $this->set('users', $this->Paginator->paginate($this->modelClass)); $this->set('searchTerm', $searchTerm); } From bd7c29b6d45ac03c701ebd16bbab1e59846eae9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 23 Jul 2013 16:25:00 +0200 Subject: [PATCH 0057/1476] Started to fix the issue #125 from github, preliminarily commit --- Controller/Component/RememberMeComponent.php | 18 ++++++++++++++---- Controller/UsersController.php | 10 +++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index ebf79137b..b0ae9dfff 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -129,10 +129,9 @@ public function restoreLoginFromCookie($checkLoginStatus = true) { return true; } - extract($this->settings); - $cookie = $this->Cookie->read($cookieKey); - - if (!empty($cookie)) { + if ($this->cookieIsSet()) { + extract($this->settings); + $cookie = $this->Cookie->read($cookieKey); $request = $this->request->data; foreach ($fields as $field) { @@ -184,6 +183,17 @@ public function setCookie($data = array()) { return true; } +/** + * Checks if the remember me cookie is set + * + * @return boolean + */ + public function cookieIsSet() { + extract($this->settings); + $cookie = $this->Cookie->read($cookieKey); + return (!empty($cookie)); + } + /** * Destroys the remember me cookie * diff --git a/Controller/UsersController.php b/Controller/UsersController.php index f6ad3d357..22d072a2e 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -729,7 +729,6 @@ protected function _sendPasswordReset($admin = null, $options = array()) { * @param string Cookie data keyname for the userdata, its default is "User". This is set to User and NOT using the model alias to make sure it works with different apps with different user models across different (sub)domains. * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html - * @deprecated Use the RememberMe Component */ protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { $this->RememberMe->settings['cookieKey'] = $cookieKey; @@ -751,8 +750,13 @@ protected function _resetPassword($token) { } if (!empty($this->request->data) && $this->{$this->modelClass}->resetPassword(Set::merge($user, $this->request->data))) { - $this->Session->setFlash(__d('users', 'Password changed, you can now login with your new password.')); - $this->redirect($this->Auth->loginAction); + if ($this->RememberMe->cookieIsSet()) { + $this->Session->setFlash(__d('users', 'Password changed.')); + $this->_setCookie(); + } else { + $this->Session->setFlash(__d('users', 'Password changed, you can now login with your new password.')); + $this->redirect($this->Auth->loginAction); + } } $this->set('token', $token); From c11ed91f02d88f7ac4ced3529dc4721efc38d558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 4 Aug 2013 17:51:58 +0200 Subject: [PATCH 0058/1476] Refs #127 Removing the UserDetails https://github.com/CakeDC/users/issues/127 --- Controller/UserDetailsController.php | 216 --------------- Controller/UsersController.php | 14 +- Model/User.php | 67 +---- Model/UserDetail.php | 259 ------------------ Test/Case/AllUsersPluginTest.php | 2 - .../Component/RememberMeComponentTest.php | 1 + .../Controller/UserDetailsControllerTest.php | 45 --- Test/Case/Controller/UsersControllerTest.php | 17 +- Test/Case/Model/UserDetailTest.php | 190 ------------- Test/Case/Model/UserTest.php | 2 +- Test/Fixture/UserDetailFixture.php | 92 ------- View/UserDetails/add.ctp | 31 --- View/UserDetails/admin_add.ctp | 31 --- View/UserDetails/admin_edit.ctp | 33 --- View/UserDetails/admin_index.ctp | 76 ----- View/UserDetails/admin_view.ctp | 61 ----- View/UserDetails/edit.ctp | 25 -- View/UserDetails/index.ctp | 28 -- View/UserDetails/view.ctp | 62 ----- 19 files changed, 6 insertions(+), 1246 deletions(-) delete mode 100644 Controller/UserDetailsController.php delete mode 100644 Model/UserDetail.php delete mode 100644 Test/Case/Controller/UserDetailsControllerTest.php delete mode 100755 Test/Case/Model/UserDetailTest.php delete mode 100644 Test/Fixture/UserDetailFixture.php delete mode 100644 View/UserDetails/add.ctp delete mode 100644 View/UserDetails/admin_add.ctp delete mode 100644 View/UserDetails/admin_edit.ctp delete mode 100644 View/UserDetails/admin_index.ctp delete mode 100644 View/UserDetails/admin_view.ctp delete mode 100644 View/UserDetails/edit.ctp delete mode 100644 View/UserDetails/index.ctp delete mode 100644 View/UserDetails/view.ctp diff --git a/Controller/UserDetailsController.php b/Controller/UserDetailsController.php deleted file mode 100644 index fdc36edf3..000000000 --- a/Controller/UserDetailsController.php +++ /dev/null @@ -1,216 +0,0 @@ -UserDetail->find('all', array( - 'contain' => array(), - 'conditions' => array( - 'UserDetail.user_id' => $this->Auth->user('id'), - 'UserDetail.field LIKE' => 'user.%'), - 'order' => 'UserDetail.position DESC')); - $this->set('user_details', $userDetails); - } - -/** - * View - * - * @param string $id Detail ID - * @return void - */ - public function view($id = null) { - if (!$id) { - $this->Session->setFlash(__d('users', 'Invalid Detail.')); - $this->redirect(array('action' => 'index')); - } - $this->set('user_detail', $this->UserDetail->read(null, $id)); - } - -/** - * Add - * - * @return void - */ - public function add() { - if (!empty($this->request->data)) { - $userId = $this->Auth->user('id'); - foreach ($this->request->data as $group => $options) { - foreach ($options as $key => $value) { - $field = $group . '.' . $key; - $this->UserDetail->updateAll( - array('Detail.value' => "'$value'"), - array('Detail.user_id' => $userId, 'Detail.field' => $field)); - } - } - $this->Session->setFlash(__d('users', 'Saved')); - } - $this->redirect(array('action' => 'index')); - } - -/** - * Edit - * - * Allows a logged in user to edit his own profile settings - * - * @param string $section Section name - * @return void - */ - public function edit($section = 'user') { - if (!isset($section)) { - $section = 'user'; - } - - if (!empty($this->request->data)) { - $this->UserDetail->saveSection($this->Auth->user('id'), $this->request->data, $section); - $this->Session->setFlash(sprintf(__d('users', '%s details saved'), ucfirst($section))); - } - - if (empty($this->request->data)) { - $detail = $this->UserDetail->getSection($this->Auth->user('id'), $section); - $this->request->data['UserDetail'] = $detail[$section]; - } - - $this->set('section', $section); - } - -/** - * Delete - * - * @param string $id Detail ID - * @return void - */ - public function delete($id = null) { - if (!$id) { - $this->Session->setFlash(__d('users', 'Invalid id for Detail')); - $this->redirect(array('action' => 'index')); - } - if ($this->UserDetail->delete($id)) { - $this->Session->setFlash(__d('users', 'User Detail deleted')); - $this->redirect(array('action' => 'index')); - } - } - -/** - * Admin Index - * - * @return void - */ - public function admin_index() { - $this->UserDetail->recursive = 0; - $this->set('user_details', $this->paginate()); - } - -/** - * Admin View - * - * @param string $id Detail ID - * @return void - */ - public function admin_view($id = null) { - if (!$id) { - $this->Session->setFlash(__d('users', 'Invalid Detail.')); - $this->redirect(array('action' => 'index')); - } - $this->set('user_detail', $this->UserDetail->read(null, $id)); - } - -/** - * Admin Add - * - * @return void - */ - public function admin_add() { - if (!empty($this->request->data)) { - $this->UserDetail->create(); - if ($this->UserDetail->save($this->request->data)) { - $this->Session->setFlash(__d('users', 'The Detail has been saved')); - $this->redirect(array('action' => 'index')); - } else { - $this->Session->setFlash(__d('users', 'The Detail could not be saved. Please, try again.')); - } - } - - $users = $this->UserDetail->User->find('list'); - $this->set(compact('users')); - } - -/** - * Admin edit - * - * @param string $id Detail ID - * @return void - */ - public function admin_edit($id = null) { - if (!$id && empty($this->request->data)) { - $this->Session->setFlash(__d('users', 'Invalid Detail')); - $this->redirect(array('action' => 'index')); - } - if (!empty($this->request->data)) { - if ($this->UserDetail->save($this->request->data)) { - $this->Session->setFlash(__d('users', 'The Detail has been saved')); - $this->redirect(array('action' => 'index')); - } else { - $this->Session->setFlash(__d('users', 'The Detail could not be saved. Please, try again.')); - } - } - if (empty($this->request->data)) { - $this->request->data = $this->UserDetail->read(null, $id); - } - - $users = $this->UserDetail->User->find('list'); - $this->set(compact('users')); - } - -/** - * Admin Delete - * - * @param string $id Detail ID - * @return void - */ - public function admin_delete($id = null) { - if (!$id) { - $this->Session->setFlash(__d('users', 'Invalid id for Detail')); - $this->redirect(array('action' => 'index')); - } - if ($this->UserDetail->delete($id)) { - $this->Session->setFlash(__d('users', 'User Detail deleted')); - $this->redirect(array('action' => 'index')); - } - } -} diff --git a/Controller/UsersController.php b/Controller/UsersController.php index f6ad3d357..1543ffe45 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -231,19 +231,7 @@ public function view($slug = null) { * @return void */ public function edit() { - if (!empty($this->request->data)) { - if ($this->{$this->modelClass}->UserDetail->saveSection($this->Auth->user('id'), $this->request->data, 'User')) { - $this->Session->setFlash(__d('users', 'Profile saved.')); - } else { - $this->Session->setFlash(__d('users', 'Could not save your profile.')); - } - } else { - $data = $this->{$this->modelClass}->UserDetail->getSection($this->Auth->user('id'), 'User'); - if (!isset($data[$this->modelClass])) { - $data[$this->modelClass] = array(); - } - $this->request->data['UserDetail'] = $data[$this->modelClass]; - } + // @todo replace this with something better than the user details that were removed } /** diff --git a/Model/User.php b/Model/User.php index 64e7ed99a..1449977fd 100644 --- a/Model/User.php +++ b/Model/User.php @@ -59,16 +59,6 @@ class User extends UsersAppModel { */ public $emailTokenExpirationTime = 86400; -/** - * hasMany associations - * - * @var array - */ - public $hasMany = array( - 'UserDetail' => array( - 'className' => 'Users.UserDetail', - 'foreignKey' => 'user_id')); - /** * Validation domain for translations * @@ -168,41 +158,6 @@ protected function _setupValidation() { 'to_short' => array('rule' => 'validateOldPassword', 'required' => true, 'message' => __d('users', 'Invalid password.')))); } -/** - * Sets some defaults for the UserDetail model - * - * @return void - */ - public function setupDetail() { - $this->UserDetail->sectionSchema[$this->alias] = array( - 'birthday' => array( - 'type' => 'date', - 'null' => null, - 'default' => null, - 'length' => null), - 'first_name' => array( - 'type' => 'string', - 'null' => null, - 'default' => null, - 'length' => null), - 'last_name' => array( - 'type' => 'string', - 'null' => null, - 'default' => null, - 'length' => null)); - - $this->UserDetail->sectionValidation[$this->alias] = array( - 'birthday' => array( - 'validDate' => array( - 'rule' => array('date'), 'allowEmpty' => true, 'message' => __d('users', 'Invalid date'))), - 'first_name' => array( - 'notEmpty' => array( - 'rule' => array('notEmpty'), 'allowEmpty' => true, 'message' => __d('users', 'Invalid date'))), - 'last_name' => array( - 'notEmpty' => array( - 'rule' => array('notEmpty'), 'allowEmpty' => true, 'message' => __d('users', 'Invalid date')))); - } - /** * After save callback * @@ -229,22 +184,6 @@ public function sluggedUserUrl() { } } -/** - * afterFind callback - * - * @param array $results Result data - * @param mixed $primary Primary query - * @return array - */ - public function afterFind($results, $primary = false) { - foreach ($results as &$row) { - if (isset($row['UserDetail']) && (is_array($row))) { - $row['UserDetail'] = $this->UserDetail->getSection($row[$this->alias]['id'], $this->alias); - } - } - return $results; - } - /** * Create a hash from string using given method. * Fallback on next available method. @@ -535,8 +474,7 @@ public function compareFields($field1, $field2) { */ public function view($slug = null) { $user = $this->find('first', array( - 'contain' => array( - 'UserDetail'), + 'contain' => array(), 'conditions' => array( 'OR' => array( $this->alias . '.slug' => $slug, @@ -884,8 +822,7 @@ public function add($postData = null) { */ public function edit($userId = null, $postData = null) { $user = $this->find('first', array( - 'contain' => array( - 'UserDetail'), + 'contain' => array(), 'conditions' => array($this->alias . '.id' => $userId))); $this->set($user); diff --git a/Model/UserDetail.php b/Model/UserDetail.php deleted file mode 100644 index ea5ed8cf0..000000000 --- a/Model/UserDetail.php +++ /dev/null @@ -1,259 +0,0 @@ -belongsTo['User'] = array( - 'className' => $userClass, - 'foreignKey' => 'user_id'); - parent::__construct($id, $table, $ds); - } - -/** - * Create the default fields for a user - * - * @param string $userId User ID - * @return void - */ - public function createDefaults($userId) { - $entries = array( - array( - 'field' => 'User.firstname', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.middlename', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.lastname', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.abbr-country-name', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.abbr-region', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.country-name', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.location', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.postal-code', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.region', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string'), - array( - 'field' => 'User.timeoffset', - 'value' => '', - 'input' => 'text', - 'data_type' => 'string')); - - $i = 0; - $data = array(); - foreach ($entries as $entry) { - $data[$this->alias] = $entry; - $data[$this->alias]['user_id'] = $userId; - $data[$this->alias]['position'] = $i++; - $this->create(); - $this->save($data); - } - } - -/** - * Returns details for named section - * - * @var string $userId User ID - * @var string $section Section name - * @return array - */ - public function getSection($userId = null, $section = null) { - $conditions = array( - "{$this->alias}.user_id" => $userId); - - if (!is_null($section)) { - $conditions["{$this->alias}.field LIKE"] = $section . '.%'; - } - - $results = $this->find('all', array( - 'recursive' => -1, - 'conditions' => $conditions, - 'fields' => array("{$this->alias}.field", "{$this->alias}.value"))); - - if (!empty($results)) { - foreach ($results as $result) { - list($prefix, $field) = explode('.', $result[$this->alias]['field']); - $userDetails[$prefix][$field] = $result[$this->alias]['value']; - } - $results = $userDetails; - } - return $results; - } - -/** - * Overriding this method to inject the active section schema - * - * @param mixed $field Set to true to reload schema, or a string to return a specific field - * @return array Array of table metadata - */ - public function schema($field = false) { - if (isset($this->activeSectionSchema) && !empty($this->sectionSchema[$this->activeSectionSchema])) { - return $this->sectionSchema[$this->activeSectionSchema]; - } - return parent::schema($field); - } - -/** - * Save details for named section - * - * @var string $userId User ID - * @var array $data Data - * @var string $section Section name - * @return boolean True on successful validation and saving of the virtual fields - */ - public function saveSection($userId = null, $data = null, $section = null) { - if (!empty($this->sectionSchema[$section])) { - $this->activeSectionSchema = $section; - - foreach ($data as $model => $userDetails) { - if ($model == $this->alias) { - foreach ($userDetails as $key => $value) { - $data[$model][$key] = $this->deconstruct($key, $value); - } - } - } - } - - if (!empty($this->sectionValidation[$section])) { - $tmpValidate = $this->validate; - $data = $this->set($data); - $this->validate = $this->sectionValidation[$section]; - if (!$this->validates()) { - return false; - } - $this->validate = $tmpValidate; - } - - if (isset($this->activeSectionSchema)) { - unset($this->activeSectionSchema); - } - - if (!empty($data) && is_array($data)) { - foreach ($data as $model => $userDetails) { - if ($model == $this->alias) { - // Save the details - foreach ($userDetails as $key => $value) { - $newUserDetail = array(); - $field = $section . '.' . $key; - $userDetail = $this->find('first', array( - 'recursive' => -1, - 'conditions' => array( - 'user_id' => $userId, - 'field' => $field), - 'fields' => array('id', 'field'))); - if (empty($userDetail)) { - $this->create(); - $newUserDetail[$model]['user_id'] = $userId; - } else { - $newUserDetail[$model]['id'] = $userDetail[$this->alias]['id']; - } - - $newUserDetail[$model]['field'] = $field; - $newUserDetail[$model]['value'] = $value; - $newUserDetail[$model]['input'] = ''; - $newUserDetail[$model]['data_type'] = ''; - $newUserDetail[$model]['label'] = ''; - $this->save($newUserDetail, false); - } - } elseif (isset($this->{$model})) { - // Save other model data - $toSave[$model] = $userDetails; - if (!empty($userId)) { - if ($model == 'User') { - $toSave[$model]['id'] = $userId; - } elseif ($this->{$model}->hasField('user_id')) { - $toSave[$model]['user_id'] = $userId; - } - } - $this->{$model}->save($toSave, false); - } - } - } - return true; - } -} diff --git a/Test/Case/AllUsersPluginTest.php b/Test/Case/AllUsersPluginTest.php index feae9adfe..a4ad671d4 100644 --- a/Test/Case/AllUsersPluginTest.php +++ b/Test/Case/AllUsersPluginTest.php @@ -22,11 +22,9 @@ public static function suite() { $basePath = CakePlugin::path('Users') . DS . 'Test' . DS . 'Case' . DS; // controllers - $suite->addTestFile($basePath . 'Controller' . DS . 'UserDetailsControllerTest.php'); $suite->addTestFile($basePath . 'Controller' . DS . 'UsersControllerTest.php'); // models - $suite->addTestFile($basePath . 'Model' . DS . 'UserDetailTest.php'); $suite->addTestFile($basePath . 'Model' . DS . 'UserTest.php'); return $suite; diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php index d45d003f5..667a8e5a2 100644 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -57,6 +57,7 @@ class RememberMeComponentTest extends CakeTestCase { */ public function setUp() { $_COOKIE = array(); + Configure::write('Config.language', 'eng'); $this->Controller = new RememberMeComponentTestController(new CakeRequest(), new CakeResponse()); $this->Controller->constructClasses(); diff --git a/Test/Case/Controller/UserDetailsControllerTest.php b/Test/Case/Controller/UserDetailsControllerTest.php deleted file mode 100644 index ae87ff009..000000000 --- a/Test/Case/Controller/UserDetailsControllerTest.php +++ /dev/null @@ -1,45 +0,0 @@ -UserDetails = new TestUserDetails(); - } - - function testDetailsControllerInstance() { - $this->assertTrue(is_a($this->UserDetails, 'UserDetailsController')); - } - - function tearDown() { - unset($this->UserDetails); - } -} diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 77a08d9ad..efd24bd3b 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -159,7 +159,6 @@ class UsersControllerTestCase extends CakeTestCase { */ public $fixtures = array( 'plugin.users.user', - 'plugin.users.user_detail' ); /** @@ -191,6 +190,7 @@ class UsersControllerTestCase extends CakeTestCase { public function setUp() { parent::setUp(); + Configure::write('Config.language', 'eng'); Configure::write('App.UserClass', null); $request = new CakeRequest(); @@ -463,21 +463,6 @@ public function testChangePassword() { $this->assertEqual($this->Users->redirectUrl, '/'); } -/** - * testEdit - * - * @return void - */ - public function testEdit() { - $this->Users->Session->write('Auth.User.id', '1'); - $this->Users->edit(); - $this->assertTrue(!empty($this->Users->data)); - - $this->Users->Session->write('Auth.User.id', 'INVALID-ID'); - $this->Users->edit(); - $this->assertTrue(empty($this->Users->data['User'])); - } - /** * testResetPassword * diff --git a/Test/Case/Model/UserDetailTest.php b/Test/Case/Model/UserDetailTest.php deleted file mode 100755 index 3953fde90..000000000 --- a/Test/Case/Model/UserDetailTest.php +++ /dev/null @@ -1,190 +0,0 @@ -UserDetail = ClassRegistry::init('Users.UserDetail'); - } - - public function tearDown() { - ClassRegistry::flush(); - unset($this->UserDetail); - } -/** - * testDetailInstance - * - * @return void - */ - public function testDetailInstance() { - $this->assertTrue(is_a($this->UserDetail, 'UserDetail')); - } - -/** - * testDetailFind - * - * @return void - */ - public function testUserDetailFind() { - $this->UserDetail->recursive = -1; - $results = $this->UserDetail->find('all'); - $this->assertTrue(!empty($results)); - $this->assertTrue(is_array($results)); - } - -/** - * testGetSection - * - * @return void - */ - public function testGetSection() { - $result = $this->UserDetail->getSection('47ea303a-3b2c-4251-b313-4816c0a800fa', 'User'); // phpnut - $this->assertTrue(is_array($result)); - $this->assertTrue(!empty($result)); - $this->assertEqual($result, array( - 'User' => array( - 'firstname' => 'Larry', - 'middlename' => 'E', - 'lastname' => 'Masters'))); - - - $result = $this->UserDetail->getSection('47ea303a-3b2c-4251-b313-4816c0a800fa', 'Blog'); // phpnut - $this->assertTrue(is_array($result)); - $this->assertTrue(!empty($result)); - $this->assertEqual($result, array( - 'Blog' => array( - 'name' => 'My blog'))); - - - $result = $this->UserDetail->getSection('47ea303a-3b2c-4251-b313-4816c0a800fa'); // phpnut - $this->assertTrue(is_array($result)); - $this->assertTrue(!empty($result)); - $this->assertEqual($result, array( - 'User' => array( - 'firstname' => 'Larry', - 'middlename' => 'E', - 'lastname' => 'Masters'), - 'Blog' => array( - 'name' => 'My blog'))); - } - -/** - * testSaveSection - * - * @return void - */ - public function testSaveSection() { - $data = array( - 'UserDetail' => array( - 'biography' => 'Lipsum...', - 'firstname' => 'Florian', - 'lastname' => 'Krämer')); - $this->UserDetail->saveSection('47ea303a-3cyc-k251-b313-4811c0a800bf', $data, 'User'); - $result = $this->UserDetail->getSection('47ea303a-3cyc-k251-b313-4811c0a800bf', 'User'); - $this->assertEqual($result, array( - 'User' => array( - 'biography' => 'Lipsum...', - 'firstname' => 'Florian', - 'lastname' => 'Krämer'))); - - - $data = array( - 'UserDetail' => array( - 'biography' => 'Lipsum...', - 'firstname' => 'Foo', - 'lastname' => 'Bar')); - $this->UserDetail->saveSection('47ea303a-3cyc-k251-b313-4811c0a800bf', $data, 'User'); - $result = $this->UserDetail->getSection('47ea303a-3cyc-k251-b313-4811c0a800bf', 'User'); - $this->assertEqual($result, array( - 'User' => array( - 'biography' => 'Lipsum...', - 'firstname' => 'Foo', - 'lastname' => 'Bar'))); - - - $data = array( - 'User' => array( - 'email' => 'foo@bar.com')); - $this->UserDetail->saveSection('47ea303a-3cyc-k251-b313-4811c0a800bf', $data, 'User'); - $result = $this->UserDetail->getSection('47ea303a-3cyc-k251-b313-4811c0a800bf', 'User'); - $this->UserDetail->User->id = '47ea303a-3cyc-k251-b313-4811c0a800bf'; - $result = $this->UserDetail->User->field('User.email'); - $this->assertEqual($result, 'foo@bar.com'); - } - -/** - * testDateSaving - * - * @return void - * @link https://github.com/CakeDC/users/issues/39 - */ - public function testDateSaving() { - $this->UserDetail->sectionSchema['User'] = array( - 'birthday' => array('type' => 'date'), - 'start_time' => array('type' => 'time'), - 'date_time' => array('type' => 'datetime')); - - $data = array( - 'UserDetail' => array( - 'date_time' => array( - 'day' => '01', - 'month' => '04', - 'year' => '1983', - 'hour' => '12', - 'min' => '35', - 'meridian' => 'pm'), - 'start_time' => array( - 'hour' => '12', - 'min' => '35', - 'meridian' => 'pm'), - 'birthday' => array( - 'day' => '01', - 'month' => '04', - 'year' => '1983'))); - - $this->UserDetail->saveSection('47ea303a-3cyc-k251-b313-4811c0a800bf', $data, 'User'); - $result = $this->UserDetail->getSection('47ea303a-3cyc-k251-b313-4811c0a800bf', 'User'); - - $this->assertEqual($result['User'], array( - 'birthday' => '1983-04-01', - 'date_time' => '1983-04-01 12:35:00', - 'start_time' => '12:35:00')); - } - -} diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index 870051388..70716c4ea 100644 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -38,7 +38,7 @@ class UserTestCase extends CakeTestCase { */ public $fixtures = array( 'plugin.users.user', - 'plugin.users.user_detail'); + ); /** * startTest diff --git a/Test/Fixture/UserDetailFixture.php b/Test/Fixture/UserDetailFixture.php deleted file mode 100644 index 1a72385dc..000000000 --- a/Test/Fixture/UserDetailFixture.php +++ /dev/null @@ -1,92 +0,0 @@ - array('type'=>'string', 'null' => false, 'length' => 36, 'key' => 'primary'), - 'user_id' => array('type'=>'string', 'null' => false, 'length' => 36), - 'position' => array('type'=>'float', 'null' => false, 'default' => '1', 'length' => 4), - 'field' => array('type'=>'string', 'null' => false, 'key' => 'index'), - 'value' => array('type'=>'text', 'null' => true, 'default' => NULL), - 'created' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'modified' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1), - 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1) - ) - ); - -/** - * Records - * - * @var array $records - */ - public $records = array( - array( - 'id' => '491d06d1-0648-407b-81f5-347182f0cb67', - 'user_id' => '47ea303a-3b2c-4251-b313-4816c0a800fa', //phpnut - 'position' => 2, - 'field' => 'User.firstname', - 'value' => 'Larry', - 'created' => '2008-03-25 01:47:31', - 'modified' => '2008-03-25 01:47:31'), - array( - 'id' => '491d06f0-b93c-43ba-9b79-346082f0cb67', - 'user_id' => '47ea303a-3b2c-4251-b313-4816c0a800fa',//phpnut - 'position' => 3, - 'field' => 'User.middlename', - 'value' => 'E', - 'created' => '2008-03-25 01:47:31', - 'modified' => '2008-03-25 01:47:31'), - array( - 'id' => '491d0704-5e68-4de2-92c7-345c82f0cb67', - 'user_id' => '47ea303a-3b2c-4251-b313-4816c0a800fa',//phpnut - 'position' => 4, - 'field' => 'User.lastname', - 'value' => 'Masters', - 'created' => '2008-03-25 01:47:31', - 'modified' => '2008-03-25 01:47:31'), - array( - 'id' => '491d0704-5e68-4de3-92c7-345c82f0cb67', - 'user_id' => '47ea303a-3b2c-4251-b313-4816c0a800fa',//phpnut - 'position' => 5, - 'field' => 'Blog.name', - 'value' => 'My blog', - 'created' => '2008-03-25 01:47:31', - 'modified' => '2008-03-25 01:47:31') - ); -} diff --git a/View/UserDetails/add.ctp b/View/UserDetails/add.ctp deleted file mode 100644 index 064854c91..000000000 --- a/View/UserDetails/add.ctp +++ /dev/null @@ -1,31 +0,0 @@ - -
-Form->create('UserDetail'); ?> -
- - Form->input('user_id'); - echo $this->Form->input('position'); - echo $this->Form->input('field'); - echo $this->Form->input('value'); - ?> -
-Form->end(__d('users', 'Submit')); ?> -
-
-
    -
  • Html->link(__d('users', 'List Details'), array('action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'List Users'), array('controller' => 'users', 'action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New User'), array('controller' => 'users', 'action' => 'add')); ?>
  • -
-
diff --git a/View/UserDetails/admin_add.ctp b/View/UserDetails/admin_add.ctp deleted file mode 100644 index 064854c91..000000000 --- a/View/UserDetails/admin_add.ctp +++ /dev/null @@ -1,31 +0,0 @@ - -
-Form->create('UserDetail'); ?> -
- - Form->input('user_id'); - echo $this->Form->input('position'); - echo $this->Form->input('field'); - echo $this->Form->input('value'); - ?> -
-Form->end(__d('users', 'Submit')); ?> -
-
-
    -
  • Html->link(__d('users', 'List Details'), array('action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'List Users'), array('controller' => 'users', 'action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New User'), array('controller' => 'users', 'action' => 'add')); ?>
  • -
-
diff --git a/View/UserDetails/admin_edit.ctp b/View/UserDetails/admin_edit.ctp deleted file mode 100644 index ab19c6261..000000000 --- a/View/UserDetails/admin_edit.ctp +++ /dev/null @@ -1,33 +0,0 @@ - -
-Form->create('UserDetail'); ?> -
- - Form->input('id'); - echo $this->Form->input('user_id'); - echo $this->Form->input('position'); - echo $this->Form->input('field'); - echo $this->Form->input('value'); - ?> -
-Form->end('Submit'); ?> -
-
-
    -
  • Html->link(__d('users', 'Delete'), array('action' => 'delete', $this->Form->value('UserDetail.id')), null, sprintf(__d('users', 'Are you sure you want to delete # %s?'), $this->Form->value('UserDetail.id'))); ?>
  • -
  • Html->link(__d('users', 'List Details'), array('action' => 'index'));?>
  • -
  • Html->link(__d('users', 'List Users'), array('controller' => 'users', 'action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New User'), array('controller' => 'users', 'action' => 'add')); ?>
  • -
-
diff --git a/View/UserDetails/admin_index.ctp b/View/UserDetails/admin_index.ctp deleted file mode 100644 index eb251218d..000000000 --- a/View/UserDetails/admin_index.ctp +++ /dev/null @@ -1,76 +0,0 @@ - -
-

-

Paginator->counter(array( - 'format' => __d('users', 'Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%') -)); -?>

- - - - - - - - - - - - - > - - - - - - - - - - -
Paginator->sort('id');?>Paginator->sort('user_id');?>Paginator->sort('position');?>Paginator->sort('field');?>Paginator->sort('value');?>Paginator->sort('created');?>Paginator->sort('modified');?>
- - - Html->link($user_detail['User']['id'], array('controller' => 'users', 'action' => 'view', $user_detail['User']['id'])); ?> - - - - - - - - - - - - Html->link(__d('users', 'View'), array('action'=>'view', $user_detail['UserDetail']['id'])); ?> - Html->link(__d('users', 'Edit'), array('action'=>'edit', $user_detail['UserDetail']['id'])); ?> - Html->link(__d('users', 'Delete'), array('action'=>'delete', $user_detail['UserDetail']['id']), null, sprintf(__d('users', 'Are you sure you want to delete # %s?'), $user_detail['UserDetail']['id'])); ?> -
-
-element('Users.pagination'); ?> -
-
    -
  • Html->link(__d('users', 'New User Detail'), array('action' => 'add')); ?>
  • -
  • Html->link(__d('users', 'List Users'), array('controller' => 'users', 'action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New User'), array('controller' => 'users', 'action' => 'add')); ?>
  • -
-
diff --git a/View/UserDetails/admin_view.ctp b/View/UserDetails/admin_view.ctp deleted file mode 100644 index 1b919b94a..000000000 --- a/View/UserDetails/admin_view.ctp +++ /dev/null @@ -1,61 +0,0 @@ - -
-

-
- > - > - -   - - > - > - Html->link($user_detail['User']['id'], array('controller'=> 'users', 'action' => 'view', $user_detail['User']['id'])); ?> -   - - > - > - -   - - > - > - -   - - > - > - -   - - > - > - -   - - > - > - -   - -
-
-
-
    -
  • Html->link(__d('users', 'Edit Detail'), array('action' => 'edit', $user_detail['UserDetail']['id'])); ?>
  • -
  • Html->link(__d('users', 'Delete Detail'), array('action' => 'delete', $user_detail['UserDetail']['id']), null, sprintf(__d('users', 'Are you sure you want to delete # %s?'), $user_detail['UserDetail']['id'])); ?>
  • -
  • Html->link(__d('users', 'List Details'), array('action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New Detail'), array('action' => 'add')); ?>
  • -
  • Html->link(__d('users', 'List Users'), array('controller' => 'users', 'action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New User'), array('controller' => 'users', 'action' => 'add')); ?>
  • -
-
\ No newline at end of file diff --git a/View/UserDetails/edit.ctp b/View/UserDetails/edit.ctp deleted file mode 100644 index 949db3f57..000000000 --- a/View/UserDetails/edit.ctp +++ /dev/null @@ -1,25 +0,0 @@ - -
-Form->create('UserDetail', array('action' => 'edit')); ?> -
- - Form->input('firstname'); - echo $this->Form->input('middlename'); - echo $this->Form->input('lastname'); - echo $this->Form->input('biography'); - echo $this->Form->input('birthday'); - ?> -
-Form->end('Submit'); ?> -
\ No newline at end of file diff --git a/View/UserDetails/index.ctp b/View/UserDetails/index.ctp deleted file mode 100644 index c2ee3cfce..000000000 --- a/View/UserDetails/index.ctp +++ /dev/null @@ -1,28 +0,0 @@ -Form->create('UserDetail'); - foreach ($user_details as $user_detail) { - $options = array(); - $options['type'] = $user_detail['UserDetail']['input']; - if ($user_detail['UserDetail']['input'] == 'checkbox') { - if ($user_detail['UserDetail']['value'] == 1) { - $options['checked'] = true; - } - } - if ($user_detail['UserDetail']['input'] == 'text' || $user_detail['UserDetail']['input'] == 'textarea' ) { - $options['value'] = $user_detail['UserDetail']['value']; - } - echo $this->Form->input($user_detail['UserDetail']['field'], ($options)); - } - echo $this->Form->end(__d('users', 'Submit')); -} diff --git a/View/UserDetails/view.ctp b/View/UserDetails/view.ctp deleted file mode 100644 index 60495ba4a..000000000 --- a/View/UserDetails/view.ctp +++ /dev/null @@ -1,62 +0,0 @@ - -
-

-
- > - > - -   - - > - > - Html->link($user_detail['User']['id'], array('controller' => 'users', 'action' => 'view', $user_detail['User']['id'])); ?> -   - - > - > - -   - - > - > - -   - - > - > - -   - - > - > - -   - - > - > - -   - -
-
- -
-
    -
  • Html->link(__d('users', 'Edit Detail'), array('action' => 'edit', $user_detail['UserDetail']['id'])); ?>
  • -
  • Html->link(__d('users', 'Delete Detail'), array('action' => 'delete', $user_detail['UserDetail']['id']), null, sprintf(__d('users', 'Are you sure you want to delete # %s?'), $user_detail['UserDetail']['id'])); ?>
  • -
  • Html->link(__d('users', 'List Details'), array('action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New Detail'), array('action' => 'add')); ?>
  • -
  • Html->link(__d('users', 'List Users'), array('controller' => 'users', 'action' => 'index')); ?>
  • -
  • Html->link(__d('users', 'New User'), array('controller' => 'users', 'action' => 'add')); ?>
  • -
-
From 46553dc6601bd22d62ca60028e4defa6a27cb18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 4 Aug 2013 18:37:05 +0200 Subject: [PATCH 0059/1476] Cleaning up User::_findSearch --- Controller/UsersController.php | 2 +- Model/User.php | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index f6ad3d357..cb4ad7670 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -256,7 +256,7 @@ public function admin_index() { unset($this->{$this->modelClass}->validate['username']); unset($this->{$this->modelClass}->validate['email']); $this->{$this->modelClass}->data[$this->modelClass] = $this->passedArgs; - if ($this->{$this->modelClass}->Behaviors->attached('Searchable')) { + if ($this->{$this->modelClass}->Behaviors->loaded('Searchable')) { $parsedConditions = $this->{$this->modelClass}->parseCriteria($this->passedArgs); } else { $parsedConditions = array(); diff --git a/Model/User.php b/Model/User.php index 64e7ed99a..efeb54527 100644 --- a/Model/User.php +++ b/Model/User.php @@ -754,24 +754,21 @@ protected function _beforeRegistration($postData = array(), $useEmailVerificatio * @link https://github.com/CakeDC/search */ protected function _findSearch($state, $query, $results = array()) { - if (!App::import('Lib', 'Utils.Languages')) { + if (!class_exists('SearchableBehavior')) { throw new MissingPluginException(array('plugin' => 'Search')); } if ($state == 'before') { - $this->Behaviors->attach('Containable', array('autoFields' => false)); + $this->Behaviors->load('Containable', array( + 'autoFields' => false) + ); $results = $query; - if (!empty($query['by'])) { - $by = $query['by']; - } if (empty($query['search'])) { $query['search'] = ''; } - $db = ConnectionManager::getDataSource($this->useDbConfig); $by = $query['by']; - $search = $query['search']; $like = '%' . $query['search'] . '%'; switch ($by) { @@ -804,9 +801,8 @@ protected function _findSearch($state, $query, $results = array()) { if (isset($query['operation']) && $query['operation'] == 'count') { $results['fields'] = array('COUNT(DISTINCT ' . $this->alias . '.id)'); - } else { - //$results['fields'] = array('DISTINCT User.*'); } + return $results; } elseif ($state == 'after') { if (isset($query['operation']) && $query['operation'] == 'count') { From c23ab4d1b58e4e77e24b3998195b49f4f5c081c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 4 Aug 2013 18:43:22 +0200 Subject: [PATCH 0060/1476] Refs #129 Updating documentation --- Model/User.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Model/User.php b/Model/User.php index efeb54527..5c2abf26e 100644 --- a/Model/User.php +++ b/Model/User.php @@ -838,7 +838,10 @@ public function paginateCount($conditions = array(), $recursive = 0, $extra = ar /** * Adds a new user - * + * + * The difference to register() is that this method here is intended to be used + * by admins to add new users without going through all the registration logic + * * @param array post data, should be Controller->data * @return boolean True if the data was saved successfully. */ From 39157f2b2167a2f22074bd4f998327999901c091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 4 Aug 2013 19:21:51 +0200 Subject: [PATCH 0061/1476] Removing User::sluggedUserUrl - this is somehow redundant and not needed because it can be done via routes and the user slug --- Model/User.php | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/Model/User.php b/Model/User.php index 5c2abf26e..defa7c17e 100644 --- a/Model/User.php +++ b/Model/User.php @@ -203,32 +203,6 @@ public function setupDetail() { 'rule' => array('notEmpty'), 'allowEmpty' => true, 'message' => __d('users', 'Invalid date')))); } -/** - * After save callback - * - * @param boolean $created - * @return void - */ - public function afterSave($created) { - if ($created) { - $this->sluggedUserUrl(); - } - } - -/** - * Override this method as needed to generate the url you want - * - * @return void - * @see User::afterSave(); - */ - public function sluggedUserUrl() { - if (!empty($this->data[$this->alias]['slug'])) { - if ($this->hasField('url')) { - $this->saveField('url', '/user/' . $this->data[$this->alias]['slug'], false); - } - } - } - /** * afterFind callback * From 1997e0ee913eccc3b2f9f65b97b89f8f8ce766f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 5 Aug 2013 02:29:24 +0200 Subject: [PATCH 0062/1476] Removing the Gravatar Helper dependency, its not used in any views so no need to add it. Also fixing the UsersController::search(). --- Controller/UsersController.php | 25 ++++++++++--------------- Model/User.php | 4 +++- View/Users/search.ctp | 2 +- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index ee1249148..f1d5e3773 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -84,7 +84,6 @@ class UsersController extends UsersAppController { */ public function __construct($request, $response) { $this->_setupComponents(); - $this->_setupHelpers(); parent::__construct($request, $response); $this->_reInitControllerName(); } @@ -118,25 +117,21 @@ protected function _pluginDot() { } /** - * Setup components based on plugin availability * - * @return void - * @link https://github.com/CakeDC/search */ - protected function _setupComponents() { - if (App::import('Component', 'Search.Prg')) { - $this->components[] = 'Search.Prg'; - } + protected function _pluginLoaded($plugin) { + return CakePlugin::loaded($plugin); } /** - * Setup helpers based on plugin availability + * Setup components based on plugin availability * * @return void + * @link https://github.com/CakeDC/search */ - protected function _setupHelpers() { - if (App::import('Helper', 'Goodies.Gravatar')) { - $this->helpers[] = 'Goodies.Gravatar'; + protected function _setupComponents() { + if ($this->_pluginLoaded('Search')) { + $this->components[] = 'Search.Prg'; } } @@ -417,12 +412,12 @@ public function login() { * @link https://github.com/CakeDC/search */ public function search() { - if (!App::import('Component', 'Search.Prg')) { + if (!$this->_pluginLoaded('Search')) { throw new MissingPluginException(array('plugin' => 'Search')); } $searchTerm = ''; - $this->Prg->commonProcess($this->modelClass, $this->modelClass, 'search', false); + $this->Prg->commonProcess($this->modelClass); $by = null; if (!empty($this->request->params['named']['search'])) { @@ -615,7 +610,7 @@ public function reset_password($token = null, $user = null) { * @link https://github.com/CakeDC/utils */ protected function _setLanguages($viewVar = 'languages') { - if (!App::import('Lib', 'Utils.Languages')) { + if (!$this->_pluginLoaded('Utils')) { throw new MissingPluginException(array('plugin' => 'Utils')); } $Languages = new Languages(); diff --git a/Model/User.php b/Model/User.php index 63993d8ef..2ee71ca05 100644 --- a/Model/User.php +++ b/Model/User.php @@ -32,7 +32,9 @@ class User extends UsersAppModel { * * @var array */ - public $findMethods = array('search' => true); + public $findMethods = array( + 'search' => true + ); /** * All search fields need to be configured in the Model::filterArgs array. diff --git a/View/Users/search.ctp b/View/Users/search.ctp index fec064cae..862945fad 100644 --- a/View/Users/search.ctp +++ b/View/Users/search.ctp @@ -58,6 +58,6 @@ - element('Users.pagination'); ?> + element('Users.paging'); ?> element('Users.Users/sidebar'); ?> \ No newline at end of file From c4d3681e882d7e503abcb9d8cbf272c69e96bae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 14 Aug 2013 22:50:28 +0200 Subject: [PATCH 0063/1476] Refactoring the code of the plugin to make it easier to extend it without the need to override a lot of code. --- Controller/UsersController.php | 31 +++--- Model/User.php | 178 +++++++++++++++++---------------- Model/UsersAppModel.php | 9 +- 3 files changed, 120 insertions(+), 98 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 036423802..6769de4d1 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -119,8 +119,12 @@ protected function _pluginDot() { /** * */ - protected function _pluginLoaded($plugin) { - return CakePlugin::loaded($plugin); + protected function _pluginLoaded($plugin, $exception = true) { + $result = CakePlugin::loaded($plugin); + if ($exception === true && $result === false) { + throw new MissingPluginException(array('plugin' => $plugin)); + } + return $result; } /** @@ -130,7 +134,7 @@ protected function _pluginLoaded($plugin) { * @link https://github.com/CakeDC/search */ protected function _setupComponents() { - if ($this->_pluginLoaded('Search')) { + if ($this->_pluginLoaded('Search', false)) { $this->components[] = 'Search.Prg'; } } @@ -158,6 +162,7 @@ public function beforeFilter() { */ protected function _setupAuth() { $this->Auth->allow('add', 'reset', 'verify', 'logout', 'view', 'reset_password', 'login', 'resend_verification'); + if (!is_null(Configure::read('Users.allowRegistration')) && !Configure::read('Users.allowRegistration')) { $this->Auth->deny('add'); } @@ -239,11 +244,13 @@ public function admin_index() { unset($this->{$this->modelClass}->validate['username']); unset($this->{$this->modelClass}->validate['email']); $this->{$this->modelClass}->data[$this->modelClass] = $this->passedArgs; + if ($this->{$this->modelClass}->Behaviors->loaded('Searchable')) { $parsedConditions = $this->{$this->modelClass}->parseCriteria($this->passedArgs); } else { $parsedConditions = array(); } + $this->Paginator->settings[$this->modelClass]['conditions'] = $parsedConditions; $this->Paginator->settings[$this->modelClass]['order'] = array($this->modelClass . '.created' => 'desc'); @@ -258,11 +265,14 @@ public function admin_index() { * @return void */ public function admin_view($id = null) { - if (!$id) { + try { + $user = $this->{$this->modelClass}->view($id, 'id'); + } catch (NotFoundException $e) { $this->Session->setFlash(__d('users', 'Invalid User.')); $this->redirect(array('action' => 'index')); } - $this->set('user', $this->{$this->modelClass}->read(null, $id)); + + $this->set('user', $user); } /** @@ -412,9 +422,7 @@ public function login() { * @link https://github.com/CakeDC/search */ public function search() { - if (!$this->_pluginLoaded('Search')) { - throw new MissingPluginException(array('plugin' => 'Search')); - } + $this->_pluginLoaded('Search'); $searchTerm = ''; $this->Prg->commonProcess($this->modelClass); @@ -520,7 +528,7 @@ public function request_new_password($token = null) { throw new NotFoundException(); } - $data = $this->{$this->modelClass}->validateToken($token, true); + $data = $this->{$this->modelClass}->verifyEmail($token); if (!$data) { $this->Session->setFlash(__d('users', 'The url you accessed is not longer valid')); @@ -610,9 +618,8 @@ public function reset_password($token = null, $user = null) { * @link https://github.com/CakeDC/utils */ protected function _setLanguages($viewVar = 'languages') { - if (!$this->_pluginLoaded('Utils')) { - throw new MissingPluginException(array('plugin' => 'Utils')); - } + $this->_pluginLoaded('Utils'); + $Languages = new Languages(); $this->set($viewVar, $Languages->lists('locale')); } diff --git a/Model/User.php b/Model/User.php index 2ee71ca05..d2b18d673 100644 --- a/Model/User.php +++ b/Model/User.php @@ -207,14 +207,13 @@ public function confirmEmail($email = null) { } /** - * Verifies a users email by a token that was sent to him via email and flags the user record as active + * Checks the token for email verification * - * @param string $token The token that wa sent to the user - * @throws RuntimeException - * @return array On success it returns the user data record + * @param string $token + * @return array */ - public function verifyEmail($token = null) { - $user = $this->find('first', array( + public function checkEmailVerfificationToken($token = null) { + $result = $this->find('first', array( 'contain' => array(), 'conditions' => array( $this->alias . '.email_verified' => 0, @@ -222,7 +221,24 @@ public function verifyEmail($token = null) { 'fields' => array( 'id', 'email', 'email_token_expires', 'role'))); - if (empty($user)) { + if (empty($result)) { + return false; + } + + return $result; + } + +/** + * Verifies a users email by a token that was sent to him via email and flags the user record as active + * + * @param string $token The token that wa sent to the user + * @throws RuntimeException + * @return array On success it returns the user data record + */ + public function verifyEmail($token = null) { + $user = $this->checkEmailVerfificationToken($token); + + if ($user === false) { throw new RuntimeException(__d('users', 'Invalid token, please check the email you were sent, and retry the verification link.')); } @@ -243,55 +259,10 @@ public function verifyEmail($token = null) { return $user; } -/** - * Validates the user token - * - * @deprecated See verifyEmail() - * @param string $token Token - * @param boolean $reset Reset boolean - * @param boolean $now time() value - * @return mixed false or user data - */ - public function validateToken($token = null, $reset = false, $now = null) { - if (!$now) { - $now = time(); - } - - $data = false; - $match = $this->find('first', array( - 'contain' => array(), - 'conditions' => array( - $this->alias . '.email_token' => $token), - 'fields' => array( - 'id', 'email', 'email_token_expires', 'role'))); - - if (!empty($match)) { - $expires = strtotime($match[$this->alias]['email_token_expires']); - if ($expires > $now) { - $data[$this->alias]['id'] = $match[$this->alias]['id']; - $data[$this->alias]['email'] = $match[$this->alias]['email']; - $data[$this->alias]['email_verified'] = '1'; - $data[$this->alias]['role'] = $match[$this->alias]['role']; - - if ($reset === true) { - $newPassword = $this->generatePassword(); - $data[$this->alias]['password'] = $this->hash($newPassword, null, true); - $data[$this->alias]['new_password'] = $newPassword; - $data[$this->alias]['password_token'] = null; - } - - $data[$this->alias]['email_token'] = null; - $data[$this->alias]['email_token_expires'] = null; - } - } - - return $data; - } - /** * Updates the last activity field of a user * - * @param string $user User ID + * @param string $userId User id * @param string $field Default is "last_action", changing it allows you to use this method also for "last_login" for example * @return boolean True on success */ @@ -312,8 +283,8 @@ public function updateLastActivity($userId = null, $field = 'last_action') { * @return mixed False or user data as array on success */ public function passwordReset($postData = array()) { - $this->recursive = -1; $user = $this->find('first', array( + 'contain' => array(), 'conditions' => array( $this->alias . '.active' => 1, $this->alias . '.email' => $postData[$this->alias]['email']))); @@ -354,6 +325,20 @@ public function checkPasswordToken($token = null) { return $user; } +/** + * Changes the validation rules for the User::resetPassword() method + * + * @return array Set of rules required for the User::resetPassword() method + */ + public function setUpResetPasswordValidationRules() { + return array( + 'new_password' => $this->validate['password'], + 'confirm_password' => array( + 'required' => array( + 'rule' => array('compareFields', 'new_password', 'confirm_password'), + 'message' => __d('users', 'The passwords are not equal.')))); + } + /** * Resets the password * @@ -363,13 +348,8 @@ public function checkPasswordToken($token = null) { public function resetPassword($postData = array()) { $result = false; - $tmp = $this->validate; - $this->validate = array( - 'new_password' => $tmp['password'], - 'confirm_password' => array( - 'required' => array( - 'rule' => array('compareFields', 'new_password', 'confirm_password'), - 'message' => __d('users', 'The passwords are not equal.')))); + //$tmp = $this->validate; + //$this->validate = $this->setUpResetPasswordValidationRules(); $this->set($postData); if ($this->validates()) { @@ -380,7 +360,7 @@ public function resetPassword($postData = array()) { 'callbacks' => false)); } - $this->validate = $tmp; + //$this->validate = $tmp; return $result; } @@ -444,27 +424,49 @@ public function compareFields($field1, $field2) { /** * Returns all data about a user * - * @param string $slug user slug or the uuid of a user - * @throws OutOfBoundsException + * @param string|integer $slug user slug or the uuid of a user + * @param string $field + * @throws NotFoundException * @return array */ - public function view($slug = null) { + public function view($slug = null, $field = 'slug') { $user = $this->find('first', array( 'contain' => array(), 'conditions' => array( 'OR' => array( - $this->alias . '.slug' => $slug, + $this->alias . '.' . $field => $slug, $this->alias . '.' . $this->primaryKey => $slug), $this->alias . '.active' => 1, $this->alias . '.email_verified' => 1))); if (empty($user)) { - throw new OutOfBoundsException(__d('users', 'The user does not exist.')); + throw new NotFoundException(__d('users', 'The user does not exist.')); } return $user; } +/** + * Finds an user simply by email + * + * Used by the following methods: + * - checkEmailVerification + * - resendVerification + * + * Override it as needed, to add additional models to contain for example + * + * @param string $email + * @return array + */ + public function findByEmail($email = null) { + return $this->find('first', array( + 'contain' => array(), + 'conditions' => array( + $this->alias . '.email' => $email, + ) + )); + } + /** * Checks if an email is already verified and if not renews the expiration time * @@ -473,12 +475,7 @@ public function view($slug = null) { * @return bool True if the email was not already verified */ public function checkEmailVerification($postData = array(), $renew = true) { - $user = $this->find('first', array( - 'contain' => array('Profile'), - 'conditions' => array( - $this->alias . '.email' => $postData[$this->alias]['email'] - ) - )); + $user = $this->findByEmail($postData[$this->alias]['email']); if (empty($user)) { $this->invalidate('email', __d('users', 'Invalid Email address.')); @@ -501,7 +498,6 @@ public function checkEmailVerification($postData = array(), $renew = true) { $this->data = $user; return true; } - } /** @@ -559,10 +555,7 @@ public function resendVerification($postData = array()) { return false; } - $user = $this->find('first', array( - 'contain' => array(), - 'conditions' => array( - $this->alias . '.email' => $postData[$this->alias]['email']))); + $user = $this->findByEmail($postData[$this->alias]['email']); if (empty($user)) { $this->invalidate('email', __d('users', 'The email address does not exist in the system')); @@ -796,14 +789,8 @@ public function add($postData = null) { * @return mixed True on successfully save else post data as array */ public function edit($userId = null, $postData = null) { - $user = $this->find('first', array( - 'contain' => array(), - 'conditions' => array($this->alias . '.id' => $userId))); - + $user = $this->getUserForEditing($userId); $this->set($user); - if (empty($user)) { - throw new OutOfBoundsException(__d('users', 'Invalid User')); - } if (!empty($postData)) { $this->set($postData); @@ -817,6 +804,26 @@ public function edit($userId = null, $postData = null) { } } +/** + * Gets the user data that needs to be edited + * + * Override this method and inject the conditions you need + */ + public function getUserForEditing($userId = null, $options = array()) { + $defaults = array( + 'contain' => array(), + 'conditions' => array($this->alias . '.id' => $userId)); + $options = Set::merge($defaults, $options); + + $user = $this->find('first', $options); + + if (empty($user)) { + throw new NotFoundException(__d('users', 'Invalid User')); + } + + return $user; + } + /** * Removes all users from the user table that are outdated * @@ -829,4 +836,5 @@ protected function _removeExpiredRegistrations() { $this->alias . '.email_verified' => 0, $this->alias . '.email_token_expires <' => date('Y-m-d H:i:s'))); } + } diff --git a/Model/UsersAppModel.php b/Model/UsersAppModel.php index 252a786d2..c129eaf5e 100644 --- a/Model/UsersAppModel.php +++ b/Model/UsersAppModel.php @@ -26,6 +26,13 @@ class UsersAppModel extends AppModel { */ public $plugin = 'Users'; +/** + * Recursive level for finds + * + * @var integer + */ + public $recursive = -1; + /** * Behaviors * @@ -41,7 +48,7 @@ class UsersAppModel extends AppModel { * @param array * @param integer * @param array - * @return + * @return mixed */ public function paginateCount($conditions = array(), $recursive = 0, $extra = array()) { $parameters = compact('conditions'); From b11e0601ae4369660ace50d0a3bdc0ff1793a043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 25 Aug 2013 22:59:01 +0200 Subject: [PATCH 0064/1476] Updating the readme.md php blocks --- readme.md | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index be4021668..cb5fbf329 100644 --- a/readme.md +++ b/readme.md @@ -41,8 +41,10 @@ The default password reset process requires the user to enter his email address, To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. +```php public $components = array( 'Users.RememberMe'); +``` If you are using another user model than 'User' you'll have to configure it: @@ -52,14 +54,18 @@ If you are using another user model than 'User' you'll have to configure it: And add this line +```php $this->RememberMe->restoreLoginFromCookie() +``` to your controllers beforeFilter() callack +```php public function beforeFilter() { parent::beforeFilter(); $this->RememberMe->restoreLoginFromCookie(); } +``` The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. @@ -69,7 +75,9 @@ The code will read the login credentials from the cookie and log the user in bas To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php +```php Configure::write('App.defaultEmail', your@email.com); +``` If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. @@ -77,21 +85,26 @@ If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from ema Declare the controller class +```php App::uses('UsersController', 'Users.Controller'); class AppUsersController extends UsersController { - public $name = 'AppUsers'; + public $name = 'AppUsers'; } +``` In the case you want to extend also the user model it's required to set the right user class in the beforeFilter() because the controller will use the inherited model which would be Users.User. +```php public function beforeFilter() { parent::beforeFilter(); $this->User = ClassRegistry::init('AppUser'); - $this->set('model', 'AppUser'); + $this->set('model', 'AppUser'); } +``` You can overwrite the render() method to fall back to the plugin views in the case you want to use some of them +```php public function render($view = null, $layout = null) { if (is_null($view)) { $view = $this->action; @@ -104,6 +117,7 @@ You can overwrite the render() method to fall back to the plugin views in the ca } return parent::render($view, $layout); } +``` Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory @@ -111,25 +125,31 @@ Note: Depending on the CakePHP version you are using, you might need to bring a To use the basics the plugin already offers but changing some of the settings overwrite the _setupAuth() method in the extending controller. +```php protected function _setupAuth() { parent::_setupAuth(); $this->Auth->loginRedirect = array('plugin' => null, 'admin' => false, 'controller' => 'app_users', 'action' => 'login'); } +``` If you want to disable it simply overwrite it without any body +```php protected function _setupAuth() { } +``` ### Extending the model ### Declare the model +```php App::uses('User', 'Users.Model'); class AppUser extends User { public $useTable = 'users'; } +``` It's important to override the AppUser::useTable property with the 'users' table. @@ -141,10 +161,13 @@ To remove the second users from /users/users in the url you can use routes. The plugin itself comes with a routes file but you need to explicitly load them. +```php CakePlugin::load('Users', array('routes' => true)); +``` List of the used routes: +```php Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); @@ -152,6 +175,7 @@ List of the used routes: Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); +``` If you're extending the plugin remove the plugin from the route by setting it to null and replace the controller with your controller extending the plugins users controller. @@ -184,7 +208,9 @@ The plugin uses the $default email configuration (should be present in your Conf You can add Users.roles on bootstrap.php file and these roles will be used on Admin Add / Edit pages. i.e: +```php Configure::write('Users.roles', array('admin' => 'Admin', 'registered' => 'Registered')); +``` If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered role setting Users.defaultRole on bootstrap.php. i.e: From a17cafe2a77eebb0ae12d8e0a69b2c849bb48e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 25 Aug 2013 23:16:39 +0200 Subject: [PATCH 0065/1476] Updating the readme.md --- readme.md | 110 +++++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/readme.md b/readme.md index cb5fbf329..928054326 100644 --- a/readme.md +++ b/readme.md @@ -42,8 +42,9 @@ The default password reset process requires the user to enter his email address, To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. ```php - public $components = array( - 'Users.RememberMe'); +public $components = array( + 'Users.RememberMe' +); ``` If you are using another user model than 'User' you'll have to configure it: @@ -55,16 +56,16 @@ If you are using another user model than 'User' you'll have to configure it: And add this line ```php - $this->RememberMe->restoreLoginFromCookie() +$this->RememberMe->restoreLoginFromCookie() ``` to your controllers beforeFilter() callack ```php - public function beforeFilter() { - parent::beforeFilter(); - $this->RememberMe->restoreLoginFromCookie(); - } +public function beforeFilter() { + parent::beforeFilter(); + $this->RememberMe->restoreLoginFromCookie(); +} ``` The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. @@ -76,7 +77,7 @@ The code will read the login credentials from the cookie and log the user in bas To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php ```php - Configure::write('App.defaultEmail', your@email.com); +Configure::write('App.defaultEmail', your@email.com); ``` If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. @@ -86,37 +87,37 @@ If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from ema Declare the controller class ```php - App::uses('UsersController', 'Users.Controller'); - class AppUsersController extends UsersController { - public $name = 'AppUsers'; - } +App::uses('UsersController', 'Users.Controller'); +class AppUsersController extends UsersController { + public $name = 'AppUsers'; +} ``` In the case you want to extend also the user model it's required to set the right user class in the beforeFilter() because the controller will use the inherited model which would be Users.User. ```php - public function beforeFilter() { - parent::beforeFilter(); - $this->User = ClassRegistry::init('AppUser'); - $this->set('model', 'AppUser'); - } +public function beforeFilter() { + parent::beforeFilter(); + $this->User = ClassRegistry::init('AppUser'); + $this->set('model', 'AppUser'); +} ``` You can overwrite the render() method to fall back to the plugin views in the case you want to use some of them ```php - public function render($view = null, $layout = null) { - if (is_null($view)) { - $view = $this->action; - } - $viewPath = substr(get_class($this), 0, strlen(get_class($this)) - 10); - if (!file_exists(APP . 'View' . DS . $viewPath . DS . $view . '.ctp')) { - $this->plugin = 'Users'; - } else { - $this->viewPath = $viewPath; - } - return parent::render($view, $layout); +public function render($view = null, $layout = null) { + if (is_null($view)) { + $view = $this->action; } + $viewPath = substr(get_class($this), 0, strlen(get_class($this)) - 10); + if (!file_exists(APP . 'View' . DS . $viewPath . DS . $view . '.ctp')) { + $this->plugin = 'Users'; + } else { + $this->viewPath = $viewPath; + } + return parent::render($view, $layout); +} ``` Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory @@ -126,18 +127,22 @@ Note: Depending on the CakePHP version you are using, you might need to bring a To use the basics the plugin already offers but changing some of the settings overwrite the _setupAuth() method in the extending controller. ```php - protected function _setupAuth() { - parent::_setupAuth(); - - $this->Auth->loginRedirect = array('plugin' => null, 'admin' => false, 'controller' => 'app_users', 'action' => 'login'); - } +protected function _setupAuth() { + parent::_setupAuth(); + $this->Auth->loginRedirect = array( + 'plugin' => null, + 'admin' => false, + 'controller' => 'app_users', + 'action' => 'login' + ); +} ``` If you want to disable it simply overwrite it without any body ```php - protected function _setupAuth() { - } +protected function _setupAuth() { +} ``` ### Extending the model ### @@ -145,10 +150,10 @@ If you want to disable it simply overwrite it without any body Declare the model ```php - App::uses('User', 'Users.Model'); - class AppUser extends User { - public $useTable = 'users'; - } +App::uses('User', 'Users.Model'); +class AppUser extends User { + public $useTable = 'users'; +} ``` It's important to override the AppUser::useTable property with the 'users' table. @@ -162,19 +167,19 @@ To remove the second users from /users/users in the url you can use routes. The plugin itself comes with a routes file but you need to explicitly load them. ```php - CakePlugin::load('Users', array('routes' => true)); +CakePlugin::load('Users', array('routes' => true)); ``` List of the used routes: ```php - Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); - Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); - Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); - Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); - Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); - Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); - Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); +Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); +Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); +Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); ``` If you're extending the plugin remove the plugin from the route by setting it to null and replace the controller with your controller extending the plugins users controller. @@ -191,7 +196,6 @@ Note that you will have to overwrite any view that is linking to the plugin like ## Configuration options - ### Disable Slugs If the Utils plugin is present the users model will auto attach and use the sluggable behavior. @@ -202,19 +206,23 @@ To not create slugs for a new user records put this in your configuration: Confi The plugin uses the $default email configuration (should be present in your Config/email.php file), but you can override it using - Configure::write('Users.emailConfig', 'default'); +```php +Configure::write('Users.emailConfig', 'default'); +``` ## Roles Management You can add Users.roles on bootstrap.php file and these roles will be used on Admin Add / Edit pages. i.e: ```php - Configure::write('Users.roles', array('admin' => 'Admin', 'registered' => 'Registered')); +Configure::write('Users.roles', array('admin' => 'Admin', 'registered' => 'Registered')); ``` If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered role setting Users.defaultRole on bootstrap.php. i.e: - Configure::write('Users.defaultRole', 'user_registered'); +```php +Configure::write('Users.defaultRole', 'user_registered'); +``` ## Enabling / Disabling Registration From 7cbe7ef8cd85876e16bca5cd3e1bc32bc1aae10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 25 Aug 2013 23:20:24 +0200 Subject: [PATCH 0066/1476] Adding auth adapters for cookie, multi-column and token authentication --- .../Component/Auth/CookieAuthenticate.php | 87 ++++++++++ .../Auth/MultiColumnAuthenticate.php | 84 ++++++++++ .../Component/Auth/TokenAuthenticate.php | 138 ++++++++++++++++ Test/Case/AllAuthenticateTest.php | 22 +++ .../Component/Auth/CookieAuthenticateTest.php | 92 +++++++++++ .../Auth/MultiColumnAuthenticateTest.php | 152 ++++++++++++++++++ .../Component/Auth/TokenAuthenticateTest.php | 120 ++++++++++++++ Test/Fixture/MultiUserFixture.php | 39 +++++ 8 files changed, 734 insertions(+) create mode 100644 Controller/Component/Auth/CookieAuthenticate.php create mode 100644 Controller/Component/Auth/MultiColumnAuthenticate.php create mode 100644 Controller/Component/Auth/TokenAuthenticate.php create mode 100644 Test/Case/AllAuthenticateTest.php create mode 100644 Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php create mode 100644 Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php create mode 100644 Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php create mode 100644 Test/Fixture/MultiUserFixture.php diff --git a/Controller/Component/Auth/CookieAuthenticate.php b/Controller/Component/Auth/CookieAuthenticate.php new file mode 100644 index 000000000..554cb52f8 --- /dev/null +++ b/Controller/Component/Auth/CookieAuthenticate.php @@ -0,0 +1,87 @@ +Auth->authenticate = array( + * 'Authenticate.Cookie' => array( + * 'fields' => array( + * 'username' => 'username', + * 'password' => 'password' + * ), + * 'userModel' => 'User', + * 'scope' => array('User.active' => 1), + * 'crypt' => 'rijndael', // Defaults to rijndael(safest), optionally set to 'cipher' if required + * 'cookie' => array( + * 'name' => 'RememberMe', + * 'time' => '+2 weeks', + * ) + * ) + * ) + * }}} + * + * @author Ceeram + * @copyright Ceeram + * @license MIT + * @link https://github.com/ceeram/Authenticate + */ +class CookieAuthenticate extends BaseAuthenticate { + + public function __construct(ComponentCollection $collection, $settings) { + $this->settings['cookie'] = array( + 'name' => 'RememberMe', + 'time' => '+2 weeks', + 'base' => Router::getRequest()->base + ); + $this->settings['crypt'] = 'rijndael'; + parent::__construct($collection, $settings); + } + +/** + * Authenticates the identity contained in the cookie. Will use the `settings.userModel`, and `settings.fields` + * to find COOKIE data that is used to find a matching record in the `settings.userModel`. Will return false if + * there is no cookie data, either username or password is missing, of if the scope conditions have not been met. + * + * @param CakeRequest $request The unused request object + * @return mixed False on login failure. An array of User data on success. + * @throws CakeException + */ + public function getUser(CakeRequest $request) { + if (!isset($this->_Collection->Cookie) || !$this->_Collection->Cookie instanceof CookieComponent) { + throw new CakeException('CookieComponent is not loaded'); + } + + $this->_Collection->Cookie->type($this->settings['crypt']); + list(, $model) = pluginSplit($this->settings['userModel']); + + $data = $this->_Collection->Cookie->read($model); + if (empty($data)) { + return false; + } + + extract($this->settings['fields']); + if (empty($data[$username]) || empty($data[$password])) { + return false; + } + + $user = $this->_findUser($data[$username], $data[$password]); + if ($user) { + $this->_Collection->Session->write(AuthComponent::$sessionKey, $user); + return $user; + } + return false; + } + + public function authenticate(CakeRequest $request, CakeResponse $response) { + return $this->getUser($request); + } + + public function logout($user) { + $this->_Collection->Cookie->destroy(); + } + +} diff --git a/Controller/Component/Auth/MultiColumnAuthenticate.php b/Controller/Component/Auth/MultiColumnAuthenticate.php new file mode 100644 index 000000000..73bca9927 --- /dev/null +++ b/Controller/Component/Auth/MultiColumnAuthenticate.php @@ -0,0 +1,84 @@ +Auth->authenticate = array( + * 'Authenticate.MultiColumn' => array( + * 'fields' => array( + * 'username' => 'username', + * 'password' => 'password' + * ), + * 'columns' => array('username', 'email'), + * 'userModel' => 'User', + * 'scope' => array('User.active' => 1) + * ) + * ) + * }}} + * + * @author Ceeram + * @copyright Ceeram + * @license MIT + * @link https://github.com/ceeram/Authenticate + */ +class MultiColumnAuthenticate extends FormAuthenticate { + +/** + * Settings for this object. + * + * - `fields` The fields to use to identify a user by. + * - 'columns' array of columns to check username form input against + * - `userModel` The model name of the User, defaults to User. + * - `scope` Additional conditions to use when looking up and authenticating users, + * i.e. `array('User.is_active' => 1).` + * + * @var array + */ + public $settings = array( + 'fields' => array( + 'username' => 'username', + 'password' => 'password' + ), + 'columns' => array(), + 'userModel' => 'User', + 'scope' => array() + ); + +/** + * Find a user record using the standard options. + * + * @param string $username The username/identifier. + * @param string $password The unhashed password. + * @return Mixed Either false on failure, or an array of user data. + */ + protected function _findUser($username, $password = null) { + $userModel = $this->settings['userModel']; + list($plugin, $model) = pluginSplit($userModel); + $fields = $this->settings['fields']; + $conditions = array($model . '.' . $fields['username'] => $username); + if ($this->settings['columns'] && is_array($this->settings['columns'])) { + $columns = array(); + foreach ($this->settings['columns'] as $column) { + $columns[] = array($model . '.' . $column => $username); + } + $conditions = array('OR' => $columns); + } + $conditions = array_merge($conditions, array($model . '.' . $fields['password'] => $this->_password($password))); + if (!empty($this->settings['scope'])) { + $conditions = array_merge($conditions, $this->settings['scope']); + } + $result = ClassRegistry::init($userModel)->find('first', array( + 'conditions' => $conditions, + 'recursive' => 0 + )); + if (empty($result) || empty($result[$model])) { + return false; + } + unset($result[$model][$fields['password']]); + return $result[$model]; + } + +} diff --git a/Controller/Component/Auth/TokenAuthenticate.php b/Controller/Component/Auth/TokenAuthenticate.php new file mode 100644 index 000000000..bcfe60c47 --- /dev/null +++ b/Controller/Component/Auth/TokenAuthenticate.php @@ -0,0 +1,138 @@ +Auth->authenticate = array( + * 'Authenticate.Token' => array( + * 'fields' => array( + * 'username' => 'username', + * 'password' => 'password', + * 'token' => 'public_key', + * ), + * 'parameter' => '_token', + * 'header' => 'X-MyApiTokenHeader', + * 'userModel' => 'User', + * 'scope' => array('User.active' => 1) + * ) + * ) + * }}} + * + * @author Ceeram + * @copyright Ceeram + * @license MIT + * @link https://github.com/ceeram/Authenticate + */ +class TokenAuthenticate extends BaseAuthenticate { + +/** + * Settings for this object. + * + * - `fields` The fields to use to identify a user by. Make sure `'token'` has been added to the array + * - `parameter` The url parameter name of the token. + * - `header` The token header value. + * - `userModel` The model name of the User, defaults to User. + * - `scope` Additional conditions to use when looking up and authenticating users, + * i.e. `array('User.is_active' => 1).` + * - `recursive` The value of the recursive key passed to find(). Defaults to 0. + * - `contain` Extra models to contain and store in session. + * + * @var array + */ + public $settings = array( + 'fields' => array( + 'username' => 'username', + 'password' => 'password', + 'token' => 'token', + ), + 'parameter' => '_token', + 'header' => 'X-ApiToken', + 'userModel' => 'User', + 'scope' => array(), + 'recursive' => 0, + 'contain' => null, + ); + +/** + * Constructor + * + * @param ComponentCollection $collection The Component collection used on this request. + * @param array $settings Array of settings to use. + */ + public function __construct(ComponentCollection $collection, $settings) { + parent::__construct($collection, $settings); + if (empty($this->settings['parameter']) && empty($this->settings['header'])) { + throw new CakeException(__d('authenticate', 'You need to specify token parameter and/or header')); + } + } + +/** + * + * @param CakeRequest $request The request object + * @param CakeResponse $response response object. + * @return mixed. False on login failure. An array of User data on success. + */ + public function authenticate(CakeRequest $request, CakeResponse $response) { + $user = $this->getUser($request); + if (!$user) { + $response->statusCode(401); + $response->send(); + } + return $user; + } + +/** + * Get token information from the request. + * + * @param CakeRequest $request Request object. + * @return mixed Either false or an array of user information + */ + public function getUser(CakeRequest $request) { + if (!empty($this->settings['header'])) { + $token = $request->header($this->settings['header']); + if ($token) { + return $this->_findUser($token, null); + } + } + if (!empty($this->settings['parameter']) && !empty($request->query[$this->settings['parameter']])) { + $token = $request->query[$this->settings['parameter']]; + return $this->_findUser($token); + } + return false; + } + +/** + * Find a user record. + * + * @param string $username The token identifier. + * @param string $password Unused password. + * @return Mixed Either false on failure, or an array of user data. + */ + public function _findUser($username, $password = null) { + $userModel = $this->settings['userModel']; + list($plugin, $model) = pluginSplit($userModel); + $fields = $this->settings['fields']; + + $conditions = array( + $model . '.' . $fields['token'] => $username, + ); + if (!empty($this->settings['scope'])) { + $conditions = array_merge($conditions, $this->settings['scope']); + } + $result = ClassRegistry::init($userModel)->find('first', array( + 'conditions' => $conditions, + 'recursive' => (int)$this->settings['recursive'], + 'contain' => $this->settings['contain'], + )); + if (empty($result) || empty($result[$model])) { + return false; + } + $user = $result[$model]; + unset($user[$fields['password']]); + unset($result[$model]); + return array_merge($user, $result); + } + +} diff --git a/Test/Case/AllAuthenticateTest.php b/Test/Case/AllAuthenticateTest.php new file mode 100644 index 000000000..bab10b726 --- /dev/null +++ b/Test/Case/AllAuthenticateTest.php @@ -0,0 +1,22 @@ +addTestDirectoryRecursive($path); + + return $suite; + } +} diff --git a/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php b/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php new file mode 100644 index 000000000..eb9415bd1 --- /dev/null +++ b/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php @@ -0,0 +1,92 @@ +request = new CakeRequest('posts/index', false); + Router::setRequestInfo($this->request); + $this->Collection = new ComponentCollection(); + $this->Collection->load('Cookie'); + $this->Collection->load('Session'); + $this->auth = new CookieAuthenticate($this->Collection, array( + 'fields' => array('username' => 'user', 'password' => 'password'), + 'userModel' => 'MultiUser', + )); + $password = Security::hash('password', null, true); + $User = ClassRegistry::init('MultiUser'); + $User->updateAll(array('password' => $User->getDataSource()->value($password))); + $this->response = $this->getMock('CakeResponse'); + } + +/** + * tearDown + * + * @return void + */ + public function tearDown() { + parent::tearDown(); + $this->Collection->Cookie->destroy(); + } + +/** + * test authenticate email or username + * + * @return void + */ + public function testAuthenticate() { + $expected = array( + 'id' => 1, + 'user' => 'mariano', + 'email' => 'mariano@example.com', + 'token' => '12345', + 'created' => '2007-03-17 01:16:23', + 'updated' => '2007-03-17 01:18:31' + ); + + $result = $this->auth->authenticate($this->request, $this->response); + $this->assertFalse($result); + + $this->Collection->Cookie->write('MultiUser', array('user' => 'mariano', 'password' => 'password')); + $result = $this->auth->authenticate($this->request, $this->response); + $this->assertEquals($expected, $result); + } +} diff --git a/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php b/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php new file mode 100644 index 000000000..9ffa17637 --- /dev/null +++ b/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php @@ -0,0 +1,152 @@ +Collection = $this->getMock('ComponentCollection'); + $this->auth = new MultiColumnAuthenticate($this->Collection, array( + 'fields' => array('username' => 'user', 'password' => 'password'), + 'userModel' => 'MultiUser', + 'columns' => array('user', 'email') + )); + $password = Security::hash('password', null, true); + $User = ClassRegistry::init('MultiUser'); + $User->updateAll(array('password' => $User->getDataSource()->value($password))); + $this->response = $this->getMock('CakeResponse'); + } + +/** + * test authenticate email or username + * + * @return void + */ + public function testAuthenticateEmailOrUsername() { + $request = new CakeRequest('posts/index', false); + $expected = array( + 'id' => 1, + 'user' => 'mariano', + 'email' => 'mariano@example.com', + 'token' => '12345', + 'created' => '2007-03-17 01:16:23', + 'updated' => '2007-03-17 01:18:31' + ); + + $request->data = array('MultiUser' => array( + 'user' => 'mariano', + 'password' => 'password' + )); + $result = $this->auth->authenticate($request, $this->response); + $this->assertEquals($expected, $result); + + $request->data = array('MultiUser' => array( + 'user' => 'mariano@example.com', + 'password' => 'password' + )); + $result = $this->auth->authenticate($request, $this->response); + $this->assertEquals($expected, $result); + } + +/** + * test the authenticate method + * + * @return void + */ + public function testAuthenticateNoData() { + $request = new CakeRequest('posts/index', false); + $request->data = array(); + $this->assertFalse($this->auth->authenticate($request, $this->response)); + } + +/** + * test the authenticate method + * + * @return void + */ + public function testAuthenticateNoUsername() { + $request = new CakeRequest('posts/index', false); + $request->data = array('MultiUser' => array('password' => 'foobar')); + $this->assertFalse($this->auth->authenticate($request, $this->response)); + } + +/** + * test the authenticate method + * + * @return void + */ + public function testAuthenticateNoPassword() { + $request = new CakeRequest('posts/index', false); + $request->data = array('MultiUser' => array('user' => 'mariano')); + $this->assertFalse($this->auth->authenticate($request, $this->response)); + + $request->data = array('MultiUser' => array('user' => 'mariano@example.com')); + $this->assertFalse($this->auth->authenticate($request, $this->response)); + } + +/** + * test the authenticate method + * + * @return void + */ + public function testAuthenticateInjection() { + $request = new CakeRequest('posts/index', false); + $request->data = array( + 'MultiUser' => array( + 'user' => '> 1', + 'password' => "' OR 1 = 1" + )); + $this->assertFalse($this->auth->authenticate($request, $this->response)); + } + +/** + * test scope failure. + * + * @return void + */ + public function testAuthenticateScopeFail() { + $this->auth->settings['scope'] = array('user' => 'nate'); + $request = new CakeRequest('posts/index', false); + $request->data = array('User' => array( + 'user' => 'mariano', + 'password' => 'password' + )); + + $this->assertFalse($this->auth->authenticate($request, $this->response)); + } + +} diff --git a/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php b/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php new file mode 100644 index 000000000..8b992e258 --- /dev/null +++ b/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php @@ -0,0 +1,120 @@ +Collection = $this->getMock('ComponentCollection'); + $this->auth = new TokenAuthenticate($this->Collection, array( + 'fields' => array( + 'username' => 'user', + 'password' => 'password', + 'token' => 'token' + ), + 'userModel' => 'MultiUser', + )); + $password = Security::hash('password', null, true); + $User = ClassRegistry::init('MultiUser'); + $User->updateAll(array('password' => $User->getDataSource()->value($password))); + $this->response = $this->getMock('CakeResponse'); + } + +/** + * test authenticate token as query parameter + * + * @return void + */ + public function testAuthenticateTokenParameter() { + $this->auth->settings['_parameter'] = 'token'; + $request = new CakeRequest('posts/index?_token=54321'); + + $result = $this->auth->getUser($request, $this->response); + $this->assertFalse($result); + + $expected = array( + 'id' => '1', + 'user' => 'mariano', + 'email' => 'mariano@example.com', + 'token' => '12345', + 'created' => '2007-03-17 01:16:23', + 'updated' => '2007-03-17 01:18:31' + ); + $request = new CakeRequest('posts/index?_token=12345'); + $result = $this->auth->getUser($request, $this->response); + $this->assertEquals($expected, $result); + + $this->auth->settings['parameter'] = 'tokenname'; + $request = new CakeRequest('posts/index?tokenname=12345'); + $result = $this->auth->getUser($request, $this->response); + $this->assertEquals($expected, $result); + } + +/** + * test authenticate token as request header + * + * @return void + */ + public function testAuthenticateTokenHeader() { + $_SERVER['HTTP_X_APITOKEN'] = '54321'; + $request = new CakeRequest('posts/index', false); + + $result = $this->auth->getUser($request, $this->response); + $this->assertFalse($result); + + $expected = array( + 'id' => '1', + 'user' => 'mariano', + 'email' => 'mariano@example.com', + 'token' => '12345', + 'created' => '2007-03-17 01:16:23', + 'updated' => '2007-03-17 01:18:31' + ); + $_SERVER['HTTP_X_APITOKEN'] = '12345'; + $result = $this->auth->getUser($request, $this->response); + $this->assertEquals($expected, $result); + } + +} diff --git a/Test/Fixture/MultiUserFixture.php b/Test/Fixture/MultiUserFixture.php new file mode 100644 index 000000000..0c59ae023 --- /dev/null +++ b/Test/Fixture/MultiUserFixture.php @@ -0,0 +1,39 @@ + array('type' => 'integer', 'key' => 'primary'), + 'user' => array('type' => 'string', 'null' => false), + 'email' => array('type' => 'string', 'null' => false), + 'password' => array('type' => 'string', 'null' => false), + 'token' => array('type' => 'string', 'null' => false), + 'created' => 'datetime', + 'updated' => 'datetime' + ); + +/** + * records property + * + * @var array + */ + public $records = array( + array('user' => 'mariano', 'email' => 'mariano@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '12345', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), + array('user' => 'nate', 'email' => 'nate@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '23456', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31'), + array('user' => 'larry', 'email' => 'larry@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '34567', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31'), + array('user' => 'garrett', 'email' => 'garrett@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '45678', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31'), + array('user' => 'chartjes', 'email' => 'chartjes@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '56789', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31'), + + ); +} From 47b45fd02735938cdb6b84fa4ff9f1e925b8b5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 25 Aug 2013 23:23:00 +0200 Subject: [PATCH 0067/1476] Adding a configuration setting to disable the default auth by config --- Controller/UsersController.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 036423802..64f9f0c30 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -117,7 +117,10 @@ protected function _pluginDot() { } /** + * Wrapper for CakePlugin::loaded() * + * @param string $plugin + * @return boolean */ protected function _pluginLoaded($plugin) { return CakePlugin::loaded($plugin); @@ -157,10 +160,15 @@ public function beforeFilter() { * @return void */ protected function _setupAuth() { + if (Configure::read('Users.disableDefaultAuth') === true) { + return; + } + $this->Auth->allow('add', 'reset', 'verify', 'logout', 'view', 'reset_password', 'login', 'resend_verification'); if (!is_null(Configure::read('Users.allowRegistration')) && !Configure::read('Users.allowRegistration')) { $this->Auth->deny('add'); } + if ($this->request->action == 'register') { $this->Components->disable('Auth'); } From fabaa67881268936020b4fe87aea34ecfe208f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 25 Aug 2013 23:33:22 +0200 Subject: [PATCH 0068/1476] Updating the users plugin readme.md --- readme.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 928054326..c56c125fa 100644 --- a/readme.md +++ b/readme.md @@ -145,6 +145,12 @@ protected function _setupAuth() { } ``` +or you can use the configuration settings to disable it, for example in your boostrap.php + +```php +Configure::write('Users.disableDefaultAuth'); +``` + ### Extending the model ### Declare the model @@ -256,14 +262,14 @@ Please feel free to contribute to the plugin with new issues, requests, unit tes ## License ## -Copyright 2009-2012, [Cake Development Corporation](http://cakedc.com) +Copyright 2009-2013, [Cake Development Corporation](http://cakedc.com) Licensed under [The MIT License](http://www.opensource.org/licenses/mit-license.php)
Redistributions of files must retain the above copyright notice. ## Copyright ### -Copyright 2009-2012
+Copyright 2009-2013
[Cake Development Corporation](http://cakedc.com)
1785 E. Sahara Avenue, Suite 490-423
Las Vegas, Nevada 89104
From 616459da21938c7cc3b9cae6955b69aaf11f0101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 25 Aug 2013 23:41:22 +0200 Subject: [PATCH 0069/1476] Fixes https://github.com/CakeDC/users/issues/131 --- Controller/UsersAppController.php | 12 ------------ Controller/UsersController.php | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Controller/UsersAppController.php b/Controller/UsersAppController.php index 4d2dc1691..6463ee860 100644 --- a/Controller/UsersAppController.php +++ b/Controller/UsersAppController.php @@ -20,16 +20,4 @@ class UsersAppController extends AppController { -/** - * Default isAuthorized method - * - * This is called to see if a user (when logged in) is able to access an action - * - * @param array $user - * @return boolean True if allowed - */ - public function isAuthorized($user) { - return parent::isAuthorized($user); - } - } diff --git a/Controller/UsersController.php b/Controller/UsersController.php index fac0d9c28..55a9dbbd1 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -51,7 +51,8 @@ class UsersController extends UsersAppController { 'Form', 'Session', 'Time', - 'Text'); + 'Text' + ); /** * Components @@ -65,7 +66,8 @@ class UsersController extends UsersAppController { 'Paginator', 'Security', 'Search.Prg', - 'Users.RememberMe'); + 'Users.RememberMe' + ); /** * Preset vars @@ -775,4 +777,17 @@ protected function _getMailInstance() { } } +/** + * Default isAuthorized method + * + * This is called to see if a user (when logged in) is able to access an action + * + * @param array $user + * @return boolean True if allowed + * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#using-controllerauthorize + */ + public function isAuthorized($user = null) { + return parent::isAuthorized($user); + } + } From 07de58e83b5e23fb3b789e9485b7fc8f68712ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sat, 7 Sep 2013 18:48:21 +0200 Subject: [PATCH 0070/1476] Refactoring the pagination and improving the documentation --- Controller/UsersController.php | 52 +++++++++++++++++++++++++--------- readme.md | 25 +++++++++++++++- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 55a9dbbd1..a0c5d9a90 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -66,7 +66,7 @@ class UsersController extends UsersAppController { 'Paginator', 'Security', 'Search.Prg', - 'Users.RememberMe' + 'Users.RememberMe', ); /** @@ -152,6 +152,7 @@ protected function _setupComponents() { public function beforeFilter() { parent::beforeFilter(); $this->_setupAuth(); + $this->_setupPagination(); $this->set('model', $this->modelClass); @@ -160,6 +161,41 @@ public function beforeFilter() { } } +/** + * Sets the default pagination settings up + * + * Override this method or the index action directly if you want to change + * pagination settings. + * + * @return void + */ + protected function _setupPagination() { + $this->Paginator->settings = array( + 'limit' => 12, + 'conditions' => array( + $this->modelClass . '.active' => 1, + $this->modelClass . '.email_verified' => 1 + ) + ); + } + +/** + * Sets the default pagination settings up + * + * Override this method or the index() action directly if you want to change + * pagination settings. admin_index() + * + * @return void + */ + protected function _setupAdminPagination() { + $this->Paginator->settings = array( + 'limit' => 20, + 'order' => array( + $this->modelClass . '.created' => 'desc' + ) + ); + } + /** * Setup Authentication Component * @@ -201,11 +237,6 @@ protected function _setupAuth() { * @return void */ public function index() { - $this->Paginator->settings = array( - 'limit' => 12, - 'conditions' => array( - $this->modelClass . '.active' => 1, - $this->modelClass . '.email_verified' => 1)); $this->set('users', $this->Paginator->paginate($this->modelClass)); } @@ -261,10 +292,8 @@ public function admin_index() { $parsedConditions = array(); } + $this->_setupAdminPagination(); $this->Paginator->settings[$this->modelClass]['conditions'] = $parsedConditions; - $this->Paginator->settings[$this->modelClass]['order'] = array($this->modelClass . '.created' => 'desc'); - - $this->{$this->modelClass}->recursive = 0; $this->set('users', $this->Paginator->paginate()); } @@ -545,13 +574,10 @@ public function request_new_password($token = null) { return $this->redirect('/'); } - $email = $data[$this->modelClass]['email']; - unset($data[$this->modelClass]['email']); - if ($this->{$this->modelClass}->save($data, array('validate' => false))) { $this->_sendNewPassword($data); $this->Session->setFlash(__d('users', 'Your password was sent to your registered email account')); - return $this->redirect(array('action' => 'login')); + $this->redirect(array('action' => 'login')); } $this->Session->setFlash(__d('users', 'There was an error verifying your account. Please check the email you were sent, and retry the verification link.')); diff --git a/readme.md b/readme.md index c56c125fa..4c3579e14 100644 --- a/readme.md +++ b/readme.md @@ -234,6 +234,30 @@ Configure::write('Users.defaultRole', 'user_registered'); Some application won't need to have registration enable so you can define Users.allowRegistration on bootstrap.php to enable / disable registration. By default registration will be enabled. +## Configuration options + +The configuration settings can be written by using the Configure class. + + Users.disableDefaultAuth + +Disables/enables the default auth setup that is implemented in the plugins UsersController::_setupAuth() + + Users.allowRegistration + +Disables/enables the user registration. + + Users.roles + +Optional array of user roles if you need it. This is not activly used by the plugin by default. + + Users.sendPassword + +Disables/enables the password reset functionality + + Users.emailConfig + +Email configuration settings array used by this plugin + ## Requirements ## * PHP version: PHP 5.2+ @@ -259,7 +283,6 @@ All versions are updated with security patches. Please feel free to contribute to the plugin with new issues, requests, unit tests and code fixes or new features. If you want to contribute some code, create a feature branch from develop, and send us your pull request. Unit tests for new features and issues detected are mandatory to keep quality high. - ## License ## Copyright 2009-2013, [Cake Development Corporation](http://cakedc.com) From 65ac433e52f4ecb6c2dd4178f84a5a87c828c18b Mon Sep 17 00:00:00 2001 From: Gilles Wittenberg Date: Wed, 11 Sep 2013 11:47:50 +0200 Subject: [PATCH 0071/1476] Update users.pot --- Locale/users.pot | 705 +++++++++++++++++------------------------------ 1 file changed, 249 insertions(+), 456 deletions(-) diff --git a/Locale/users.pot b/Locale/users.pot index c9d074bb4..a7fc0c5da 100644 --- a/Locale/users.pot +++ b/Locale/users.pot @@ -1,18 +1,11 @@ -# LANGUAGE translation of the CakePHP Users plugin -# -# Copyright 2010, Cake Development Corporation (http://cakedc.com) -# -# Licensed under The MIT License -# Redistributions of files must retain the above copyright notice. -# -# @copyright Copyright 2010, Cake Development Corporation (http://cakedc.com) -# @license MIT License (http://www.opensource.org/licenses/mit-license.php) +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2010-09-15 15:48+0200\n" +"POT-Creation-Date: 2013-09-11 11:46+0200\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" @@ -21,701 +14,501 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "" - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "" - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "" - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "" - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "" - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "" - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "" - -#: /controllers/users_controller.php:193 +#: Controller/UsersController.php:310 msgid "Invalid User." msgstr "" -#: /controllers/users_controller.php:207 +#: Controller/UsersController.php:328 msgid "The User has been saved" msgstr "" -#: /controllers/users_controller.php:223 +#: Controller/UsersController.php:345 msgid "User saved" msgstr "" -#: /controllers/users_controller.php:247 +#: Controller/UsersController.php:369 msgid "User deleted" msgstr "" -#: /controllers/users_controller.php:249 -#: /models/user.php:703 +#: Controller/UsersController.php:371 +#: Model/User.php:821 msgid "Invalid User" msgstr "" -#: /controllers/users_controller.php:273 +#: Controller/UsersController.php:393 msgid "You are already registered and logged in!" msgstr "" -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 +#: Controller/UsersController.php:401 +#: Test/Case/Controller/UsersControllerTest.php:342 msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." msgstr "" -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 +#: Controller/UsersController.php:406 +#: Test/Case/Controller/UsersControllerTest.php:357 msgid "Your account could not be created. Please, try again." msgstr "" -#: /controllers/users_controller.php:309 +#: Controller/UsersController.php:428 msgid "%s you have successfully logged in" msgstr "" -#: /controllers/users_controller.php:383 -msgid "%s you have successfully logged out" +#: Controller/UsersController.php:444 +#: Test/Case/Controller/UsersControllerTest.php:316 +msgid "Invalid e-mail / password combination. Please try again" msgstr "" -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" +#: Controller/UsersController.php:510 +msgid "%s you have successfully logged out" msgstr "" -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" +#: Controller/UsersController.php:524 +msgid "The email was resent. Please check your inbox." msgstr "" -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" +#: Controller/UsersController.php:527 +msgid "The email could not be sent. Please check errors." msgstr "" -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" +#: Controller/UsersController.php:550 +#: Test/Case/Controller/UsersControllerTest.php:374 +msgid "Your e-mail has been validated!" msgstr "" -#: /controllers/users_controller.php:438 -msgid "Your password was sent to your registered email account" +#: Controller/UsersController.php:573 +msgid "The url you accessed is not longer valid" msgstr "" -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 -msgid "Your e-mail has been validated!" +#: Controller/UsersController.php:579 +msgid "Your password was sent to your registered email account" msgstr "" -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." +#: Controller/UsersController.php:583 +msgid "There was an error verifying your account. Please check the email you were sent, and retry the verification link." msgstr "" -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 -msgid "The url you accessed is not longer valid" +#: Controller/UsersController.php:599;709 +msgid "Password Reset" msgstr "" -#: /controllers/users_controller.php:467 +#: Controller/UsersController.php:616;780 msgid "Password changed." msgstr "" -#: /controllers/users_controller.php:521 +#: Controller/UsersController.php:677 msgid "Account verification" msgstr "" -#: /controllers/users_controller.php:563 +#: Controller/UsersController.php:736 msgid "%s has been sent an email with instruction to reset their password." msgstr "" -#: /controllers/users_controller.php:567 +#: Controller/UsersController.php:740 msgid "You should receive an email with further instructions shortly" msgstr "" -#: /controllers/users_controller.php:571 +#: Controller/UsersController.php:744 msgid "No user was found with that email." msgstr "" -#: /controllers/users_controller.php:588 +#: Controller/UsersController.php:774 msgid "Invalid password reset token, try again." msgstr "" -#: /controllers/users_controller.php:594 +#: Controller/UsersController.php:783 msgid "Password changed, you can now login with your new password." msgstr "" -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "" - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "" - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "" - -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "" - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "" - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "" - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "" - -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." +#: Controller/Component/RememberMeComponent.php:230 +msgid "Invalid options %s" msgstr "" -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "" - -#: /models/user.php:137;357 +#: Model/User.php:158;339 msgid "The passwords are not equal." msgstr "" -#: /models/user.php:139 +#: Model/User.php:160 msgid "Invalid password." msgstr "" -#: /models/user.php:150 -msgid "Invalid date" +#: Model/User.php:242 +#: Test/Case/Controller/UsersControllerTest.php:382 +msgid "Invalid token, please check the email you were sent, and retry the verification link." +msgstr "" + +#: Model/User.php:247 +msgid "The token has expired." msgstr "" -#: /models/user.php:315 +#: Model/User.php:301 msgid "This Email Address exists but was never validated." msgstr "" -#: /models/user.php:317 +#: Model/User.php:303 msgid "This Email Address does not exist in the system." msgstr "" -#: /models/user.php:406 +#: Model/User.php:397 msgid "$this->data['" msgstr "" -#: /models/user.php:460 +#: Model/User.php:443 msgid "The user does not exist." msgstr "" -#: /models/user.php:505 +#: Model/User.php:481 +msgid "Invalid Email address." +msgstr "" + +#: Model/User.php:486 +msgid "This email is already verified." +msgstr "" + +#: Model/User.php:554 msgid "Please enter your email address." msgstr "" -#: /models/user.php:515 +#: Model/User.php:561 msgid "The email address does not exist in the system" msgstr "" -#: /models/user.php:520 +#: Model/User.php:566 msgid "Your account is already authenticaed." msgstr "" -#: /models/user.php:525 +#: Model/User.php:571 msgid "Your account is disabled." msgstr "" -#: /tests/cases/controllers/users_controller.test.php:34 +#: Test/Case/Controller/UsersControllerTest.php:55 msgid "Sorry, but you need to login to access this location." msgstr "" -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" +#: Test/Case/Controller/UsersControllerTest.php:275 +msgid "adminuser you have successfully logged in" msgstr "" -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" +#: Test/Case/Controller/UsersControllerTest.php:401 +msgid "testuser you have successfully logged out" msgstr "" -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" +#: View/Elements/Users/admin_sidebar.ctp:3 +#: View/Elements/Users/sidebar.ctp:9 +msgid "Logout" msgstr "" -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" +#: View/Elements/Users/admin_sidebar.ctp:4 +#: View/Elements/Users/sidebar.ctp:10 +msgid "My Account" msgstr "" -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" +#: View/Elements/Users/admin_sidebar.ctp:6 +msgid "Add Users" msgstr "" -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 +#: View/Elements/Users/admin_sidebar.ctp:7 +#: View/Elements/Users/sidebar.ctp:15 msgid "List Users" msgstr "" -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" +#: View/Elements/Users/admin_sidebar.ctp:9 +msgid "Frontend" msgstr "" -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" +#: View/Elements/Users/sidebar.ctp:4 +#: View/Users/login.ctp:13 +msgid "Login" msgstr "" -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" +#: View/Elements/Users/sidebar.ctp:6 +msgid "Register an account" msgstr "" -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" +#: View/Elements/Users/sidebar.ctp:11 +msgid "Change password" msgstr "" -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" +#: View/Emails/text/account_verification.ctp:12 +msgid "Hello %s," msgstr "" -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" +#: View/Emails/text/account_verification.ctp:14 +msgid "to validate your account, you must visit the URL below within 24 hours" msgstr "" -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" +#: View/Emails/text/new_password.ctp:12 +msgid "Your password has been reset" msgstr "" -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 -msgid "previous" +#: View/Emails/text/new_password.ctp:13 +msgid "Please login using this password and change your password" msgstr "" -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 -msgid "next" +#: View/Emails/text/new_password.ctp:15 +msgid "Your new password is: %s" msgstr "" -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" +#: View/Emails/text/password_reset_request.ctp:12 +msgid "A request to reset your password was sent. To change your password click the link below." msgstr "" -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" +#: View/Users/add.ctp:13 +#: View/Users/admin_add.ctp:15 +msgid "Add User" msgstr "" -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" +#: View/Users/add.ctp:18 +#: View/Users/admin_add.ctp:18 +#: View/Users/admin_edit.ctp:19 +#: View/Users/admin_index.ctp:18 +#: View/Users/admin_view.ctp:15 +#: View/Users/search.ctp:18 +#: View/Users/view.ctp:15 +msgid "Username" msgstr "" -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" +#: View/Users/add.ctp:20 +#: View/Users/admin_add.ctp:20 +msgid "E-mail (used as login)" msgstr "" -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" +#: View/Users/add.ctp:21 +#: View/Users/admin_add.ctp:21 +msgid "Must be a valid email address" msgstr "" -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" +#: View/Users/add.ctp:22 +#: View/Users/admin_add.ctp:22 +msgid "An account with that email already exists" msgstr "" -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" +#: View/Users/add.ctp:24 +#: View/Users/admin_add.ctp:24 +#: View/Users/login.ctp:23 +msgid "Password" msgstr "" -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" +#: View/Users/add.ctp:27 +#: View/Users/admin_add.ctp:27 +msgid "Password (confirm)" msgstr "" -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" +#: View/Users/add.ctp:29 +msgid "Terms of Service" msgstr "" -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" +#: View/Users/add.ctp:31 +msgid "I have read and agreed to " msgstr "" -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" +#: View/Users/add.ctp:32 +#: View/Users/change_password.ctp:26 +#: View/Users/edit.ctp:25 +#: View/Users/login.ctp:30 +#: View/Users/request_password_change.ctp:22 +#: View/Users/resend_verification.ctp:22 +#: View/Users/reset_password.ctp:14 +msgid "Submit" msgstr "" -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" +#: View/Users/admin_add.ctp:31 +#: View/Users/admin_edit.ctp:24 +msgid "Role" msgstr "" -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" +#: View/Users/admin_add.ctp:34 +#: View/Users/admin_edit.ctp:27 +msgid "Is Admin" msgstr "" -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" +#: View/Users/admin_add.ctp:36 +#: View/Users/admin_edit.ctp:29 +msgid "Active" msgstr "" -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" +#: View/Users/admin_edit.ctp:15 +#: View/Users/edit.ctp:15 +msgid "Edit User" msgstr "" -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" +#: View/Users/admin_edit.ctp:21 +#: View/Users/admin_index.ctp:19 +#: View/Users/login.ctp:21 +#: View/Users/search.ctp:20 +msgid "Email" msgstr "" -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" +#: View/Users/admin_index.ctp:13 +#: View/Users/index.ctp:13 +#: View/Users/search.ctp:13 +msgid "Users" msgstr "" -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 -msgid "Password" +#: View/Users/admin_index.ctp:15 +msgid "Filter" msgstr "" -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 -msgid "Login" +#: View/Users/admin_index.ctp:20 +#: View/Users/search.ctp:23 +msgid "Search" msgstr "" -#: /views/elements/email/text/account_verification.ctp:2 -msgid "Hello %s," +#: View/Users/admin_index.ctp:32 +#: View/Users/index.ctp:25 +#: View/Users/search.ctp:35 +msgid "Actions" msgstr "" -#: /views/elements/email/text/account_verification.ctp:4 -msgid "to validate your account, you must visit the URL below within 24 hours" +#: View/Users/admin_index.ctp:50;53 +msgid "Yes" msgstr "" -#: /views/elements/email/text/password_reset_request.ctp:2 -msgid "A request to reset your password was sent. To change your password click the link below." +#: View/Users/admin_index.ctp:50;53 +msgid "No" msgstr "" -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 -msgid "Add User" +#: View/Users/admin_index.ctp:59 +#: View/Users/index.ctp:39 +#: View/Users/search.ctp:49 +msgid "View" msgstr "" -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 -msgid "Edit User" +#: View/Users/admin_index.ctp:60 +#: View/Users/search.ctp:50 +msgid "Edit" msgstr "" -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 -msgid "Users" +#: View/Users/admin_index.ctp:61 +#: View/Users/search.ctp:52 +msgid "Delete" msgstr "" -#: /views/users/admin_index.ctp:4 -msgid "Filter" +#: View/Users/admin_index.ctp:61 +#: View/Users/search.ctp:55 +msgid "Are you sure you want to delete # %s?" msgstr "" -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" +#: View/Users/admin_view.ctp:13 +#: View/Users/view.ctp:13 +msgid "User" msgstr "" -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 -msgid "Search" +#: View/Users/admin_view.ctp:20 +#: View/Users/view.ctp:20 +msgid "Created" msgstr "" -#: /views/users/admin_view.ctp:24 -msgid "Delete User" +#: View/Users/admin_view.ctp:25 +msgid "Modified" msgstr "" -#: /views/users/change_password.ctp:1 +#: View/Users/change_password.ctp:13 +#: View/Users/edit.ctp:22 msgid "Change your password" msgstr "" -#: /views/users/change_password.ctp:3 +#: View/Users/change_password.ctp:14 msgid "Please enter your old password because of security reasons and then your new password twice." msgstr "" -#: /views/users/change_password.ctp:8 +#: View/Users/change_password.ctp:18 msgid "Old Password" msgstr "" -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 +#: View/Users/change_password.ctp:21 +#: View/Users/reset_password.ctp:9 msgid "New Password" msgstr "" -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 +#: View/Users/change_password.ctp:24 +#: View/Users/reset_password.ctp:12 msgid "Confirm" msgstr "" -#: /views/users/dashboard.ctp:2 +#: View/Users/dashboard.ctp:13 msgid "Welcome" msgstr "" -#: /views/users/dashboard.ctp:3 +#: View/Users/dashboard.ctp:14 msgid "Recent broadcasts" msgstr "" -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "" - -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "" - -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "" - -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "" - -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "" - -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "" - -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "" - -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "" - -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "" - -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "" - -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "" - -#: /views/users/groups.ctp:68 -msgid "Leave group" +#: View/Users/index.ctp:17 +#: View/Users/search.ctp:27 +msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" msgstr "" -#: /views/users/login.ctp:11 +#: View/Users/login.ctp:25 msgid "Remember Me" msgstr "" -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "" - -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" +#: View/Users/login.ctp:26 +msgid "I forgot my password" msgstr "" -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "" - -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "" - -#: /views/users/register.ctp:13 -msgid "Please choose username" +#: View/Users/request_password_change.ctp:13 +msgid "Forgot your password?" msgstr "" -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" +#: View/Users/request_password_change.ctp:14 +#: View/Users/resend_verification.ctp:14 +msgid "Please enter the email you used for registration and you'll get an email with further instructions." msgstr "" -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" +#: View/Users/request_password_change.ctp:21 +#: View/Users/resend_verification.ctp:21 +msgid "Your Email" msgstr "" -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" +#: View/Users/resend_verification.ctp:13 +msgid "Resend the Email Verification" msgstr "" -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" +#: View/Users/reset_password.ctp:2 +msgid "Reset your password" msgstr "" -#: /views/users/register.ctp:23 -msgid "Password (confirm)" +#: View/Users/search.ctp:22 +msgid "Name" msgstr "" -#: /views/users/register.ctp:25 -msgid "Passwords must match" +#: Model/User.php:validation for field username +msgid "Please enter a username." msgstr "" -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " +#: Model/User.php:validation for field username +msgid "The username must be alphanumeric." msgstr "" -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" +#: Model/User.php:validation for field username +msgid "This username is already in use." msgstr "" -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" +#: Model/User.php:validation for field username +msgid "The username must have at least 3 characters." msgstr "" -#: /views/users/register.ctp:46 -msgid "Openid Identifier" +#: Model/User.php:validation for field email +msgid "Please enter a valid email address." msgstr "" -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" +#: Model/User.php:validation for field email +msgid "This email is already in use." msgstr "" -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." +#: Model/User.php:validation for field password +msgid "The password must have at least 6 characters." msgstr "" -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" +#: Model/User.php:validation for field password +msgid "Please enter a password." msgstr "" -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" +#: Model/User.php:validation for field temppassword +msgid "The passwords are not equal, please try again." msgstr "" -#: /views/users/search.ctp:1 -msgid "Search for users" +#: Model/User.php:validation for field tos +msgid "You must agree to the terms of use." msgstr "" From a82f55503da291112c911ae63f325a20bb00a263 Mon Sep 17 00:00:00 2001 From: Gilles Wittenberg Date: Wed, 11 Sep 2013 11:50:42 +0200 Subject: [PATCH 0072/1476] Add Dutch translations --- Locale/nld/LC_MESSAGES/users.mo | Bin 0 -> 9670 bytes Locale/nld/LC_MESSAGES/users.po | 696 ++++++++++++++++++++++++++++++++ 2 files changed, 696 insertions(+) create mode 100644 Locale/nld/LC_MESSAGES/users.mo create mode 100644 Locale/nld/LC_MESSAGES/users.po diff --git a/Locale/nld/LC_MESSAGES/users.mo b/Locale/nld/LC_MESSAGES/users.mo new file mode 100644 index 0000000000000000000000000000000000000000..6445b1044ba4b9d4b50d4d74124f666315d72555 GIT binary patch literal 9670 zcmbW6ZHyh)S;tS)1QOHG(uO7tc{!%t#3sAfyK&;icAWTa?QCm%-Sw^=CnaU>y=U*v z-nlcInYnwt29W@Q3Xo7gqynLWKoy8L2~@QbQh};!g-Qf`D565D2xiCc1m6ul1l|fB1GV2t@HX%qsCg^k4}w=gotuH0cMa73KMmds{xYcjJ_WuF z{0mTgeg%92{73Me;Qb8l1LwgX0Iz~;U>DT>p9dk?yb6krzXe6dSF7=_gZK0PFQDe# z!6BmmE|4zs9`F|MAy9JNU-h2@3*N7SI_IxI(eoAX`@w$(kAkm*qU$j_?*Y$L_z_V0 zxdyhtPkkAwTF_ZL9^ z8ONWy!ELYs{t~zV{%Q68EpU$a2RKyY=Rn!rkAu?3uYi*GAA;iN??B1r-$1Rq3n9D+ zo&@K?PlJzw{{)KOdtl;0@DOOh%b?^v0449A0HueY2PM~6Kz@U7q< zfwI?6gOcZK;4$zPj7j?(2PKCOg1-p<6ezpC6C->Ncn}ml=Rxt)1I6#pf$s-D32OhZ zR(KmiIK%q^aPuw55k$r2YY6oU_$^TD&$8JAU>hvKp8+Awybek~Z{u*`yFf%^?yYbR z{1M)dgF3ehLbCaIg}(<%E}sL%-E-W{4?NFyuVt#-|<7(8t)H)+V?o9@ikEAzXD>S=C?qd z_Zd*<{aJ-y0xj=f2BrUh2c>5TQR{C5rRR5p`@nla?RN_7ftNtZ;qxFWGJgq*-milv z!T+rK4`Y0?-(?Vyn01hU=4JkDg1-)G{T(Q6349QI5{yCd_1mDnkh2ESPaCEt&NTK~J? zVeoSxDlq>Aiq5;3^aS`JumFDn)c)TFwf}yc)PgTm_!208`3+F|_#!B}{<^|%fP^IT zZBX*PlgZ-io(dlXZ{htRQ1-GPlsqngN5BE7eLn@hAN&*WCGbB$STrSzblxkV^zjFv z`1$h+zXl%X{eM7~m}5AtFap*8v*266by`fTAIbV7)r<5i-+~3N8+AWLlU(ZOA%2L? z4((x@XsMr5)sF5?{ zTcIt|WV_2W#a=y%_2+48df`cFAEse;<{VAWChZ{YI8Dz1+O4!JG}&tXNZyFeoTWvy z57AE3^!zC8dD<3jmG)z_Gqk5^_t6ON-rqLBL$nr6k97M%nru>jq9+UB|Drzc2YUGc zO}dwTv}q@3^&{K4T)oKNZlTGZWxMhV*@m8HXoOJj3-S|7+x+jK6qg-c5trPlSLII)Ac+^}(4 zlzG2Z##w61%;v6er7bsHoZGFaC%-c%%j5O96^R=<1%=0LXHK-+cCB#v@CPHQjjEMi7Uf1%R#oH`$;{jn z0`t|6LBw%z(RPU|oqeyJDV{c`0>!o5>h}o_%&9D0kMo{6#Q~*jo6~*=vpDB1n-GkV3*n-zXVa`cC`YXFWpS3YNba}qdgr>8R z4FU}3RRT2UcWh;-=0enS=7Jm8i_3*2hnYG16Hi*-XooV&+92RGgU<*GkEX4Ym-dkqSbr~hhFQdHF0zyETi5k?$ zUKmm}GQ-aqGo-ivVfVFyLGK@q*%bwm(Q9zz_N>w2SMbz z;Ddycj2k%*!7WUbgeL`9?NGU)^(-kQCR^N&{T>$4nl@#U>w~+whEs`C{w6txFufyd z_QI^L@m+G3AqG{*px#W#UzLjl8zyf+iN!81C(T3*-LN2}4&I(cdg{1Zg6MSbS4#qU ztgRCc%nxV(PNU&=8m?xh4|dYe?hR!8#(O}>QQG09@Lr&PMM>XRn9H#nm@6*fvUcXG zE6i2oCF`m;4Ka{AGvo^RWJvq=`k7wGK7Ua9AgN=m!5yKn;pcEE$$z+CTuc^u^T4TV zEH9HCt|fh!9^1CCb z4y|rEZIL-BXOe2Y>kMM92-$rzK^$4Q@4P4opH!kJz)A09VVExFjFvitN}Yw=zdUf4t*Is5z>E z29Ea>8>F2++1%W!i+V@wp7TrR7e~Y|H0JkEJFtRNcD5k5bl1uQTM23OQ6DbRuf?&Y3#*G~7gvsQlW6?d z;eJ_(Q9k*W->$8`e%t%@FJ@?|9a-SI<1enOg%=F59w^!d5!qBI zO{W#56rt3lgjWyi=5ppbq>;_MA9wMgGIP_qM0_1FBsvVph6oVpX5w_6OD>ua!Wr+| z>rUGdi}|!bRrCI-v)(l6|Raa$TzyN;VE&-mz)V9bgz2>Bv42Z1q{Bw#}ugqz#2lmYda# z;%}%U72*DlPt96fR=>_VbdEPt=H5)A=Mn2ztsC{s1&LrxQWU?=Ec#H<3A(Ahz^kqP z4&!Bvkos^jk{YEY)pu0azS|@dz6@6JJ1Tm8cU9?TOAH!!cbvJnjgwuEEw63 z#~W^0VyKi>S(-FPtd_OWIUd>R<;Fr03gMm*+2@S}a0sOiW7(vl#hG1931t!KDkZIB zag=E06nUM~HyJNag~&1aKyI}I3&;A$E*NT8RlAfvaY-oAU5OGy!OM5C-1A$fJy7QT>@R+BGrgeB6HbY^&p#ET*1OI2`GqzCIABFMcIEU;I-2 zo^>6JJhfedgCE!DVBSZ&O$l?0A#>)?p+pEk;qGtPQ~qNddZ_AO-ELzl@ghJ6h?Wo2 z4of^_yVSp3)xXtM2j{29J%t?<#{-3ga-=hbteY;;rlB4VSwNC)Nyzk)WzKT#VjQ-L z&feggP6>rRN{UyBFOj9^)kUL~LvI}3(wf&W;(9n%cu(!>qY4QlBjTUW%ARFjTk$42 z+>rZ;eZ$%trFL+d)QGnm&aIb-tF;k4I26-Z4fPzRi1iZy_#@itL*M(J@bKx06-$CJPzW=qOa1LIwS|4s zvNr4mzN(KUGG11?M??0D%2^QZ)W$g7L7BU(W|BVqtwWH-FX{KjDvzF6qLHyM<%jEZ z=*\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" +"X-Generator: Poedit 1.5.5\n" + +#: Controller/UsersController.php:310 +msgid "Invalid User." +msgstr "Ongeldige gebruiker." + +#: Controller/UsersController.php:328 +msgid "The User has been saved" +msgstr "Gebruiker is opgeslagen" + +#: Controller/UsersController.php:345 +msgid "User saved" +msgstr "Gebruiker is opgeslagen" + +#: Controller/UsersController.php:369 +msgid "User deleted" +msgstr "Gebruiker is verwijderd" + +#: Controller/UsersController.php:371 Model/User.php:821 +msgid "Invalid User" +msgstr "Ongeldige gebruiker" + +#: Controller/UsersController.php:393 +msgid "You are already registered and logged in!" +msgstr "U bent al geregistreerd en ingelogd!" + +#: Controller/UsersController.php:401 +#: Test/Case/Controller/UsersControllerTest.php:342 +msgid "" +"Your account has been created. You should receive an e-mail shortly to " +"authenticate your account. Once validated you will be able to login." +msgstr "" +"Uw account is gecreëerd. U heeft een email ontvangen om uw account te " +"verifiëren. Na verificatie bent u instaat in te loggen." + +#: Controller/UsersController.php:406 +#: Test/Case/Controller/UsersControllerTest.php:357 +msgid "Your account could not be created. Please, try again." +msgstr "Uw account kon niet worden gecreëerd. Probeer opnieuw." + +#: Controller/UsersController.php:428 +msgid "%s you have successfully logged in" +msgstr "%s, u ben succesvol ingelogd" + +#: Controller/UsersController.php:444 +#: Test/Case/Controller/UsersControllerTest.php:316 +msgid "Invalid e-mail / password combination. Please try again" +msgstr "Ongeldig emailadress / wachtwoord combinatie. Probeer opnieuw." + +#: Controller/UsersController.php:510 +msgid "%s you have successfully logged out" +msgstr "%s, u bent succesvol uitgelogd" + +#: Controller/UsersController.php:524 +msgid "The email was resent. Please check your inbox." +msgstr "E-mail is nogmaals verstuurd. Check uw inbox." + +#: Controller/UsersController.php:527 +msgid "The email could not be sent. Please check errors." +msgstr "Gegeven kon niet worden opgeslagen. Probeer opnieuw." + +#: Controller/UsersController.php:550 +#: Test/Case/Controller/UsersControllerTest.php:374 +msgid "Your e-mail has been validated!" +msgstr "Uw email is geverifiëerd" + +#: Controller/UsersController.php:573 +msgid "The url you accessed is not longer valid" +msgstr "De URL, die u probeert te bezoeken, is niet langer geldig" + +#: Controller/UsersController.php:579 +msgid "Your password was sent to your registered email account" +msgstr "Uw wachtwoord is naar uw, bij ons geregistreerde, email gestuurd" + +#: Controller/UsersController.php:583 +msgid "" +"There was an error verifying your account. Please check the email you were " +"sent, and retry the verification link." +msgstr "" +"Er heeft zich een error voorgedaan bij de verificatie van uw account. Bekijk " +"uw e-mail en volg de verificatie link." + +#: Controller/UsersController.php:599;709 +msgid "Password Reset" +msgstr "Wachtwoord wijzigen" + +#: Controller/UsersController.php:616;780 +msgid "Password changed." +msgstr "Wachtwoord gewijzigd." + +#: Controller/UsersController.php:677 +msgid "Account verification" +msgstr "Account verificatie" + +#: Controller/UsersController.php:736 +msgid "%s has been sent an email with instruction to reset their password." +msgstr "" +"Er is een email naar %s verstuurd met instructies om zijn/haar wachtwoord te " +"wijzigen. " + +#: Controller/UsersController.php:740 +msgid "You should receive an email with further instructions shortly" +msgstr "Er is een email verstuurd met verder te volgen instructies" + +#: Controller/UsersController.php:744 +msgid "No user was found with that email." +msgstr "Er is geen gebruiker met dat emailadres." + +#: Controller/UsersController.php:774 +msgid "Invalid password reset token, try again." +msgstr "Ongeldige token, probeer opnieuw." + +#: Controller/UsersController.php:783 +msgid "Password changed, you can now login with your new password." +msgstr "Wachtwoord gewijzigd. U kunt nu inloggen met uw nieuwe wachtwoord." + +#: Controller/Component/RememberMeComponent.php:230 +msgid "Invalid options %s" +msgstr "Ongeldig wachtwoord." + +#: Model/User.php:158;339 +msgid "The passwords are not equal." +msgstr "De wachtwoorden zijn niet gelijk." + +#: Model/User.php:160 +msgid "Invalid password." +msgstr "Ongeldig wachtwoord." + +#: Model/User.php:242 Test/Case/Controller/UsersControllerTest.php:382 +msgid "" +"Invalid token, please check the email you were sent, and retry the " +"verification link." +msgstr "Ongeldige token. Bekijk uw e-mail en volg de verificatie link." + +#: Model/User.php:247 +msgid "The token has expired." +msgstr "De token is verlopen." + +#: Model/User.php:301 +msgid "This Email Address exists but was never validated." +msgstr "Dit emailadres bestaat, maar is nooit geverifiëerd." + +#: Model/User.php:303 +msgid "This Email Address does not exist in the system." +msgstr "Dit emailadres bestaat niet in dit systeem" + +#: Model/User.php:397 +msgid "$this->data['" +msgstr "$this->data['" + +#: Model/User.php:443 +msgid "The user does not exist." +msgstr "De gebruiker bestaat niet." + +#: Model/User.php:481 +msgid "Invalid Email address." +msgstr "Moet een geldig e-mailadres zijn" + +#: Model/User.php:486 +msgid "This email is already verified." +msgstr "Het emailadres is al in gebruik." + +#: Model/User.php:554 +msgid "Please enter your email address." +msgstr "Vul uw emailadres in." + +#: Model/User.php:561 +msgid "The email address does not exist in the system" +msgstr "Het emailadres bestaat niet in dit systeem" + +#: Model/User.php:566 +msgid "Your account is already authenticaed." +msgstr "Uw account is al geverifiëerd." + +#: Model/User.php:571 +msgid "Your account is disabled." +msgstr "Uw account is uitgezet." + +#: Test/Case/Controller/UsersControllerTest.php:55 +msgid "Sorry, but you need to login to access this location." +msgstr "U moet ingelogd zijn om deze locatie te bekijken." + +#: Test/Case/Controller/UsersControllerTest.php:275 +msgid "adminuser you have successfully logged in" +msgstr "testuser, u bent succesvol ingelogd" + +#: Test/Case/Controller/UsersControllerTest.php:401 +msgid "testuser you have successfully logged out" +msgstr "testuser, u bent succesvol ingelogd" + +#: View/Elements/Users/admin_sidebar.ctp:3 View/Elements/Users/sidebar.ctp:9 +msgid "Logout" +msgstr "Uitloggen" + +#: View/Elements/Users/admin_sidebar.ctp:4 View/Elements/Users/sidebar.ctp:10 +msgid "My Account" +msgstr "Mijn Account" + +#: View/Elements/Users/admin_sidebar.ctp:6 +msgid "Add Users" +msgstr "Voeg gebruiker toe" + +#: View/Elements/Users/admin_sidebar.ctp:7 View/Elements/Users/sidebar.ctp:15 +msgid "List Users" +msgstr "Toon gebruikers" + +#: View/Elements/Users/admin_sidebar.ctp:9 +msgid "Frontend" +msgstr "Frontend" + +#: View/Elements/Users/sidebar.ctp:4 View/Users/login.ctp:13 +msgid "Login" +msgstr "Inloggen" + +#: View/Elements/Users/sidebar.ctp:6 +msgid "Register an account" +msgstr "Registreer een account" + +#: View/Elements/Users/sidebar.ctp:11 +msgid "Change password" +msgstr "Wijzig uw wachtwoord" + +#: View/Emails/text/account_verification.ctp:12 +msgid "Hello %s," +msgstr "Hallo %s," + +#: View/Emails/text/account_verification.ctp:14 +msgid "to validate your account, you must visit the URL below within 24 hours" +msgstr "Om uw account te verifiëren, volg binnen 24 uur de volgende URL" + +#: View/Emails/text/new_password.ctp:12 +msgid "Your password has been reset" +msgstr "Uw wachtwoord is gewijzigd" + +#: View/Emails/text/new_password.ctp:13 +msgid "Please login using this password and change your password" +msgstr "Login met dit wachtwoord om daarna uw wachtwoord te wijzigen" + +#: View/Emails/text/new_password.ctp:15 +msgid "Your new password is: %s" +msgstr "Uw wachtwoord is gewijzigd" + +#: View/Emails/text/password_reset_request.ctp:12 +msgid "" +"A request to reset your password was sent. To change your password click the " +"link below." +msgstr "" +"Een verzoek om uw wachtwoord te wijzigen is verstuurd. Om uw wachtwoord te " +"wijzigen klik op de beneden staande link." + +#: View/Users/add.ctp:13 View/Users/admin_add.ctp:15 +msgid "Add User" +msgstr "Voeg gebruiker toe" + +#: View/Users/add.ctp:18 View/Users/admin_add.ctp:18 +#: View/Users/admin_edit.ctp:19 View/Users/admin_index.ctp:18 +#: View/Users/admin_view.ctp:15 View/Users/search.ctp:18 +#: View/Users/view.ctp:15 +msgid "Username" +msgstr "Gebruikersnaam" + +#: View/Users/add.ctp:20 View/Users/admin_add.ctp:20 +msgid "E-mail (used as login)" +msgstr "E-mail (gebruik als login)" + +#: View/Users/add.ctp:21 View/Users/admin_add.ctp:21 +msgid "Must be a valid email address" +msgstr "Moet een geldig e-mailadres zijn" + +#: View/Users/add.ctp:22 View/Users/admin_add.ctp:22 +msgid "An account with that email already exists" +msgstr "Een account met dit e-mailadres bestaat al" + +#: View/Users/add.ctp:24 View/Users/admin_add.ctp:24 View/Users/login.ctp:23 +msgid "Password" +msgstr "Wachtwoord" + +#: View/Users/add.ctp:27 View/Users/admin_add.ctp:27 +msgid "Password (confirm)" +msgstr "Wachtwoord (bevestig)" + +#: View/Users/add.ctp:29 +msgid "Terms of Service" +msgstr "Gebruikersvoorwaarden" + +#: View/Users/add.ctp:31 +msgid "I have read and agreed to " +msgstr "Ik heb gelezen en ga akkoord met de " + +#: View/Users/add.ctp:32 View/Users/change_password.ctp:26 +#: View/Users/edit.ctp:25 View/Users/login.ctp:30 +#: View/Users/request_password_change.ctp:22 +#: View/Users/resend_verification.ctp:22 View/Users/reset_password.ctp:14 +msgid "Submit" +msgstr "Opslaan" + +#: View/Users/admin_add.ctp:31 View/Users/admin_edit.ctp:24 +msgid "Role" +msgstr "Rol" + +#: View/Users/admin_add.ctp:34 View/Users/admin_edit.ctp:27 +msgid "Is Admin" +msgstr "Is Administrator" + +#: View/Users/admin_add.ctp:36 View/Users/admin_edit.ctp:29 +msgid "Active" +msgstr "Actief" + +#: View/Users/admin_edit.ctp:15 View/Users/edit.ctp:15 +msgid "Edit User" +msgstr "Wijzig gebruiker" + +#: View/Users/admin_edit.ctp:21 View/Users/admin_index.ctp:19 +#: View/Users/login.ctp:21 View/Users/search.ctp:20 +msgid "Email" +msgstr "E-mail" + +#: View/Users/admin_index.ctp:13 View/Users/index.ctp:13 +#: View/Users/search.ctp:13 +msgid "Users" +msgstr "Gebruikers" + +#: View/Users/admin_index.ctp:15 +msgid "Filter" +msgstr "Filter" + +#: View/Users/admin_index.ctp:20 View/Users/search.ctp:23 +msgid "Search" +msgstr "Zoeken" + +#: View/Users/admin_index.ctp:32 View/Users/index.ctp:25 +#: View/Users/search.ctp:35 +msgid "Actions" +msgstr "Acties" + +#: View/Users/admin_index.ctp:50;53 +msgid "Yes" +msgstr "Ja" + +#: View/Users/admin_index.ctp:50;53 +msgid "No" +msgstr "Nee" + +#: View/Users/admin_index.ctp:59 View/Users/index.ctp:39 +#: View/Users/search.ctp:49 +msgid "View" +msgstr "Bekijk" + +#: View/Users/admin_index.ctp:60 View/Users/search.ctp:50 +msgid "Edit" +msgstr "Wijzig" + +#: View/Users/admin_index.ctp:61 View/Users/search.ctp:52 +msgid "Delete" +msgstr "Verwijder" + +#: View/Users/admin_index.ctp:61 View/Users/search.ctp:55 +msgid "Are you sure you want to delete # %s?" +msgstr "Weet u zeker dat u # %s wilt verwijderen?" + +#: View/Users/admin_view.ctp:13 View/Users/view.ctp:13 +msgid "User" +msgstr "Gebruiker" + +#: View/Users/admin_view.ctp:20 View/Users/view.ctp:20 +msgid "Created" +msgstr "Gecreëerd" + +#: View/Users/admin_view.ctp:25 +msgid "Modified" +msgstr "Gewijzigd" + +#: View/Users/change_password.ctp:13 View/Users/edit.ctp:22 +msgid "Change your password" +msgstr "Wijzig uw wachtwoord" + +#: View/Users/change_password.ctp:14 +msgid "" +"Please enter your old password because of security reasons and then your new " +"password twice." +msgstr "" +"Vul eerst uw oude wachtwoord in. En daarna tweemaal uw nieuwe wachtwoord." + +#: View/Users/change_password.ctp:18 +msgid "Old Password" +msgstr "Oude wachtwoord" + +#: View/Users/change_password.ctp:21 View/Users/reset_password.ctp:9 +msgid "New Password" +msgstr "Nieuw wachtwoord" + +#: View/Users/change_password.ctp:24 View/Users/reset_password.ctp:12 +msgid "Confirm" +msgstr "Bevestig" + +#: View/Users/dashboard.ctp:13 +msgid "Welcome" +msgstr "Welkom" + +#: View/Users/dashboard.ctp:14 +msgid "Recent broadcasts" +msgstr "Recente uitzendingen" + +#: View/Users/index.ctp:17 View/Users/search.ctp:27 +msgid "" +"Page %page% of %pages%, showing %current% records out of %count% total, " +"starting on record %start%, ending on %end%" +msgstr "" +"Pagina %page% van %pages%, %current% van %count% objecten getoond, beginnend " +"bij %start%, eindigend bij %end%" + +#: View/Users/login.ctp:25 +msgid "Remember Me" +msgstr "Herinner mij" + +#: View/Users/login.ctp:26 +msgid "I forgot my password" +msgstr "Wachtwoord vergeten?" + +#: View/Users/request_password_change.ctp:13 +msgid "Forgot your password?" +msgstr "Wachtwoord vergeten?" + +#: View/Users/request_password_change.ctp:14 +#: View/Users/resend_verification.ctp:14 +msgid "" +"Please enter the email you used for registration and you'll get an email " +"with further instructions." +msgstr "" +"Vul het door u bij ons geregistreerde e-mailadres in om een e-mail met te " +"volgen instructies te ontvangen." + +#: View/Users/request_password_change.ctp:21 +#: View/Users/resend_verification.ctp:21 +msgid "Your Email" +msgstr "Uw E-mail" + +#: View/Users/resend_verification.ctp:13 +msgid "Resend the Email Verification" +msgstr "Verstuur nogmaals de e-mail verificatie." + +#: View/Users/reset_password.ctp:2 +msgid "Reset your password" +msgstr "Wijzig uw wachtwoord" + +#: View/Users/search.ctp:22 +msgid "Name" +msgstr "Naam" + +#: Model/User.php:validation for field username +msgid "Please enter a username." +msgstr "Vul een gebruikersnaam in" + +#: Model/User.php:validation for field username +msgid "The username must be alphanumeric." +msgstr "Een gebruikersnaam kan alleen uit letters en cijfers bestaan" + +#: Model/User.php:validation for field username +msgid "This username is already in use." +msgstr "De gebruikersnaam is al in gebruik." + +#: Model/User.php:validation for field username +msgid "The username must have at least 3 characters." +msgstr "De gebruikersnaam moet uit minstens 3 karakters bestaan." + +#: Model/User.php:validation for field email +msgid "Please enter a valid email address." +msgstr "Vul een geldig emailadres in." + +#: Model/User.php:validation for field email +msgid "This email is already in use." +msgstr "Het emailadres is al in gebruik." + +#: Model/User.php:validation for field password +msgid "The password must have at least 6 characters." +msgstr "Een wachtwoord moet uit minstens 6 karakters bestaan." + +#: Model/User.php:validation for field password +msgid "Please enter a password." +msgstr "Vul een wachtwoord in." + +#: Model/User.php:validation for field temppassword +msgid "The passwords are not equal, please try again." +msgstr "De wachtwoorden zijn niet gelijk. Probeer opnieuw." + +#: Model/User.php:validation for field tos +msgid "You must agree to the terms of use." +msgstr "Ga akkoord met de gebruikersvoorwaarden." + +#~ msgid "Invalid Detail." +#~ msgstr "Ongeldige gegevens." + +#~ msgid "Saved" +#~ msgstr "Opgeslagen" + +#~ msgid "%s details saved" +#~ msgstr "%s gegevens opgeslagen" + +#~ msgid "Invalid id for Detail" +#~ msgstr "Ongeldige id voor Gegeven" + +#~ msgid "User Detail deleted" +#~ msgstr "Gegeven verwijderd" + +#~ msgid "The Detail has been saved" +#~ msgstr "Gegeven is opgeslagen" + +#~ msgid "The Detail could not be saved. Please, try again." +#~ msgstr "Gegeven kon niet worden opgeslagen. Probeer opnieuw." + +#~ msgid "Invalid Detail" +#~ msgstr "Ongeldig gegeven" + +#~ msgid "Profile saved." +#~ msgstr "Profiel opgeslagen." + +#~ msgid "Could not save your profile." +#~ msgstr "Profiel kon niet worden opgeslagen." + +#~ msgid "Invalid date" +#~ msgstr "Ongeldige datum" + +#~ msgid "Add User Detail" +#~ msgstr "Voeg gegeven toe" + +#~ msgid "List Details" +#~ msgstr "Toon gegevens" + +#~ msgid "New User" +#~ msgstr "Nieuwe gebruiker" + +#~ msgid "Edit User Detail" +#~ msgstr "Wijzig gegeven" + +#~ msgid "User Details" +#~ msgstr "Toon gegevens" + +#~ msgid "New User Detail" +#~ msgstr "Voeg gegeven toe" + +#~ msgid "User Detail" +#~ msgstr "Voeg gegeven toe" + +#~ msgid "Id" +#~ msgstr "Id" + +#~ msgid "Position" +#~ msgstr "Positie" + +#~ msgid "Field" +#~ msgstr "Veld" + +#~ msgid "Value" +#~ msgstr "Waarde" + +#~ msgid "Edit Detail" +#~ msgstr "Wijzig gegeven" + +#~ msgid "Delete Detail" +#~ msgstr "Verwijder gegeven" + +#~ msgid "New Detail" +#~ msgstr "Voeg gegeven toe" + +#~ msgid "There url you accessed is not longer valid" +#~ msgstr "De URL, die u probeert te bezoeken, is niet langer geldig" + +#~ msgid "" +#~ "There was an error trying to validate your e-mail address. Please check " +#~ "your e-mail for the URL you should use to verify your e-mail address." +#~ msgstr "" +#~ "Er is een error opgetreden bij het verifiëren van uw email. Controleer de " +#~ "email voor de URL die moet worden gevolgt om uw emailadres te verifiëren." + +#~ msgid "floriank you have successfully logged out" +#~ msgstr "floriank, u bent succesvol ingelogd" + +#~ msgid "List Groups" +#~ msgstr "Toon groepen" + +#~ msgid "New Group" +#~ msgstr "Nieuwe groep" + +#~ msgid "Details" +#~ msgstr "Gegevens" + +#~ msgid "previous" +#~ msgstr "vorige" + +#~ msgid "next" +#~ msgstr "volgende" + +#~ msgid "Detail" +#~ msgstr "Gegeven" + +#~ msgid "Related Groups" +#~ msgstr "Gerelateerde Groepen" + +#~ msgid "User Id" +#~ msgstr "Gebruiker Id" + +#~ msgid "Is Public" +#~ msgstr "Publiekelijk" + +#~ msgid "Description" +#~ msgstr "Omschrijving" + +#~ msgid "Delete User" +#~ msgstr "Verwijder Gebruiker" + +#~ msgid "My Groups" +#~ msgstr "Mijn Groepen" + +#~ msgid "Create a new group" +#~ msgstr "Creëer een nieuwe groep" + +#~ msgid "Invite a user" +#~ msgstr "Nodig een gebruiker uit" + +#~ msgid "Requests to join" +#~ msgstr "Uitnodigen" + +#~ msgid "My own groups" +#~ msgstr "Mijn eigen groepen" + +#~ msgid "Members" +#~ msgstr "Leden" + +#~ msgid "Invite user" +#~ msgstr "Nodig gebruiker uit" + +#~ msgid "Manage Broadcast Scope" +#~ msgstr "Beheer uitzending bereik" + +#~ msgid "Access" +#~ msgstr "Toegang" + +#~ msgid "Addons" +#~ msgstr "Toevoegingen" + +#~ msgid "Groups im a member in" +#~ msgstr "Groepen waartoe ik behoor" + +#~ msgid "Leave group" +#~ msgstr "Verlaat groep" + +#~ msgid "Account registration" +#~ msgstr "Account registratie" + +#~ msgid "Please select a username that is not already in use" +#~ msgstr "Vul een gebruikersnaam in die nog niet in gebruik is" + +#~ msgid "Must be at least 3 characters" +#~ msgstr "Moet minstens 3 karakters bevatten" + +#~ msgid "Username must contain numbers and letters only" +#~ msgstr "Gebruikers naam kan alleen letters en cijfers bevatten" + +#~ msgid "Please choose username" +#~ msgstr "Kies een gebruikersnaam" + +#~ msgid "Must be at least 5 characters long" +#~ msgstr "Moet minstens 5 karakters bevatten" + +#~ msgid "Passwords must match" +#~ msgstr "Wachtwoorden moeten gelijk zijn" + +#~ msgid "You must verify you have read the Terms of Service" +#~ msgstr "U moet akkoord gaan met de gebruikersvoorwaarden" + +#~ msgid "Openid Identifier" +#~ msgstr "Openid identificatie" + +#~ msgid "Search for users" +#~ msgstr "Zoek gebruikers" From 1a4820587dd4f5308d93f685f52053c4b0a3eac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 16 Sep 2013 13:53:55 +0200 Subject: [PATCH 0073/1476] Moving the App::uses calls on top of the class --- Model/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Model/User.php b/Model/User.php index d2b18d673..b16922ce4 100644 --- a/Model/User.php +++ b/Model/User.php @@ -11,6 +11,8 @@ App::uses('Security', 'Utility'); App::uses('UsersAppModel', 'Users.Model'); +App::uses('SearchableBehavior', 'Search.Model/Behavior'); +App::uses('SluggableBehavior', 'Utils.Model/Behavior'); /** * Users Plugin User Model @@ -133,12 +135,10 @@ public function __construct($id = false, $table = null, $ds = null) { * @link https://github.com/CakeDC/utils */ protected function _setupBehaviors() { - App::uses('SearchableBehavior', 'Search.Model/Behavior'); if (class_exists('SearchableBehavior')) { $this->actsAs[] = 'Search.Searchable'; } - App::uses('SluggableBehavior', 'Utils.Model/Behavior'); if (class_exists('SluggableBehavior') && Configure::read('Users.disableSlugs') !== true) { $this->actsAs['Utils.Sluggable'] = array( 'label' => 'username', From 11f2a182910a9fce650803059b5ddc8ea63e2fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 16 Sep 2013 14:11:17 +0200 Subject: [PATCH 0074/1476] Working in implementing more events --- Controller/UsersController.php | 27 ++++++++++++++++++++++++--- Model/User.php | 34 +++++++++++++++++++++++----------- readme.md | 17 +++++++++++++++++ 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index c81b31ef1..90ff68f99 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -397,7 +397,11 @@ public function add() { if (!empty($this->request->data)) { $user = $this->{$this->modelClass}->register($this->request->data); if ($user !== false) { - $Event = new CakeEvent('Users.UsersController.afterRegistration', $this, $this->request->data); + $Event = new CakeEvent( + 'Users.Controller.Users.afterRegistration', + $this, + $this->request->data + ); $this->getEventManager()->dispatch($Event); if ($Event->isStopped()) { $this->redirect(array('action' => 'login')); @@ -420,10 +424,27 @@ public function add() { * @return void */ public function login() { + $Event = new CakeEvent( + 'Users.Controller.Users.beforeLogin', + $this + ); + + $this->getEventManager()->dispatch($Event); + + if ($Event->isStopped()) { + return false; + } + if ($this->request->is('post')) { if ($this->Auth->login()) { - $Event = new CakeEvent('Users.UsersController.afterLogin', $this, array( - 'isFirstLogin' => !$this->Auth->user('last_login'))); + $Event = new CakeEvent( + 'Users.Controller.Users.afterLogin', + $this, + array( + 'isFirstLogin' => !$this->Auth->user('last_login') + ) + ); + $this->getEventManager()->dispatch($Event); $this->{$this->modelClass}->id = $this->Auth->user('id'); diff --git a/Model/User.php b/Model/User.php index c5f343f9b..ac542c426 100644 --- a/Model/User.php +++ b/Model/User.php @@ -513,6 +513,17 @@ public function checkEmailVerification($postData = array(), $renew = true) { * @return mixed */ public function register($postData = array(), $options = array()) { + $Event = new CakeEvent( + 'Users.Model.User.beforeRegister', + $this, + $this->request->data + ); + + $this->getEventManager()->dispatch($Event); + if ($Event->isStopped()) { + return $Event->result; + } + if (is_bool($options)) { $options = array('emailVerification' => $options); } @@ -529,24 +540,25 @@ public function register($postData = array(), $options = array()) { $this->_removeExpiredRegistrations(); } - $Event = new CakeEvent('Users.User.beforeRegister', $this); - $this->getEventManager()->dispatch($Event); - if ($Event->isStopped()) { - return $Event->result; - } - $this->set($postData); if ($this->validates()) { $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); $this->create(); $this->data = $this->save($postData, false); $this->data[$this->alias]['id'] = $this->id; + + $Event = new CakeEvent( + 'Users.Model.User.afterRegister', + $this + ); + + $this->getEventManager()->dispatch($Event); + + if ($Event->isStopped()) { + return $Event->result; + } + if ($returnData) { - $Event = new CakeEvent('Users.User.afterRegister', $this, $this->request->data); - $this->getEventManager()->dispatch($Event); - if ($Event->isStopped()) { - return $Event->result; - } return $this->data; } return true; diff --git a/readme.md b/readme.md index 4c3579e14..5c704694b 100644 --- a/readme.md +++ b/readme.md @@ -258,6 +258,23 @@ Disables/enables the password reset functionality Email configuration settings array used by this plugin +## Events ## + +Events follow these conventions: + + Users.Controller.Users.someCallBack + Users.Model.User.someCallBack + ... + +Triggered events are: + + * Users.Controller.Users.beforeRegister + * Users.Controller.Users.afterRegister + * Users.Controller.Users.beforeLogin + * Users.Controller.Users.afterLogin + * Users.Model.User.beforeRegister + * Users.Model.User.afterRegister + ## Requirements ## * PHP version: PHP 5.2+ From 2dd064b5e89b022929860cc08a4559970346a28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 16 Sep 2013 14:19:48 +0200 Subject: [PATCH 0075/1476] Refining the events --- Controller/UsersController.php | 12 +++++++++--- Model/User.php | 11 +++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 90ff68f99..89ecd9d63 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -400,7 +400,9 @@ public function add() { $Event = new CakeEvent( 'Users.Controller.Users.afterRegistration', $this, - $this->request->data + array( + 'data' => $this->request->data, + ) ); $this->getEventManager()->dispatch($Event); if ($Event->isStopped()) { @@ -426,13 +428,16 @@ public function add() { public function login() { $Event = new CakeEvent( 'Users.Controller.Users.beforeLogin', - $this + $this, + array( + 'data' => $this->request->data, + ) ); $this->getEventManager()->dispatch($Event); if ($Event->isStopped()) { - return false; + return; } if ($this->request->is('post')) { @@ -441,6 +446,7 @@ public function login() { 'Users.Controller.Users.afterLogin', $this, array( + 'data' => $this->request->data, 'isFirstLogin' => !$this->Auth->user('last_login') ) ); diff --git a/Model/User.php b/Model/User.php index ac542c426..a713bb3cb 100644 --- a/Model/User.php +++ b/Model/User.php @@ -516,7 +516,10 @@ public function register($postData = array(), $options = array()) { $Event = new CakeEvent( 'Users.Model.User.beforeRegister', $this, - $this->request->data + array( + 'data' => $postData, + 'options' => $options + ) ); $this->getEventManager()->dispatch($Event); @@ -549,7 +552,11 @@ public function register($postData = array(), $options = array()) { $Event = new CakeEvent( 'Users.Model.User.afterRegister', - $this + $this, + array( + 'data' => $this->data, + 'options' => $options + ) ); $this->getEventManager()->dispatch($Event); From 52cda09618f16b1f2f38f48ba100abef128c3ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 18 Sep 2013 22:19:16 +0100 Subject: [PATCH 0076/1476] fixing some typos in spanish translation, and using fix suggestion from @tsolar --- Locale/spa/LC_MESSAGES/users.po | 86 ++++++++++++++++----------------- Locale/users.pot | 70 +++++++++++++-------------- 2 files changed, 78 insertions(+), 78 deletions(-) diff --git a/Locale/spa/LC_MESSAGES/users.po b/Locale/spa/LC_MESSAGES/users.po index e947da423..c8529a310 100644 --- a/Locale/spa/LC_MESSAGES/users.po +++ b/Locale/spa/LC_MESSAGES/users.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: Users CakePHP plugin\n" "POT-Creation-Date: 2010-09-15 15:48+0200\n" -"PO-Revision-Date: 2010-09-24 16:38-0400\n" -"Last-Translator: José Lorenzo Rodríguez \n" +"PO-Revision-Date: 2013-09-18 22:13-0000\n" +"Last-Translator: Jorge González \n" "Language-Team: CakeDC \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -22,7 +22,7 @@ msgstr "" #: /controllers/details_controller.php:57;138 msgid "Invalid Detail." -msgstr "Detalle no váido" +msgstr "Detalle no válido." #: /controllers/details_controller.php:78 msgid "Saved" @@ -58,7 +58,7 @@ msgstr "Perfil guardado" #: /controllers/users_controller.php:159 msgid "Could not save your profile." -msgstr "No se pudo guardar su perfil" +msgstr "No se pudo guardar su perfil." #: /controllers/users_controller.php:193 msgid "Invalid User." @@ -83,25 +83,25 @@ msgstr "Usuario no válido" #: /controllers/users_controller.php:273 msgid "You are already registered and logged in!" -msgstr "¡Ya estás registrado e iniciado la sesión!" +msgstr "¡Ya estás registrado y has iniciado la sesión!" #: /controllers/users_controller.php:282 #: /tests/cases/controllers/users_controller.test.php:194 msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Su cuenta ha sido creada. Debería recibir un correo para autenticar su cuenta. Una vez validada podrá iniciar sesión" +msgstr "Su cuenta ha sido creada. Debería recibir un correo con un enlace para verificar su cuenta de correo. Una vez validado, podrá iniciar sesión." #: /controllers/users_controller.php:287 #: /tests/cases/controllers/users_controller.test.php:205 msgid "Your account could not be created. Please, try again." -msgstr "Su suenta no pudo ser creada, intente de nuevo" +msgstr "Su cuenta no pudo ser creada, por favor inténtelo de nuevo." #: /controllers/users_controller.php:309 msgid "%s you have successfully logged in" -msgstr "%s usted ha iniciado sesión" +msgstr "%s ha iniciado sesión" #: /controllers/users_controller.php:383 msgid "%s you have successfully logged out" -msgstr "%s usted ha cerrado la sesión" +msgstr "%s ha cerrado la sesión" #: /controllers/users_controller.php:409 msgid "There url you accessed is not longer valid" @@ -117,11 +117,11 @@ msgstr "Su contraseña ha sido reiniciada" #: /controllers/users_controller.php:435 msgid "Please login using this password and change your password" -msgstr "Por favor ingrese usando esta contraseña y luego cámbiela" +msgstr "Por favor acceda usando esta contraseña y luego cámbiela" #: /controllers/users_controller.php:438 msgid "Your password was sent to your registered email account" -msgstr "Su contraseña fue enviada a su cuenta de correo registrada" +msgstr "Su contraseña fue enviada a la cuenta de correo que utilizó al registrarse" #: /controllers/users_controller.php:444 #: /tests/cases/controllers/users_controller.test.php:219 @@ -130,7 +130,7 @@ msgstr "¡Su correo ha sido validado!" #: /controllers/users_controller.php:448 msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "Ocurrió un error tratando de validar su dirección de correo. Por favor verifique su correo en busca del URL que debe usar para verificar su cuenta." +msgstr "Ocurrió un error tratando de validar su dirección de correo. Por favor verifique su correo y utilice la URL que le hemos enviado para validar su cuenta. Tenga en cuenta que a veces los correos pueden ser clasificados como correo basura (SPAM) por error, por favor revise su bandeja de entrada y su bandeja de SPAM." #: /controllers/users_controller.php:452 #: /tests/cases/controllers/users_controller.test.php:224 @@ -147,31 +147,31 @@ msgstr "Verificación de cuenta" #: /controllers/users_controller.php:563 msgid "%s has been sent an email with instruction to reset their password." -msgstr "%s ha sido enviado un correo con instrucciones para reiniciar su contraseña" +msgstr "%s, le hemos enviado un correo con instrucciones para reiniciar su contraseña." #: /controllers/users_controller.php:567 msgid "You should receive an email with further instructions shortly" -msgstr "Debe resibir un correo con más instrucciones en breve" +msgstr "Recibirá un correo con más instrucciones en breve" #: /controllers/users_controller.php:571 msgid "No user was found with that email." -msgstr "Ningún usuario fue encontrado con dicho correo" +msgstr "Ningún usuario fue encontrado con dicho correo." #: /controllers/users_controller.php:588 msgid "Invalid password reset token, try again." -msgstr "Contraseña no válida" +msgstr "Contraseña no válida, por favor inténtelo de nuevo." #: /controllers/users_controller.php:594 msgid "Password changed, you can now login with your new password." -msgstr "Contraseña modificada, ahora puede ingresar nuevamente" +msgstr "Contraseña modificada, ahora puede acceder nuevamente." #: /models/user.php:102 msgid "Please enter a username" -msgstr "Por favor ingrese un nombre de usuario" +msgstr "Por favor, introduzca un nombre de usuario" #: /models/user.php:105 msgid "The username must be alphanumeric" -msgstr "El nombre de usuario debe ser alfa-numérico" +msgstr "El nombre de usuario debe estar compuesto únicamente por letras y números, sin espacios" #: /models/user.php:108 msgid "This username is already in use." @@ -183,35 +183,35 @@ msgstr "El nombre de usuario debe contener al menos 3 caracteres" #: /models/user.php:116 msgid "Please enter a valid email address." -msgstr "Por favor ingrese una dirección de correo electrónico válida" +msgstr "Por favor introduzca una dirección de correo electrónico válida." #: /models/user.php:119 msgid "This email is already in use." -msgstr "Este correo ya se encuentra en uso" +msgstr "Este correo ya se encuentra en uso." #: /models/user.php:123 msgid "The password must have at least 8 characters." -msgstr "La contraseña debe tener al menos 8 caracteres" +msgstr "La contraseña debe tener al menos 8 caracteres." #: /models/user.php:126 msgid "Please enter a password." -msgstr "Por favor ingrese una contraseña" +msgstr "Por favor introduzca una contraseña." #: /models/user.php:129 msgid "The passwords are not equal, please try again." -msgstr "Las contraseñas no coinciden, por favor intente de nuevo" +msgstr "Las contraseñas no coinciden, por favor inténtelo de nuevo." #: /models/user.php:132 msgid "You must agree to the terms of use." -msgstr "Debe estar de acuerdo con los términos de uso" +msgstr "Debe aceptar las condiciones de uso." #: /models/user.php:137;357 msgid "The passwords are not equal." -msgstr "Las contraseñas no coinciden" +msgstr "Las contraseñas no coinciden." #: /models/user.php:139 msgid "Invalid password." -msgstr "Contraseña no válida" +msgstr "Contraseña no válida." #: /models/user.php:150 msgid "Invalid date" @@ -219,11 +219,11 @@ msgstr "Fecha no válida" #: /models/user.php:315 msgid "This Email Address exists but was never validated." -msgstr "La dirección de correo existe, pero nunca fue validada" +msgstr "La dirección de correo existe, pero nunca fue validada." #: /models/user.php:317 msgid "This Email Address does not exist in the system." -msgstr "Esta dirección de correo no existe en el sistema" +msgstr "Esta dirección de correo no existe en el sistema." # Error? #: /models/user.php:406 @@ -232,11 +232,11 @@ msgstr "" #: /models/user.php:460 msgid "The user does not exist." -msgstr "El usuario no existe" +msgstr "El usuario no existe." #: /models/user.php:505 msgid "Please enter your email address." -msgstr "Por favor ingresa tu dirección de correo" +msgstr "Por favor introduce tu dirección de correo." #: /models/user.php:515 msgid "The email address does not exist in the system" @@ -244,11 +244,11 @@ msgstr "La dirección de correo no existe en el sistema" #: /models/user.php:520 msgid "Your account is already authenticaed." -msgstr "Yu cuenta ya ha sido autenticada" +msgstr "Tu cuenta ya ha sido autenticada." #: /models/user.php:525 msgid "Your account is disabled." -msgstr "Tu cuenta está deshabilidata" +msgstr "Tu cuenta está deshabilitada" #: /tests/cases/controllers/users_controller.test.php:34 msgid "Sorry, but you need to login to access this location." @@ -256,7 +256,7 @@ msgstr "Lo sentimos, pero debe iniciar sesión para acceder a esta ubicación" #: /tests/cases/controllers/users_controller.test.php:35;174 msgid "Invalid e-mail / password combination. Please try again" -msgstr "Combinación de correo / contraseña no válida. Intente de nuevo" +msgstr "Combinación de email / contraseña no válida. Por favor, inténtelo de nuevo" #: /tests/cases/controllers/users_controller.test.php:168 msgid "testuser you have successfully logged in" @@ -348,7 +348,7 @@ msgstr "Eliminar" #: /views/users/admin_view.ctp:24 #: /views/users/index.ctp:33 msgid "Are you sure you want to delete # %s?" -msgstr "¿Está seguro que desea eliminar %s?" +msgstr "¿Está seguro que desea eliminar # %s?" #: /views/details/admin_index.ctp:2 #: /views/users/register.ctp:4 @@ -563,7 +563,7 @@ msgstr "Cambiar contraseña" #: /views/users/change_password.ctp:3 msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "Por favor ingrese su antigua contraseña por razones de seguridad y luego ingrese su nueva contraseña dos veces" +msgstr "Por favor introduzca su contraseña anterior por razones de seguridad y luego su nueva contraseña dos veces." #: /views/users/change_password.ctp:8 msgid "Old Password" @@ -572,7 +572,7 @@ msgstr "Contraseña anterior" #: /views/users/change_password.ctp:11 #: /views/users/reset_password.ctp:9 msgid "New Password" -msgstr "Nueva Contraseña" +msgstr "Nueva contraseña" #: /views/users/change_password.ctp:14 #: /views/users/reset_password.ctp:12 @@ -597,7 +597,7 @@ msgstr "Crear un nuevo grupo" #: /views/users/groups.ctp:6 msgid "Invite a user" -msgstr "Invitar un usuario" +msgstr "Invitar a un usuario" #: /views/users/groups.ctp:7 msgid "Requests to join" @@ -661,7 +661,7 @@ msgstr "Por favor escoja un nombre de usuario" #: /views/users/register.ctp:15 msgid "E-mail (used as login)" -msgstr "Correo (usuado para ingresar)" +msgstr "Correo (usado para acceder)" #: /views/users/register.ctp:16 msgid "Must be a valid email address" @@ -685,15 +685,15 @@ msgstr "Las contraseñas deben coincidir" #: /views/users/register.ctp:29;85 msgid "I have read and agreed to " -msgstr "He leido y estoy de acuerdo con" +msgstr "He leído y estoy de acuerdo con" #: /views/users/register.ctp:29;85 msgid "Terms of Service" -msgstr "Términos del Servicio" +msgstr "Condiciones del Servicio" #: /views/users/register.ctp:30;86 msgid "You must verify you have read the Terms of Service" -msgstr "Debe verificar que ha leído los Términos de Servicio" +msgstr "Debe verificar que ha leído las Condiciones de Servicio" #: /views/users/register.ctp:46 msgid "Openid Identifier" @@ -705,7 +705,7 @@ msgstr "¿Olvidó su contraseña?" #: /views/users/request_password_change.ctp:3 msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Por favor ingrese el correo que utilizó para registrarse y recibirá un correo con más instrucciones" +msgstr "Por favor introduzca el correo que utilizó para registrarse y recibirá un correo con más instrucciones" #: /views/users/request_password_change.ctp:11 msgid "Your Email" diff --git a/Locale/users.pot b/Locale/users.pot index a7fc0c5da..aab333679 100644 --- a/Locale/users.pot +++ b/Locale/users.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2013-09-11 11:46+0200\n" +"POT-Creation-Date: 2013-09-18 22:41+0200\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" @@ -31,7 +31,7 @@ msgid "User deleted" msgstr "" #: Controller/UsersController.php:371 -#: Model/User.php:821 +#: Model/User.php:829;858 msgid "Invalid User" msgstr "" @@ -39,83 +39,83 @@ msgstr "" msgid "You are already registered and logged in!" msgstr "" -#: Controller/UsersController.php:401 +#: Controller/UsersController.php:413 #: Test/Case/Controller/UsersControllerTest.php:342 msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." msgstr "" -#: Controller/UsersController.php:406 +#: Controller/UsersController.php:418 #: Test/Case/Controller/UsersControllerTest.php:357 msgid "Your account could not be created. Please, try again." msgstr "" -#: Controller/UsersController.php:428 +#: Controller/UsersController.php:462 msgid "%s you have successfully logged in" msgstr "" -#: Controller/UsersController.php:444 +#: Controller/UsersController.php:483 #: Test/Case/Controller/UsersControllerTest.php:316 msgid "Invalid e-mail / password combination. Please try again" msgstr "" -#: Controller/UsersController.php:510 +#: Controller/UsersController.php:549 msgid "%s you have successfully logged out" msgstr "" -#: Controller/UsersController.php:524 +#: Controller/UsersController.php:563 msgid "The email was resent. Please check your inbox." msgstr "" -#: Controller/UsersController.php:527 +#: Controller/UsersController.php:566 msgid "The email could not be sent. Please check errors." msgstr "" -#: Controller/UsersController.php:550 +#: Controller/UsersController.php:589 #: Test/Case/Controller/UsersControllerTest.php:374 msgid "Your e-mail has been validated!" msgstr "" -#: Controller/UsersController.php:573 +#: Controller/UsersController.php:612 msgid "The url you accessed is not longer valid" msgstr "" -#: Controller/UsersController.php:579 +#: Controller/UsersController.php:618 msgid "Your password was sent to your registered email account" msgstr "" -#: Controller/UsersController.php:583 +#: Controller/UsersController.php:622 msgid "There was an error verifying your account. Please check the email you were sent, and retry the verification link." msgstr "" -#: Controller/UsersController.php:599;709 +#: Controller/UsersController.php:638;748 msgid "Password Reset" msgstr "" -#: Controller/UsersController.php:616;780 +#: Controller/UsersController.php:655;819 msgid "Password changed." msgstr "" -#: Controller/UsersController.php:677 +#: Controller/UsersController.php:716 msgid "Account verification" msgstr "" -#: Controller/UsersController.php:736 +#: Controller/UsersController.php:775 msgid "%s has been sent an email with instruction to reset their password." msgstr "" -#: Controller/UsersController.php:740 +#: Controller/UsersController.php:779 msgid "You should receive an email with further instructions shortly" msgstr "" -#: Controller/UsersController.php:744 +#: Controller/UsersController.php:783 msgid "No user was found with that email." msgstr "" -#: Controller/UsersController.php:774 +#: Controller/UsersController.php:813 msgid "Invalid password reset token, try again." msgstr "" -#: Controller/UsersController.php:783 +#: Controller/UsersController.php:822 msgid "Password changed, you can now login with your new password." msgstr "" @@ -164,19 +164,19 @@ msgstr "" msgid "This email is already verified." msgstr "" -#: Model/User.php:554 +#: Model/User.php:584 msgid "Please enter your email address." msgstr "" -#: Model/User.php:561 +#: Model/User.php:591 msgid "The email address does not exist in the system" msgstr "" -#: Model/User.php:566 +#: Model/User.php:596 msgid "Your account is already authenticaed." msgstr "" -#: Model/User.php:571 +#: Model/User.php:601 msgid "Your account is disabled." msgstr "" @@ -472,43 +472,43 @@ msgstr "" msgid "Name" msgstr "" -#: Model/User.php:validation for field username +#: Plugin/Users/Model/User.php:validation for field username msgid "Please enter a username." msgstr "" -#: Model/User.php:validation for field username +#: Plugin/Users/Model/User.php:validation for field username msgid "The username must be alphanumeric." msgstr "" -#: Model/User.php:validation for field username +#: Plugin/Users/Model/User.php:validation for field username msgid "This username is already in use." msgstr "" -#: Model/User.php:validation for field username +#: Plugin/Users/Model/User.php:validation for field username msgid "The username must have at least 3 characters." msgstr "" -#: Model/User.php:validation for field email +#: Plugin/Users/Model/User.php:validation for field email msgid "Please enter a valid email address." msgstr "" -#: Model/User.php:validation for field email +#: Plugin/Users/Model/User.php:validation for field email msgid "This email is already in use." msgstr "" -#: Model/User.php:validation for field password +#: Plugin/Users/Model/User.php:validation for field password msgid "The password must have at least 6 characters." msgstr "" -#: Model/User.php:validation for field password +#: Plugin/Users/Model/User.php:validation for field password msgid "Please enter a password." msgstr "" -#: Model/User.php:validation for field temppassword +#: Plugin/Users/Model/User.php:validation for field temppassword msgid "The passwords are not equal, please try again." msgstr "" -#: Model/User.php:validation for field tos +#: Plugin/Users/Model/User.php:validation for field tos msgid "You must agree to the terms of use." msgstr "" From e0b46bc4e2e6895505bf6a9a40e74ceb6a195510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 18 Sep 2013 22:49:35 +0100 Subject: [PATCH 0077/1476] fixing some keys to refer to users domain and adding missing keys to spa translation --- .../Component/Auth/TokenAuthenticate.php | 2 +- Locale/spa/LC_MESSAGES/users.po | 1015 ++++++++--------- Locale/users.pot | 14 +- View/Elements/pagination.ctp | 4 +- 4 files changed, 521 insertions(+), 514 deletions(-) diff --git a/Controller/Component/Auth/TokenAuthenticate.php b/Controller/Component/Auth/TokenAuthenticate.php index bcfe60c47..b837cb175 100644 --- a/Controller/Component/Auth/TokenAuthenticate.php +++ b/Controller/Component/Auth/TokenAuthenticate.php @@ -64,7 +64,7 @@ class TokenAuthenticate extends BaseAuthenticate { public function __construct(ComponentCollection $collection, $settings) { parent::__construct($collection, $settings); if (empty($this->settings['parameter']) && empty($this->settings['header'])) { - throw new CakeException(__d('authenticate', 'You need to specify token parameter and/or header')); + throw new CakeException(__d('users', 'You need to specify token parameter and/or header')); } } diff --git a/Locale/spa/LC_MESSAGES/users.po b/Locale/spa/LC_MESSAGES/users.po index c8529a310..f78d2c3da 100644 --- a/Locale/spa/LC_MESSAGES/users.po +++ b/Locale/spa/LC_MESSAGES/users.po @@ -11,711 +11,706 @@ msgid "" msgstr "" "Project-Id-Version: Users CakePHP plugin\n" -"POT-Creation-Date: 2010-09-15 15:48+0200\n" -"PO-Revision-Date: 2013-09-18 22:13-0000\n" +"POT-Creation-Date: 2013-09-18 23:20+0200\n" +"PO-Revision-Date: 2013-09-18 22:36-0000\n" "Last-Translator: Jorge González \n" "Language-Team: CakeDC \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "Detalle no válido." - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "Guardado" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "%s detalles guardados" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "Identificador no válido para detalle" - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "Detalle eliminado" - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "El detalle ha sido guardado" - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "El detalle no pudo ser guardado, intente de nuevo" - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "Detalle no válido" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "Perfil guardado" - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "No se pudo guardar su perfil." - -#: /controllers/users_controller.php:193 +#: Controller/UsersController.php:310 msgid "Invalid User." msgstr "Usuario no válido" -#: /controllers/users_controller.php:207 +#: Controller/UsersController.php:328 msgid "The User has been saved" msgstr "El usuario ha sido guardado" -#: /controllers/users_controller.php:223 +#: Controller/UsersController.php:345 msgid "User saved" msgstr "Usuario guardado" -#: /controllers/users_controller.php:247 +#: Controller/UsersController.php:369 msgid "User deleted" msgstr "Usuario elimianado" -#: /controllers/users_controller.php:249 -#: /models/user.php:703 +#: Controller/UsersController.php:371 +#: Model/User.php:829;858 msgid "Invalid User" msgstr "Usuario no válido" -#: /controllers/users_controller.php:273 +#: Controller/UsersController.php:393 msgid "You are already registered and logged in!" msgstr "¡Ya estás registrado y has iniciado la sesión!" -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 +#: Controller/UsersController.php:413 +#: Test/Case/Controller/UsersControllerTest.php:342 msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." msgstr "Su cuenta ha sido creada. Debería recibir un correo con un enlace para verificar su cuenta de correo. Una vez validado, podrá iniciar sesión." -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 +#: Controller/UsersController.php:418 +#: Test/Case/Controller/UsersControllerTest.php:357 msgid "Your account could not be created. Please, try again." msgstr "Su cuenta no pudo ser creada, por favor inténtelo de nuevo." -#: /controllers/users_controller.php:309 +#: Controller/UsersController.php:462 msgid "%s you have successfully logged in" msgstr "%s ha iniciado sesión" -#: /controllers/users_controller.php:383 +#: Controller/UsersController.php:483 +#: Test/Case/Controller/UsersControllerTest.php:316 +msgid "Invalid e-mail / password combination. Please try again" +msgstr "Combinación de email / contraseña no válida. Por favor, inténtelo de nuevo" + +#: Controller/UsersController.php:549 msgid "%s you have successfully logged out" msgstr "%s ha cerrado la sesión" -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" -msgstr "El url que intentó acceder ya no es válido" +#: Controller/UsersController.php:563 +msgid "The email was resent. Please check your inbox." +msgstr "Se ha reenviado el correo, por favor compruebe que le ha llegado a su bandeja de entrada." -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" -msgstr "Contraseña reiniciada" +#: Controller/UsersController.php:566 +msgid "The email could not be sent. Please check errors." +msgstr "El email no se pudo enviar. Por favor compruebe los errores y/o la configuración de envío de emails." -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" -msgstr "Su contraseña ha sido reiniciada" +#: Controller/UsersController.php:589 +#: Test/Case/Controller/UsersControllerTest.php:374 +msgid "Your e-mail has been validated!" +msgstr "¡Su correo ha sido validado!" -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" -msgstr "Por favor acceda usando esta contraseña y luego cámbiela" +#: Controller/UsersController.php:612 +msgid "The url you accessed is not longer valid" +msgstr "El URL que accedió no es válido" -#: /controllers/users_controller.php:438 +#: Controller/UsersController.php:618 msgid "Your password was sent to your registered email account" msgstr "Su contraseña fue enviada a la cuenta de correo que utilizó al registrarse" -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 -msgid "Your e-mail has been validated!" -msgstr "¡Su correo ha sido validado!" - -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "Ocurrió un error tratando de validar su dirección de correo. Por favor verifique su correo y utilice la URL que le hemos enviado para validar su cuenta. Tenga en cuenta que a veces los correos pueden ser clasificados como correo basura (SPAM) por error, por favor revise su bandeja de entrada y su bandeja de SPAM." +#: Controller/UsersController.php:622 +msgid "There was an error verifying your account. Please check the email you were sent, and retry the verification link." +msgstr "Hubo un error al verificar su cuenta. Por favor utilice el enlace de verificación que le enviamos a su cuenta de correo." -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 -msgid "The url you accessed is not longer valid" -msgstr "El URL que accedió no es válido" +#: Controller/UsersController.php:638;748 +msgid "Password Reset" +msgstr "Contraseña reiniciada" -#: /controllers/users_controller.php:467 +#: Controller/UsersController.php:655;819 msgid "Password changed." msgstr "Contraseña modificada" -#: /controllers/users_controller.php:521 +#: Controller/UsersController.php:716 msgid "Account verification" msgstr "Verificación de cuenta" -#: /controllers/users_controller.php:563 +#: Controller/UsersController.php:775 msgid "%s has been sent an email with instruction to reset their password." msgstr "%s, le hemos enviado un correo con instrucciones para reiniciar su contraseña." -#: /controllers/users_controller.php:567 +#: Controller/UsersController.php:779 msgid "You should receive an email with further instructions shortly" msgstr "Recibirá un correo con más instrucciones en breve" -#: /controllers/users_controller.php:571 +#: Controller/UsersController.php:783 msgid "No user was found with that email." msgstr "Ningún usuario fue encontrado con dicho correo." -#: /controllers/users_controller.php:588 +#: Controller/UsersController.php:813 msgid "Invalid password reset token, try again." msgstr "Contraseña no válida, por favor inténtelo de nuevo." -#: /controllers/users_controller.php:594 +#: Controller/UsersController.php:822 msgid "Password changed, you can now login with your new password." msgstr "Contraseña modificada, ahora puede acceder nuevamente." -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "Por favor, introduzca un nombre de usuario" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "El nombre de usuario debe estar compuesto únicamente por letras y números, sin espacios" - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "Este nombre de usuario ya se encuentra en uso" - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "El nombre de usuario debe contener al menos 3 caracteres" +#: Controller/Component/RememberMeComponent.php:230 +msgid "Invalid options %s" +msgstr "Opciones no válidas %s" -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "Por favor introduzca una dirección de correo electrónico válida." - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "Este correo ya se encuentra en uso." - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "La contraseña debe tener al menos 8 caracteres." - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "Por favor introduzca una contraseña." - -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." -msgstr "Las contraseñas no coinciden, por favor inténtelo de nuevo." +#: Controller/Component/Auth/TokenAuthenticate.php:67 +msgid "You need to specify token parameter and/or header" +msgstr "Necesita especificar un token y/o cabecera" -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "Debe aceptar las condiciones de uso." - -#: /models/user.php:137;357 +#: Model/User.php:158;339 msgid "The passwords are not equal." msgstr "Las contraseñas no coinciden." -#: /models/user.php:139 +#: Model/User.php:160 msgid "Invalid password." msgstr "Contraseña no válida." -#: /models/user.php:150 -msgid "Invalid date" -msgstr "Fecha no válida" +#: Model/User.php:242 +#: Test/Case/Controller/UsersControllerTest.php:382 +msgid "Invalid token, please check the email you were sent, and retry the verification link." +msgstr "Token inválido, por favor compruebe el correo de verificación que le enviamos a su cuenta y vuelva a intentarlo mediante el enlace que aparece en el contenido del mensaje." + +#: Model/User.php:247 +msgid "The token has expired." +msgstr "El token ha expirado." -#: /models/user.php:315 +#: Model/User.php:301 msgid "This Email Address exists but was never validated." msgstr "La dirección de correo existe, pero nunca fue validada." -#: /models/user.php:317 +#: Model/User.php:303 msgid "This Email Address does not exist in the system." msgstr "Esta dirección de correo no existe en el sistema." # Error? -#: /models/user.php:406 +#: Model/User.php:397 msgid "$this->data['" -msgstr "" +msgstr "$this->data['" -#: /models/user.php:460 +#: Model/User.php:443 msgid "The user does not exist." msgstr "El usuario no existe." -#: /models/user.php:505 +#: Model/User.php:481 +msgid "Invalid Email address." +msgstr "La cuenta de correo no es válida." + +#: Model/User.php:486 +msgid "This email is already verified." +msgstr "Este correo ya se ha verificado correctamente." + +#: Model/User.php:584 msgid "Please enter your email address." msgstr "Por favor introduce tu dirección de correo." -#: /models/user.php:515 +#: Model/User.php:591 msgid "The email address does not exist in the system" msgstr "La dirección de correo no existe en el sistema" -#: /models/user.php:520 +#: Model/User.php:596 msgid "Your account is already authenticaed." msgstr "Tu cuenta ya ha sido autenticada." -#: /models/user.php:525 +#: Model/User.php:601 msgid "Your account is disabled." msgstr "Tu cuenta está deshabilitada" -#: /tests/cases/controllers/users_controller.test.php:34 +#: Test/Case/Controller/UsersControllerTest.php:55 msgid "Sorry, but you need to login to access this location." msgstr "Lo sentimos, pero debe iniciar sesión para acceder a esta ubicación" -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Combinación de email / contraseña no válida. Por favor, inténtelo de nuevo" - -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" -msgstr "testuser has ingresado exitosamente" - -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" -msgstr "floriank you have successfully logged out" - -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" -msgstr "Agregar detalle" - -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" -msgstr "Listar detalles" - -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 -msgid "List Users" -msgstr "Listar usuarios" +#: Test/Case/Controller/UsersControllerTest.php:275 +msgid "adminuser you have successfully logged in" +msgstr "adminuser has ingresado exitosamente" -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "Nuevo usuario" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "Listar grupos" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "Nuevo grupo" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "Editar detalle" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" -msgstr "Eliminar" +#: Test/Case/Controller/UsersControllerTest.php:401 +msgid "testuser you have successfully logged out" +msgstr "testuser has cerrado sesión" -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" -msgstr "¿Está seguro que desea eliminar # %s?" - -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" -msgstr "Detalles" - -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "Página %page% de %pages%, mostrando %current% registros de %count% en total, empezando en %start% y terminando en %end%" - -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" -msgstr "Acciones" - -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" -msgstr "Ver" - -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" -msgstr "Editar" - -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 +#: View/Elements/pagination.ctp:14 msgid "previous" msgstr "anterior" -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 +#: View/Elements/pagination.ctp:16 msgid "next" msgstr "siguiente" -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" -msgstr "Nuevo detalle" - -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" -msgstr "Detalle" - -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" -msgstr "Id" - -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" -msgstr "Usuario" +#: View/Elements/Users/admin_sidebar.ctp:3 +#: View/Elements/Users/sidebar.ctp:9 +msgid "Logout" +msgstr "Cerrar sesión" -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" -msgstr "Posición" - -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" -msgstr "Campo" - -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" -msgstr "Valor" - -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" -msgstr "Creado" - -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" -msgstr "Modificado" +#: View/Elements/Users/admin_sidebar.ctp:4 +#: View/Elements/Users/sidebar.ctp:10 +msgid "My Account" +msgstr "Mi Cuenta" -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" -msgstr "Eliminar detalle" - -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" -msgstr "Grupos relacionado" - -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" -msgstr "Usuario Id" - -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" -msgstr "Es Público" - -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" -msgstr "Nombre" - -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" -msgstr "Descripción" - -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" -msgstr "Enviar" +#: View/Elements/Users/admin_sidebar.ctp:6 +#, fuzzy +msgid "Add Users" +msgstr "Agregar usuario" -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" -msgstr "Correo" +#: View/Elements/Users/admin_sidebar.ctp:7 +#: View/Elements/Users/sidebar.ctp:15 +msgid "List Users" +msgstr "Listar usuarios" -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 -msgid "Password" -msgstr "Contraseña" +#: View/Elements/Users/admin_sidebar.ctp:9 +msgid "Frontend" +msgstr "Público" -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 +#: View/Elements/Users/sidebar.ctp:4 +#: View/Users/login.ctp:13 msgid "Login" msgstr "Nombre de Usuario" -#: /views/elements/email/text/account_verification.ctp:2 +#: View/Elements/Users/sidebar.ctp:6 +msgid "Register an account" +msgstr "Registrar nueva cuenta" + +#: View/Elements/Users/sidebar.ctp:11 +#, fuzzy +msgid "Change password" +msgstr "Cambiar contraseña" + +#: View/Emails/text/account_verification.ctp:12 msgid "Hello %s," msgstr "Hola %s," -#: /views/elements/email/text/account_verification.ctp:4 +#: View/Emails/text/account_verification.ctp:14 msgid "to validate your account, you must visit the URL below within 24 hours" msgstr "Para validar su cuenta, debe vistar el URL antes de 24 horas" -#: /views/elements/email/text/password_reset_request.ctp:2 +#: View/Emails/text/new_password.ctp:12 +msgid "Your password has been reset" +msgstr "Su contraseña ha sido reiniciada" + +#: View/Emails/text/new_password.ctp:13 +msgid "Please login using this password and change your password" +msgstr "Por favor acceda usando esta contraseña y luego cámbiela" + +#: View/Emails/text/new_password.ctp:15 +msgid "Your new password is: %s" +msgstr "Su nueva contraseña es: %s" + +#: View/Emails/text/password_reset_request.ctp:12 msgid "A request to reset your password was sent. To change your password click the link below." msgstr "Una solicitud para reiniciar la contraseña fue enviada. Para cambiarla haga click en el siguiente enlace" -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 +#: View/Users/add.ctp:13 +#: View/Users/admin_add.ctp:15 msgid "Add User" msgstr "Agregar usuario" -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 +#: View/Users/add.ctp:18 +#: View/Users/admin_add.ctp:18 +#: View/Users/admin_edit.ctp:19 +#: View/Users/admin_index.ctp:18 +#: View/Users/admin_view.ctp:15 +#: View/Users/search.ctp:18 +#: View/Users/view.ctp:15 +msgid "Username" +msgstr "Nombre de Usuario" + +#: View/Users/add.ctp:20 +#: View/Users/admin_add.ctp:20 +msgid "E-mail (used as login)" +msgstr "Correo (usado para acceder)" + +#: View/Users/add.ctp:21 +#: View/Users/admin_add.ctp:21 +msgid "Must be a valid email address" +msgstr "Debe ser una cuenta de correo válida" + +#: View/Users/add.ctp:22 +#: View/Users/admin_add.ctp:22 +msgid "An account with that email already exists" +msgstr "Una cuenta con dicho correo ya existe" + +#: View/Users/add.ctp:24 +#: View/Users/admin_add.ctp:24 +#: View/Users/login.ctp:23 +msgid "Password" +msgstr "Contraseña" + +#: View/Users/add.ctp:27 +#: View/Users/admin_add.ctp:27 +msgid "Password (confirm)" +msgstr "Contraseña (confirmación)" + +#: View/Users/add.ctp:29 +msgid "Terms of Service" +msgstr "Condiciones del Servicio" + +#: View/Users/add.ctp:31 +msgid "I have read and agreed to " +msgstr "He leído y estoy de acuerdo con" + +#: View/Users/add.ctp:32 +#: View/Users/change_password.ctp:26 +#: View/Users/edit.ctp:25 +#: View/Users/login.ctp:30 +#: View/Users/request_password_change.ctp:22 +#: View/Users/resend_verification.ctp:22 +#: View/Users/reset_password.ctp:14 +msgid "Submit" +msgstr "Enviar" + +#: View/Users/admin_add.ctp:31 +#: View/Users/admin_edit.ctp:24 +msgid "Role" +msgstr "Rol" + +#: View/Users/admin_add.ctp:34 +#: View/Users/admin_edit.ctp:27 +msgid "Is Admin" +msgstr "Es Admin" + +#: View/Users/admin_add.ctp:36 +#: View/Users/admin_edit.ctp:29 +msgid "Active" +msgstr "Activo" + +#: View/Users/admin_edit.ctp:15 +#: View/Users/edit.ctp:15 msgid "Edit User" msgstr "Editar Usuario" -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 +#: View/Users/admin_edit.ctp:21 +#: View/Users/admin_index.ctp:19 +#: View/Users/login.ctp:21 +#: View/Users/search.ctp:20 +msgid "Email" +msgstr "Correo" + +#: View/Users/admin_index.ctp:13 +#: View/Users/index.ctp:13 +#: View/Users/search.ctp:13 msgid "Users" msgstr "Usuarios" -#: /views/users/admin_index.ctp:4 +#: View/Users/admin_index.ctp:15 msgid "Filter" msgstr "Filtrar" -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" -msgstr "Nombre de Usuario" - -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 +#: View/Users/admin_index.ctp:20 +#: View/Users/search.ctp:23 msgid "Search" msgstr "Buscar" -#: /views/users/admin_view.ctp:24 -msgid "Delete User" -msgstr "Eliminar Usuario" +#: View/Users/admin_index.ctp:32 +#: View/Users/index.ctp:25 +#: View/Users/search.ctp:35 +msgid "Actions" +msgstr "Acciones" + +#: View/Users/admin_index.ctp:50;53 +msgid "Yes" +msgstr "Sí" + +#: View/Users/admin_index.ctp:50;53 +msgid "No" +msgstr "No" + +#: View/Users/admin_index.ctp:59 +#: View/Users/index.ctp:39 +#: View/Users/search.ctp:49 +msgid "View" +msgstr "Ver" + +#: View/Users/admin_index.ctp:60 +#: View/Users/search.ctp:50 +msgid "Edit" +msgstr "Editar" + +#: View/Users/admin_index.ctp:61 +#: View/Users/search.ctp:52 +msgid "Delete" +msgstr "Eliminar" + +#: View/Users/admin_index.ctp:61 +#: View/Users/search.ctp:55 +msgid "Are you sure you want to delete # %s?" +msgstr "¿Está seguro que desea eliminar # %s?" + +#: View/Users/admin_view.ctp:13 +#: View/Users/view.ctp:13 +msgid "User" +msgstr "Usuario" -#: /views/users/change_password.ctp:1 +#: View/Users/admin_view.ctp:20 +#: View/Users/view.ctp:20 +msgid "Created" +msgstr "Creado" + +#: View/Users/admin_view.ctp:25 +msgid "Modified" +msgstr "Modificado" + +#: View/Users/change_password.ctp:13 +#: View/Users/edit.ctp:22 msgid "Change your password" msgstr "Cambiar contraseña" -#: /views/users/change_password.ctp:3 +#: View/Users/change_password.ctp:14 msgid "Please enter your old password because of security reasons and then your new password twice." msgstr "Por favor introduzca su contraseña anterior por razones de seguridad y luego su nueva contraseña dos veces." -#: /views/users/change_password.ctp:8 +#: View/Users/change_password.ctp:18 msgid "Old Password" msgstr "Contraseña anterior" -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 +#: View/Users/change_password.ctp:21 +#: View/Users/reset_password.ctp:9 msgid "New Password" msgstr "Nueva contraseña" -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 +#: View/Users/change_password.ctp:24 +#: View/Users/reset_password.ctp:12 msgid "Confirm" msgstr "Confirmar" -#: /views/users/dashboard.ctp:2 +#: View/Users/dashboard.ctp:13 msgid "Welcome" msgstr "Bienvenido" -#: /views/users/dashboard.ctp:3 +#: View/Users/dashboard.ctp:14 msgid "Recent broadcasts" msgstr "Mensajes recientes" -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "Mis grupos" +#: View/Users/index.ctp:17 +#: View/Users/search.ctp:27 +msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" +msgstr "Página %page% de %pages%, mostrando %current% registros de %count% en total, empezando en %start% y terminando en %end%" + +#: View/Users/login.ctp:25 +msgid "Remember Me" +msgstr "Recordarme" + +#: View/Users/login.ctp:26 +#, fuzzy +msgid "I forgot my password" +msgstr "¿Olvidó su contraseña?" -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "Crear un nuevo grupo" +#: View/Users/request_password_change.ctp:13 +msgid "Forgot your password?" +msgstr "¿Olvidó su contraseña?" -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "Invitar a un usuario" +#: View/Users/request_password_change.ctp:14 +#: View/Users/resend_verification.ctp:14 +msgid "Please enter the email you used for registration and you'll get an email with further instructions." +msgstr "Por favor introduzca el correo que utilizó para registrarse y recibirá un correo con más instrucciones" -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "Solicitar ingreso" +#: View/Users/request_password_change.ctp:21 +#: View/Users/resend_verification.ctp:21 +msgid "Your Email" +msgstr "Su correo" -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "Mis grupos" +#: View/Users/resend_verification.ctp:13 +msgid "Resend the Email Verification" +msgstr "Reenviar el email de verificación" -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "Miembros" +#: View/Users/reset_password.ctp:2 +msgid "Reset your password" +msgstr "Reiniciar contraseña" -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "Invitar usuario" +#: View/Users/search.ctp:22 +msgid "Name" +msgstr "Nombre" -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "Gestionar alcance de mensajes" +#: Plugin/Users/Model/User.php:validation +#: for field username +msgid "Please enter a username." +msgstr "Por favor, introduzca un nombre de usuario." -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "Acceso" +#: Plugin/Users/Model/User.php:validation +#: for field username +#, fuzzy +msgid "The username must be alphanumeric." +msgstr "El nombre de usuario debe estar compuesto únicamente por letras y números, sin espacios" -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "Complementos" +#: Plugin/Users/Model/User.php:validation +#: for field username +msgid "This username is already in use." +msgstr "Este nombre de usuario ya se encuentra en uso" -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "Grupos en los que el miembro está" +#: Plugin/Users/Model/User.php:validation +#: for field username +msgid "The username must have at least 3 characters." +msgstr "El nombre de usuario debe contener al menos 3 caracteres" -#: /views/users/groups.ctp:68 -msgid "Leave group" -msgstr "Dejar grupo" +#: Plugin/Users/Model/User.php:validation +#: for field email +msgid "Please enter a valid email address." +msgstr "Por favor introduzca una dirección de correo electrónico válida." -#: /views/users/login.ctp:11 -msgid "Remember Me" -msgstr "Recordarme" +#: Plugin/Users/Model/User.php:validation +#: for field email +msgid "This email is already in use." +msgstr "Este correo ya se encuentra en uso." -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "Registro de cuenta" +#: Plugin/Users/Model/User.php:validation +#: for field password +msgid "The password must have at least 6 characters." +msgstr "La contraseña debe tener al menos 6 caracteres." -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" -msgstr "Por favor seleccione un nombre de usuario que no esté en uso" +#: Plugin/Users/Model/User.php:validation +#: for field password +msgid "Please enter a password." +msgstr "Por favor introduzca una contraseña." -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "Debe ser de al menos 3 caracteres" +#: Plugin/Users/Model/User.php:validation +#: for field temppassword +msgid "The passwords are not equal, please try again." +msgstr "Las contraseñas no coinciden, por favor inténtelo de nuevo." -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "El nombre de usuario debe contener solo letras y números" +#: Plugin/Users/Model/User.php:validation +#: for field tos +msgid "You must agree to the terms of use." +msgstr "Debe aceptar las condiciones de uso." -#: /views/users/register.ctp:13 -msgid "Please choose username" -msgstr "Por favor escoja un nombre de usuario" +#~ msgid "Invalid Detail." +#~ msgstr "Detalle no válido." -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" -msgstr "Correo (usado para acceder)" +#~ msgid "Saved" +#~ msgstr "Guardado" -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" -msgstr "Debe ser una cuenta de correo válida" +#~ msgid "%s details saved" +#~ msgstr "%s detalles guardados" -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" -msgstr "Una cuenta con dicho correo ya existe" +#~ msgid "Invalid id for Detail" +#~ msgstr "Identificador no válido para detalle" -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" -msgstr "Debe ser de al menos 5 caracteres" +#~ msgid "Detail deleted" +#~ msgstr "Detalle eliminado" -#: /views/users/register.ctp:23 -msgid "Password (confirm)" -msgstr "Contraseña (confirmación)" +#~ msgid "The Detail has been saved" +#~ msgstr "El detalle ha sido guardado" -#: /views/users/register.ctp:25 -msgid "Passwords must match" -msgstr "Las contraseñas deben coincidir" +#~ msgid "Invalid Detail" +#~ msgstr "Detalle no válido" -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " -msgstr "He leído y estoy de acuerdo con" +#~ msgid "Profile saved." +#~ msgstr "Perfil guardado" -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" -msgstr "Condiciones del Servicio" +#~ msgid "Could not save your profile." +#~ msgstr "No se pudo guardar su perfil." -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" -msgstr "Debe verificar que ha leído las Condiciones de Servicio" +#~ msgid "There url you accessed is not longer valid" +#~ msgstr "El url que intentó acceder ya no es válido" -#: /views/users/register.ctp:46 -msgid "Openid Identifier" -msgstr "Identificador Openid" +#~ msgid "" +#~ "There was an error trying to validate your e-mail address. Please check " +#~ "your e-mail for the URL you should use to verify your e-mail address." +#~ msgstr "" +#~ "Ocurrió un error tratando de validar su dirección de correo. Por favor " +#~ "verifique su correo y utilice la URL que le hemos enviado para validar su " +#~ "cuenta. Tenga en cuenta que a veces los correos pueden ser clasificados " +#~ "como correo basura (SPAM) por error, por favor revise su bandeja de " +#~ "entrada y su bandeja de SPAM." -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" -msgstr "¿Olvidó su contraseña?" +#~ msgid "Invalid date" +#~ msgstr "Fecha no válida" -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Por favor introduzca el correo que utilizó para registrarse y recibirá un correo con más instrucciones" +#~ msgid "floriank you have successfully logged out" +#~ msgstr "floriank you have successfully logged out" -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" -msgstr "Su correo" +#~ msgid "Add Detail" +#~ msgstr "Agregar detalle" -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" -msgstr "Reiniciar contraseña" +#~ msgid "List Details" +#~ msgstr "Listar detalles" + +#~ msgid "New User" +#~ msgstr "Nuevo usuario" + +#~ msgid "List Groups" +#~ msgstr "Listar grupos" + +#~ msgid "New Group" +#~ msgstr "Nuevo grupo" + +#~ msgid "Edit Detail" +#~ msgstr "Editar detalle" + +#~ msgid "Details" +#~ msgstr "Detalles" + +#~ msgid "New Detail" +#~ msgstr "Nuevo detalle" + +#~ msgid "Detail" +#~ msgstr "Detalle" + +#~ msgid "Id" +#~ msgstr "Id" + +#~ msgid "Position" +#~ msgstr "Posición" + +#~ msgid "Field" +#~ msgstr "Campo" + +#~ msgid "Value" +#~ msgstr "Valor" + +#~ msgid "Delete Detail" +#~ msgstr "Eliminar detalle" + +#~ msgid "Related Groups" +#~ msgstr "Grupos relacionado" + +#~ msgid "User Id" +#~ msgstr "Usuario Id" + +#~ msgid "Is Public" +#~ msgstr "Es Público" + +#~ msgid "Description" +#~ msgstr "Descripción" + +#~ msgid "Delete User" +#~ msgstr "Eliminar Usuario" + +#~ msgid "My Groups" +#~ msgstr "Mis grupos" + +#~ msgid "Create a new group" +#~ msgstr "Crear un nuevo grupo" + +#~ msgid "Invite a user" +#~ msgstr "Invitar a un usuario" + +#~ msgid "Requests to join" +#~ msgstr "Solicitar ingreso" + +#~ msgid "My own groups" +#~ msgstr "Mis grupos" + +#~ msgid "Members" +#~ msgstr "Miembros" + +#~ msgid "Invite user" +#~ msgstr "Invitar usuario" + +#~ msgid "Manage Broadcast Scope" +#~ msgstr "Gestionar alcance de mensajes" + +#~ msgid "Access" +#~ msgstr "Acceso" + +#~ msgid "Addons" +#~ msgstr "Complementos" + +#~ msgid "Groups im a member in" +#~ msgstr "Grupos en los que el miembro está" + +#~ msgid "Leave group" +#~ msgstr "Dejar grupo" + +#~ msgid "Account registration" +#~ msgstr "Registro de cuenta" + +#~ msgid "Please select a username that is not already in use" +#~ msgstr "Por favor seleccione un nombre de usuario que no esté en uso" + +#~ msgid "Must be at least 3 characters" +#~ msgstr "Debe ser de al menos 3 caracteres" + +#~ msgid "Username must contain numbers and letters only" +#~ msgstr "El nombre de usuario debe contener solo letras y números" + +#~ msgid "Please choose username" +#~ msgstr "Por favor escoja un nombre de usuario" + +#~ msgid "Must be at least 5 characters long" +#~ msgstr "Debe ser de al menos 5 caracteres" + +#~ msgid "Passwords must match" +#~ msgstr "Las contraseñas deben coincidir" + +#~ msgid "You must verify you have read the Terms of Service" +#~ msgstr "Debe verificar que ha leído las Condiciones de Servicio" -#: /views/users/search.ctp:1 -msgid "Search for users" -msgstr "Buscar usuarios" +#~ msgid "Openid Identifier" +#~ msgstr "Identificador Openid" +#~ msgid "Search for users" +#~ msgstr "Buscar usuarios" diff --git a/Locale/users.pot b/Locale/users.pot index aab333679..b3204a817 100644 --- a/Locale/users.pot +++ b/Locale/users.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2013-09-18 22:41+0200\n" +"POT-Creation-Date: 2013-09-18 23:20+0200\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" @@ -123,6 +123,10 @@ msgstr "" msgid "Invalid options %s" msgstr "" +#: Controller/Component/Auth/TokenAuthenticate.php:67 +msgid "You need to specify token parameter and/or header" +msgstr "" + #: Model/User.php:158;339 msgid "The passwords are not equal." msgstr "" @@ -192,6 +196,14 @@ msgstr "" msgid "testuser you have successfully logged out" msgstr "" +#: View/Elements/pagination.ctp:14 +msgid "previous" +msgstr "" + +#: View/Elements/pagination.ctp:16 +msgid "next" +msgstr "" + #: View/Elements/Users/admin_sidebar.ctp:3 #: View/Elements/Users/sidebar.ctp:9 msgid "Logout" diff --git a/View/Elements/pagination.ctp b/View/Elements/pagination.ctp index 83b720e1b..7325cfcad 100644 --- a/View/Elements/pagination.ctp +++ b/View/Elements/pagination.ctp @@ -11,8 +11,8 @@ ?>
Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled')); + echo $this->Paginator->prev('< ' . __d('users', 'previous'), array(), null, array('class' => 'prev disabled')); echo $this->Paginator->numbers(array('separator' => '')); - echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled')); + echo $this->Paginator->next(__d('users', 'next') . ' >', array(), null, array('class' => 'next disabled')); ?>
From f8c7100cc37995e4adff51f64d53be1c0a745b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 18 Sep 2013 22:51:22 +0100 Subject: [PATCH 0078/1476] adding space to format terms sentence --- Locale/spa/LC_MESSAGES/users.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Locale/spa/LC_MESSAGES/users.po b/Locale/spa/LC_MESSAGES/users.po index f78d2c3da..40898c3d6 100644 --- a/Locale/spa/LC_MESSAGES/users.po +++ b/Locale/spa/LC_MESSAGES/users.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: Users CakePHP plugin\n" "POT-Creation-Date: 2013-09-18 23:20+0200\n" -"PO-Revision-Date: 2013-09-18 22:36-0000\n" +"PO-Revision-Date: 2013-09-18 22:52-0000\n" "Last-Translator: Jorge González \n" "Language-Team: CakeDC \n" "Language: \n" @@ -321,7 +321,7 @@ msgstr "Condiciones del Servicio" #: View/Users/add.ctp:31 msgid "I have read and agreed to " -msgstr "He leído y estoy de acuerdo con" +msgstr "He leído y estoy de acuerdo con las " #: View/Users/add.ctp:32 #: View/Users/change_password.ctp:26 From f73aaf60ec45e8fa9aea7b98f8183fb85a0145e0 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 20 Sep 2013 10:39:35 -0500 Subject: [PATCH 0079/1476] Fixing import --- Model/UsersAppModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Model/UsersAppModel.php b/Model/UsersAppModel.php index bd062bada..e1260a544 100644 --- a/Model/UsersAppModel.php +++ b/Model/UsersAppModel.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -App::uses('Model', 'Model'); +App::uses('AppModel', 'Model'); /** * Users App Model From 46d6321f53093f385ab02126dc87a21f71876b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 17 Nov 2013 22:05:36 +0100 Subject: [PATCH 0080/1476] Renamed locale fre => fra, since 2.3 CakePHP uses ISO standard. --- Locale/{fre => fra}/LC_MESSAGES/users.po | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Locale/{fre => fra}/LC_MESSAGES/users.po (100%) diff --git a/Locale/fre/LC_MESSAGES/users.po b/Locale/fra/LC_MESSAGES/users.po similarity index 100% rename from Locale/fre/LC_MESSAGES/users.po rename to Locale/fra/LC_MESSAGES/users.po From 720ebb5e0591600b8052afa9fd10bf3efd62ecf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 16 Dec 2013 00:35:47 +0100 Subject: [PATCH 0081/1476] Refs https://github.com/CakeDC/users/pull/146 --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e58f83134..5971277c7 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ } ], "require": { - "composer/installers": "*" + "composer/installers": "*", + "cakedc/search": "*" } } From b6ee0adf293ccd193b08fd8a289b11a55fad2178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 16 Dec 2013 00:40:21 +0100 Subject: [PATCH 0082/1476] Refs https://github.com/CakeDC/users/issues/145, fixing the links in the sidebar when not used from the plugin --- View/Elements/Users/sidebar.ctp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/View/Elements/Users/sidebar.ctp b/View/Elements/Users/sidebar.ctp index 4dc7170a4..95671713a 100644 --- a/View/Elements/Users/sidebar.ctp +++ b/View/Elements/Users/sidebar.ctp @@ -1,18 +1,18 @@
    Session->read('Auth.User.id')) : ?> -
  • Html->link(__d('users', 'Login'), array('action' => 'login')); ?>
  • - -
  • Html->link(__d('users', 'Register an account'), array('action' => 'add')); ?>
  • - +
  • Html->link(__d('users', 'Login'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'login')); ?>
  • + +
  • Html->link(__d('users', 'Register an account'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'add')); ?>
  • + -
  • Html->link(__d('users', 'Logout'), array('action' => 'logout')); ?> -
  • Html->link(__d('users', 'My Account'), array('action' => 'edit')); ?> -
  • Html->link(__d('users', 'Change password'), array('action' => 'change_password')); ?> +
  • Html->link(__d('users', 'Logout'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'logout')); ?> +
  • Html->link(__d('users', 'My Account'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'edit')); ?> +
  • Html->link(__d('users', 'Change password'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'change_password')); ?> Session->read('Auth.User.is_admin')) : ?> -
  •  
  • -
  • Html->link(__d('users', 'List Users'), array('action'=>'index'));?>
  • - +
  •  
  • +
  • Html->link(__d('users', 'List Users'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'index'));?>
  • +
From f93ce417242ab9363e1b22a814c1f5d947ab6220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 26 Jan 2014 23:50:51 +0100 Subject: [PATCH 0083/1476] Minor improvement to the flash message that shows the username in the UsersController.php --- Controller/UsersController.php | 4 ++-- Model/User.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 89ecd9d63..52d8dc35e 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -459,7 +459,7 @@ public function login() { if ($this->here == $this->Auth->loginRedirect) { $this->Auth->loginRedirect = '/'; } - $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged in'), $this->Auth->user('username'))); + $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged in'), $this->Auth->user($this->{$this->modelClass}->displayField))); if (!empty($this->request->data)) { $data = $this->request->data[$this->modelClass]; if (empty($this->request->data[$this->modelClass]['remember_me'])) { @@ -480,7 +480,7 @@ public function login() { $this->redirect($this->Auth->redirect($data[$this->modelClass]['return_to'])); } } else { - $this->Auth->flash(__d('users', 'Invalid e-mail / password combination. Please try again')); + $this->Auth->flash(__d('users', 'Invalid e-mail / password combination. Please try again')); } } if (isset($this->request->params['named']['return_to'])) { diff --git a/Model/User.php b/Model/User.php index a713bb3cb..9cfae0e7e 100644 --- a/Model/User.php +++ b/Model/User.php @@ -308,7 +308,7 @@ public function passwordReset($postData = array()) { /** * Checks the token for a password change - * + * * @param string $token Token * @return mixed False or user data as array */ @@ -341,7 +341,7 @@ public function setUpResetPasswordValidationRules() { /** * Resets the password - * + * * @param array $postData Post data from controller * @return boolean True on success */ From 226e3a4fc4b087ec1e1d710d3be6c7914607d1d2 Mon Sep 17 00:00:00 2001 From: Guy Warner Date: Mon, 27 Jan 2014 09:49:49 -0700 Subject: [PATCH 0084/1476] Code typos in readme --- readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 5c704694b..8b74a1563 100644 --- a/readme.md +++ b/readme.md @@ -51,12 +51,13 @@ If you are using another user model than 'User' you'll have to configure it: public $components = array( 'Users.RememberMe' => array( - 'userModel' => 'AppUser'); + 'userModel' => 'AppUser') + ); And add this line ```php -$this->RememberMe->restoreLoginFromCookie() +$this->RememberMe->restoreLoginFromCookie(); ``` to your controllers beforeFilter() callack From 3caf6dbf0aff65f2cb8f66ff65eb0000b8b97813 Mon Sep 17 00:00:00 2001 From: Guy Warner Date: Mon, 27 Jan 2014 15:39:27 -0700 Subject: [PATCH 0085/1476] Fixed some linting issues. --- Controller/Component/RememberMeComponent.php | 12 ++++++------ Controller/UsersController.php | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 15735ac5f..34e36b0d0 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -131,8 +131,8 @@ public function restoreLoginFromCookie($checkLoginStatus = true) { } if ($this->cookieIsSet()) { - extract($this->settings); - $cookie = $this->Cookie->read($cookieKey); + extract($this->settings); + $cookie = $this->Cookie->read($cookieKey); $request = $this->request->data; foreach ($fields as $field) { @@ -145,10 +145,10 @@ public function restoreLoginFromCookie($checkLoginStatus = true) { if (!$result) { $this->request->data = $request; - } + } return $result; - } + } return false; } @@ -165,7 +165,7 @@ public function setCookie($data = array()) { $data = $this->request->data; if (empty($data)) { $data = $this->Auth->user(); - } + } } if (empty($data)) { @@ -205,7 +205,7 @@ public function destroyCookie() { if (isset($_COOKIE[$cookie['name']])) { $this->Cookie->name = $cookie['name']; $this->Cookie->destroy(); - } + } } /** diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 52d8dc35e..c81339d39 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -121,7 +121,9 @@ protected function _pluginDot() { /** * Wrapper for CakePlugin::loaded() * + * @throws MissingPluginException * @param string $plugin + * @param boolean $exceiption * @return boolean */ protected function _pluginLoaded($plugin, $exception = true) { @@ -268,7 +270,6 @@ public function view($slug = null) { /** * Edit * - * @param string $id User ID * @return void */ public function edit() { @@ -543,7 +544,7 @@ public function logout() { $user = $this->Auth->user(); $this->Session->destroy(); if (isset($_COOKIE[$this->Cookie->name])) { - $this->Cookie->destroy(); + $this->Cookie->destroy(); } $this->RememberMe->destroyCookie(); $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged out'), $user[$this->{$this->modelClass}->displayField])); From 4c08b475855cef77ba8844e74fd5ed9a84c7f308 Mon Sep 17 00:00:00 2001 From: Andre Cardoso Date: Tue, 28 Jan 2014 01:05:52 -0200 Subject: [PATCH 0086/1476] Changed portuguese translation path and fixed some strings As exists basically Portugal portuguese and Brazil portuguese there are some differences. The path to translation was changed from 'por' to 'pt_BR' and some strings are now with a "brazilian" feeling. The way it was is very formal and escapes from brazilian reality. --- Locale/{por => pt_BR}/LC_MESSAGES/users.po | 56 +++++++++++----------- 1 file changed, 28 insertions(+), 28 deletions(-) rename Locale/{por => pt_BR}/LC_MESSAGES/users.po (93%) diff --git a/Locale/por/LC_MESSAGES/users.po b/Locale/pt_BR/LC_MESSAGES/users.po similarity index 93% rename from Locale/por/LC_MESSAGES/users.po rename to Locale/pt_BR/LC_MESSAGES/users.po index 92397305c..eddc80325 100644 --- a/Locale/por/LC_MESSAGES/users.po +++ b/Locale/pt_BR/LC_MESSAGES/users.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: CakePHP Users Plugin\n" "POT-Creation-Date: 2010-09-15 15:48+0200\n" -"PO-Revision-Date: 2010-09-23 19:54-0300\n" +"PO-Revision-Date: 2014-01-25 14:40-0300\n" "Last-Translator: Renan Gonçalves \n" "Language-Team: CakeDC \n" "MIME-Version: 1.0\n" @@ -32,7 +32,7 @@ msgstr "Salvo" #: /controllers/details_controller.php:96 msgid "%s details saved" -msgstr "%s detalha salvo" +msgstr "%s detalhe salvo" #: /controllers/details_controller.php:113;196 msgid "Invalid id for Detail" @@ -68,7 +68,7 @@ msgstr "Usuário inválido." #: /controllers/users_controller.php:207 msgid "The User has been saved" -msgstr "O Usuário foi saldo" +msgstr "O Usuário foi salvo" #: /controllers/users_controller.php:223 msgid "User saved" @@ -90,12 +90,12 @@ msgstr "Você já está registrado e logado!" #: /controllers/users_controller.php:282 #: /tests/cases/controllers/users_controller.test.php:194 msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Sua conta foi salva. Você logo receberá um e-mail para autenticar sua conta. Uma vez validada você poderá logar." +msgstr "Sua conta foi salva. Logo você receberá um e-mail para confirmar sua conta. Uma vez validada você poderá logar." #: /controllers/users_controller.php:287 #: /tests/cases/controllers/users_controller.test.php:205 msgid "Your account could not be created. Please, try again." -msgstr "Sua conta não pode ser criada. Por favor, tente novamente." +msgstr "Sua conta não pôde ser criada. Por favor, tente novamente." #: /controllers/users_controller.php:309 msgid "%s you have successfully logged in" @@ -119,11 +119,11 @@ msgstr "Sua senha foi resetada" #: /controllers/users_controller.php:435 msgid "Please login using this password and change your password" -msgstr "Por favor faça o login usando essa senha e então mude-a" +msgstr "Por favor faça o login usando esta senha e então mude-a o mais breve possível" #: /controllers/users_controller.php:438 msgid "Your password was sent to your registered email account" -msgstr "Sua senha foi enviado para seu e-mail registrado em sua conta" +msgstr "Sua senha foi enviada para seu e-mail registrado em sua conta" #: /controllers/users_controller.php:444 #: /tests/cases/controllers/users_controller.test.php:219 @@ -157,19 +157,19 @@ msgstr "Você deverá receber um email com mais instruções em breve" #: /controllers/users_controller.php:571 msgid "No user was found with that email." -msgstr "Nenhum usuário com esse e-mail foi encontrado." +msgstr "Não foi localizado nenhum usuário com esse e-mail." #: /controllers/users_controller.php:588 msgid "Invalid password reset token, try again." -msgstr "Chave para redefinição de senha inválida, tente novamente." +msgstr "Token para redefinição de senha inválido, tente novamente." #: /controllers/users_controller.php:594 msgid "Password changed, you can now login with your new password." -msgstr "Senha alterada, você pode agora logar com sua nova senha." +msgstr "Senha alterada, você pode logar agora com sua nova senha." #: /models/user.php:102 msgid "Please enter a username" -msgstr "Por favor entre o nome de usuário" +msgstr "Por favor informe o nome de usuário" #: /models/user.php:105 msgid "The username must be alphanumeric" @@ -185,7 +185,7 @@ msgstr "O nome de usuário deve ter no mínimo 3 caracteres." #: /models/user.php:116 msgid "Please enter a valid email address." -msgstr "Por favor entre um endereço de e-mail válido." +msgstr "Por favor informe um endereço de e-mail válido." #: /models/user.php:119 msgid "This email is already in use." @@ -197,11 +197,11 @@ msgstr "A senha deve ter no mínimo 8 caracteres." #: /models/user.php:126 msgid "Please enter a password." -msgstr "Por favor entre a senha." +msgstr "Por favor informe a sua senha." #: /models/user.php:129 msgid "The passwords are not equal, please try again." -msgstr "As senhas devem ser iguais, por favor tente novamente." +msgstr "As senhas devem ser idênticas, por favor verifique." #: /models/user.php:132 msgid "You must agree to the terms of use." @@ -237,7 +237,7 @@ msgstr "O usuário não existe." #: /models/user.php:505 msgid "Please enter your email address." -msgstr "Por favor entre seu endereço de e-mail." +msgstr "Por favor informe seu endereço de e-mail." #: /models/user.php:515 msgid "The email address does not exist in the system" @@ -261,11 +261,11 @@ msgstr "Combinação de e-mail/senha inválida. Por favor tente novamente." #: /tests/cases/controllers/users_controller.test.php:168 msgid "testuser you have successfully logged in" -msgstr "" +msgstr "Usuário de teste você logou corretamente" #: /tests/cases/controllers/users_controller.test.php:237 msgid "floriank you have successfully logged out" -msgstr "" +msgstr "Você realizou o logout com sucesso" #: /views/details/add.ctp:4 #: /views/details/admin_add.ctp:4 @@ -359,7 +359,7 @@ msgstr "Detalhes" #: /views/details/admin_index.ctp:6 #: /views/users/index.ctp:6 msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "Página %page% de %pages%, mostrando %current% resultados de um total de %count%, começando em %start%, terminando em %end%" +msgstr "Página %page% de %pages%, exibindo %current% resultados de um total de %count%, iniciando em %start%, terminando em %end%" #: /views/details/admin_index.ctp:18 #: /views/details/admin_view.ctp:65 @@ -568,7 +568,7 @@ msgstr "Por favor digite sua senha antiga por razões de segurança e depois sua #: /views/users/change_password.ctp:8 msgid "Old Password" -msgstr "Antiga senha" +msgstr "Senha antiga" #: /views/users/change_password.ctp:11 #: /views/users/reset_password.ctp:9 @@ -582,7 +582,7 @@ msgstr "Confirmar" #: /views/users/dashboard.ctp:2 msgid "Welcome" -msgstr "Bem-vindo" +msgstr "Bem-vindo(a)" #: /views/users/dashboard.ctp:3 msgid "Recent broadcasts" @@ -602,7 +602,7 @@ msgstr "Convide um usuário" #: /views/users/groups.ctp:7 msgid "Requests to join" -msgstr "Requisite para participar" +msgstr "Convites para participar" #: /views/users/groups.ctp:10 msgid "My own groups" @@ -638,7 +638,7 @@ msgstr "Deixar grupo" #: /views/users/login.ctp:11 msgid "Remember Me" -msgstr "Lembre-me" +msgstr "Lembrar-me" #: /views/users/register.ctp:2 msgid "Account registration" @@ -666,7 +666,7 @@ msgstr "E-mail (usado para logar)" #: /views/users/register.ctp:16 msgid "Must be a valid email address" -msgstr "Deve ser um endereço de e-mail válido" +msgstr "O e-mail deve ser um endereço válido" #: /views/users/register.ctp:17 msgid "An account with that email already exists" @@ -678,15 +678,15 @@ msgstr "Deve ter pelo menos 5 caracteres" #: /views/users/register.ctp:23 msgid "Password (confirm)" -msgstr "Senha (confirmação)" +msgstr "Confirme sua senha" #: /views/users/register.ctp:25 msgid "Passwords must match" -msgstr "As senhas devem ser iguais" +msgstr "As senhas devem ser idênticas" #: /views/users/register.ctp:29;85 msgid "I have read and agreed to " -msgstr "Eu li e aceito em" +msgstr "Eu li e concordo com " #: /views/users/register.ctp:29;85 msgid "Terms of Service" @@ -694,7 +694,7 @@ msgstr "Termos de Serviço" #: /views/users/register.ctp:30;86 msgid "You must verify you have read the Terms of Service" -msgstr "Você deve verificar se você leu os Termos de Serviços" +msgstr "Você deve verificar se leu os Termos de Serviços" #: /views/users/register.ctp:46 msgid "Openid Identifier" @@ -719,4 +719,4 @@ msgstr "Redefinir sua senha" #: /views/users/search.ctp:1 msgid "Search for users" msgstr "Procurar por usuários" - + From 7e273f1999e59d149b8bc471413fe097a6c0fc60 Mon Sep 17 00:00:00 2001 From: Guy Warner Date: Wed, 29 Jan 2014 08:21:11 -0700 Subject: [PATCH 0087/1476] File linting and function docs --- .../Component/Auth/TokenAuthenticate.php | 2 + Model/User.php | 5 + .../Component/RememberMeComponentTest.php | 22 ++-- Test/Case/Controller/UsersControllerTest.php | 70 +++++------ Test/Case/Model/UserTest.php | 12 +- Test/Fixture/UserFixture.php | 118 +++++++++--------- View/Users/admin_index.ctp | 4 +- View/Users/index.ctp | 4 +- View/Users/search.ctp | 4 +- View/Users/view.ctp | 12 +- 10 files changed, 123 insertions(+), 130 deletions(-) diff --git a/Controller/Component/Auth/TokenAuthenticate.php b/Controller/Component/Auth/TokenAuthenticate.php index b837cb175..eaadeaefa 100644 --- a/Controller/Component/Auth/TokenAuthenticate.php +++ b/Controller/Component/Auth/TokenAuthenticate.php @@ -60,6 +60,7 @@ class TokenAuthenticate extends BaseAuthenticate { * * @param ComponentCollection $collection The Component collection used on this request. * @param array $settings Array of settings to use. + * @throws CakeException */ public function __construct(ComponentCollection $collection, $settings) { parent::__construct($collection, $settings); @@ -69,6 +70,7 @@ public function __construct(ComponentCollection $collection, $settings) { } /** + * Authenticate user * * @param CakeRequest $request The request object * @param CakeResponse $response response object. diff --git a/Model/User.php b/Model/User.php index 9cfae0e7e..f26d8b83c 100644 --- a/Model/User.php +++ b/Model/User.php @@ -845,6 +845,11 @@ public function edit($userId = null, $postData = null) { * Gets the user data that needs to be edited * * Override this method and inject the conditions you need + * + * @var mixed $userId + * @var array $options + * @return array $user + * @throws NotFoundException */ public function getUserForEditing($userId = null, $options = array()) { $defaults = array( diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php index 667a8e5a2..492459479 100644 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -41,7 +41,7 @@ class RememberMeComponentTest extends CakeTestCase { /** * User data * @var array - */ + */ public $usersData = array( 'test' => array( 'email' => 'test@cakedc.com', @@ -102,9 +102,9 @@ public function testRestoreLoginFromCookie() { $this->RememberMe->Auth->expects($this->once()) ->method('login') ->will($this->returnValue(true)); - + $this->__setPostData(array('User' => $this->usersData['test'])); - + $this->RememberMe->restoreLoginFromCookie(); // even if we post "test" user, we have a remember me cookie set and will priorize the cookie over the post @@ -126,21 +126,17 @@ public function testRestoreLoginFromCookieIncorrectLogin() { ->method('read') ->with($this->equalTo('rememberMe')) ->will($this->returnValue($this->usersData['admin'])); - // admin will not login $this->RememberMe->Auth->expects($this->once()) ->method('login') ->will($this->returnValue(false)); - // post has "test" data $this->__setPostData(array('User' => $this->usersData['test'])); - $this->RememberMe->restoreLoginFromCookie(); - $this->assertEqual($this->RememberMe->request->data, array( 'User' => $this->usersData['test'])); } - + /** * testDestroyCookie * @@ -155,10 +151,12 @@ public function testDestroyCookie() { /** * Set post data to the test controller - * @param type $data - */ + * + * @var array $data + * @return void + */ private function __setPostData($data = array()) { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->RememberMe->request->data = array_merge($data); - } -} \ No newline at end of file + } +} diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index efd24bd3b..cebbb85da 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -67,10 +67,10 @@ public function beforeFilter() { public function setCookie($options = array()) { parent::_setCookie($options); } - + /** * Public intefface to _getMailInstance - */ + */ public function getMailInstance() { return parent::_getMailInstance(); } @@ -124,7 +124,7 @@ protected function _getMailInstance() { return $this->CakeEmail; } - } +} /** * Email configuration override for testing @@ -141,8 +141,7 @@ class EmailConfig { 'from' => 'another@example.com', ); } - - + class UsersControllerTestCase extends CakeTestCase { /** @@ -208,23 +207,23 @@ public function setUp() { $this->Users->CakeEmail = $this->getMock('CakeEmail'); $this->Users->CakeEmail->expects($this->any()) - ->method('to') - ->will($this->returnSelf()); + ->method('to') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('from') - ->will($this->returnSelf()); + ->method('from') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('subject') - ->will($this->returnSelf()); + ->method('subject') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('template') - ->will($this->returnSelf()); + ->method('template') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('viewVars') - ->will($this->returnSelf()); + ->method('viewVars') + ->will($this->returnSelf()); $this->Users->CakeEmail->expects($this->any()) - ->method('emailFormat') - ->will($this->returnSelf()); + ->method('emailFormat') + ->will($this->returnSelf()); $this->Users->Components->disable('Security'); } @@ -245,9 +244,9 @@ public function testUsersControllerInstance() { */ public function testUserLogin() { $this->Users->request->params['action'] = 'login'; - $this->__setPost(array('User' => $this->usersData['admin'])); + $this->__setPost(array('User' => $this->usersData['admin'])); $this->Users->request->url = '/users/users/login'; - + $this->Collection = $this->getMock('ComponentCollection'); $this->Users->Auth = $this->getMock('AuthComponent', array('login', 'user', 'redirect'), array($this->Collection)); $this->Users->Auth->expects($this->once()) @@ -280,16 +279,17 @@ public function testUserLogin() { $this->Users->login(); $this->assertEqual(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); } - + /** * We should not see any flash message if we GET the login action - */ + * + * @return void + */ public function testUserLoginGet() { // test with the login action $this->Users->request->url = '/users/users/login'; $this->Users->request->params['action'] = 'login'; $this->__setGet(); - $this->Users->login(); $this->Collection = $this->getMock('ComponentCollection'); $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); @@ -305,7 +305,6 @@ public function testUserLoginGet() { public function testFailedUserLogin() { $this->Users->request->params['action'] = 'login'; $this->__setPost(array('User' => $this->usersData['invalidUser'])); - $this->Collection = $this->getMock('ComponentCollection'); $this->Users->Auth = $this->getMock('AuthComponent', array('flash', 'login'), array($this->Collection)); $this->Users->Auth->expects($this->once()) @@ -320,11 +319,11 @@ public function testFailedUserLogin() { /** * Test user registration * + * @return void */ public function testAdd() { $this->Users->CakeEmail->expects($this->at(0)) ->method('send'); - $_SERVER['HTTP_HOST'] = 'test.com'; $this->Users->params['action'] = 'add'; $this->__setPost(array( @@ -340,9 +339,7 @@ public function testAdd() { $this->Users->Session->expects($this->once()) ->method('setFlash') ->with(__d('users', 'Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login.')); - $this->Users->add(); - $this->__setPost(array( 'User' => array( 'username' => 'newUser', @@ -381,7 +378,7 @@ public function testVerify() { ->method('setFlash') ->with(__d('users', 'Invalid token, please check the email you were sent, and retry the verification link.')); - $this->Users->verify('email', 'invalid-token');; + $this->Users->verify('email', 'invalid-token'); } /** @@ -421,7 +418,7 @@ public function testLogout() { */ public function testIndex() { $this->Users->passedArgs = array(); - $this->Users->index(); + $this->Users->index(); $this->assertTrue(isset($this->Users->viewVars['users'])); } @@ -431,7 +428,7 @@ public function testIndex() { * @return void */ public function testView() { - $this->Users->view('adminuser'); + $this->Users->view('adminuser'); $this->assertTrue(isset($this->Users->viewVars['user'])); $this->Users->view('INVALID-SLUG'); @@ -471,7 +468,6 @@ public function testChangePassword() { public function testResetPassword() { $this->Users->CakeEmail->expects($this->at(0)) ->method('send'); - $_SERVER['HTTP_HOST'] = 'test.com'; $this->Users->User->id = '1'; $this->Users->User->saveField('email_token_expires', date('Y-m-d H:i:s', strtotime('+1 year'))); @@ -480,8 +476,6 @@ public function testResetPassword() { 'email' => 'adminuser@cakedc.com')); $this->Users->reset_password(); $this->assertEqual($this->Users->redirectUrl, array('action' => 'login')); - - $this->Users->data = array( 'User' => array( 'new_password' => 'newpassword', @@ -501,7 +495,7 @@ public function testAdminIndex() { 'named' => array( 'search' => 'adminuser')); $this->Users->passedArgs = array(); - $this->Users->admin_index(); + $this->Users->admin_index(); $this->assertTrue(isset($this->Users->viewVars['users'])); } @@ -511,7 +505,7 @@ public function testAdminIndex() { * @return void */ public function testAdminView() { - $this->Users->admin_view('1'); + $this->Users->admin_view('1'); $this->assertTrue(isset($this->Users->viewVars['user'])); } @@ -526,7 +520,6 @@ public function testAdminDelete() { $this->Users->admin_delete('1'); $this->assertEqual($this->Users->redirectUrl, array('action' => 'index')); $this->assertFalse($this->Users->User->exists(true)); - $this->Users->admin_delete('INVALID-ID'); $this->assertEqual($this->Users->redirectUrl, array('action' => 'index')); } @@ -543,7 +536,6 @@ public function testSetCookie() { 'email' => 'testuser@cakedc.com', 'username' => 'test', 'password' => 'testtest'))); - $this->Collection = $this->getMock('ComponentCollection'); $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); $this->Users->RememberMe->expects($this->once()) @@ -551,10 +543,8 @@ public function testSetCookie() { ->with(array('name' => 'userTestCookie')); $this->Users->RememberMe->expects($this->once()) ->method('setCookie'); - $this->Users->setCookie(array( 'name' => 'userTestCookie')); - $this->assertEqual($this->Users->RememberMe->settings['cookieKey'], 'rememberMe'); } @@ -566,11 +556,9 @@ public function testSetCookie() { public function testGetMailInstance() { $defaultConfig = $this->Users->getMailInstance()->config(); $this->assertEqual($defaultConfig['from'], 'default@example.com'); - Configure::write('Users.emailConfig', 'another'); $anotherConfig = $this->Users->getMailInstance()->config(); $this->assertEqual($anotherConfig['from'], 'another@example.com'); - $this->setExpectedException('ConfigureException'); Configure::write('Users.emailConfig', 'doesnotexist'); $anotherConfig = $this->Users->getMailInstance()->config(); @@ -579,6 +567,7 @@ public function testGetMailInstance() { /** * Test * + * @var array $data * @return void */ private function __setPost($data = array()) { @@ -598,6 +587,7 @@ private function __setGet() { /** * Test * + * @var string $method unused variable * @return void */ public function endTest($method) { diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index 70716c4ea..82ce49578 100644 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -58,11 +58,11 @@ public function setUp() { public function tearDown() { parent::tearDown(); unset($this->User); - ClassRegistry::flush(); + ClassRegistry::flush(); } /** - * + * Test User Instance * * @return void */ @@ -105,7 +105,7 @@ public function testConfirmEmail() { * * @return void */ - function testGenerateToken() { + public function testGenerateToken() { $result = $this->User->generateToken(); $this->assertInternalType('string', $result); } @@ -115,7 +115,7 @@ function testGenerateToken() { * * @return void */ - function testValidateToken() { + public function testValidateToken() { $result = $this->User->validateToken('no valid token'); $this->assertFalse($result); @@ -425,15 +425,13 @@ public function testEdit() { $userId = '1'; $data = $this->User->read(null, $userId); $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; - $result = $this->User->edit(1, $data); $this->assertTrue($result); - $result = $this->User->read(null, 1); $this->assertEqual($result['User']['username'], $data['User']['username']); $this->assertEqual($result['User']['email'], $data['User']['email']); } - + /** * testEditException * diff --git a/Test/Fixture/UserFixture.php b/Test/Fixture/UserFixture.php index bd671d2e2..7c7a35185 100644 --- a/Test/Fixture/UserFixture.php +++ b/Test/Fixture/UserFixture.php @@ -37,23 +37,23 @@ class UserFixture extends CakeTestFixture { * @var array */ public $fields = array( - 'id' => array('type'=>'string', 'null' => false, 'length' => 36, 'key' => 'primary'), - 'username' => array('type'=>'string', 'null' => false, 'default' => NULL), - 'slug' => array('type'=>'string', 'null' => false, 'default' => NULL), - 'password' => array('type'=>'string', 'null' => true, 'default' => NULL, 'length' => 128), - 'password_token' => array('type'=>'string', 'null' => true, 'default' => NULL, 'length' => 128), - 'email' => array('type'=>'string', 'null' => true, 'default' => NULL), - 'email_verified' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'email_token' => array('type'=>'string', 'null' => true, 'default' => NULL), - 'email_token_expires' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'tos' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'active' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'last_action' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'last_login' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'is_admin' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'role' => array('type'=>'string', 'null' => true, 'default' => NULL), - 'created' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'modified' => array('type'=>'datetime', 'null' => true, 'default' => NULL), + 'id' => array('type' => 'string', 'null' => false, 'length' => 36, 'key' => 'primary'), + 'username' => array('type' => 'string', 'null' => false, 'default' => null), + 'slug' => array('type' => 'string', 'null' => false, 'default' => null), + 'password' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), + 'password_token' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), + 'email' => array('type' => 'string', 'null' => true, 'default' => null), + 'email_verified' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'email_token' => array('type' => 'string', 'null' => true, 'default' => null), + 'email_token_expires' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'tos' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'active' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'last_action' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'last_login' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'is_admin' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'role' => array('type' => 'string', 'null' => true, 'default' => null), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1)) ); @@ -65,118 +65,118 @@ class UserFixture extends CakeTestFixture { */ public $records = array( array( - 'id' => '1', - 'username' => 'adminuser', + 'id' => '1', + 'username' => 'adminuser', 'slug' => 'adminuser', - 'password' => 'test', // test - 'password_token' => 'testtoken', + 'password' => 'test', // test + 'password_token' => 'testtoken', 'email' => 'adminuser@cakedc.com', 'email_verified' => 1, 'email_token' => 'testtoken', 'email_token_expires' => '2008-03-25 02:45:46', 'tos' => 1, 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', + 'last_action' => '2008-03-25 02:45:46', 'last_login' => '2008-03-25 02:45:46', 'is_admin' => 1, - 'role' => 'admin', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' + 'role' => 'admin', + 'created' => '2008-03-25 02:45:46', + 'modified' => '2008-03-25 02:45:46' ), array( - 'id' => '47ea303a-3cyc-k251-b313-4811c0a800bf', - 'username' => 'testuser', + 'id' => '47ea303a-3cyc-k251-b313-4811c0a800bf', + 'username' => 'testuser', 'slug' => 'testuser', - 'password' => 'secretkey', // secretkey - 'password_token' => '', + 'password' => 'secretkey', // secretkey + 'password_token' => '', 'email' => 'testuser@cakedc.com', 'email_verified' => '1', 'email_token' => '', 'email_token_expires' => '2008-03-25 02:45:46', 'tos' => 1, 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', + 'last_action' => '2008-03-25 02:45:46', 'last_login' => '2008-03-25 02:45:46', 'is_admin' => 0, - 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' + 'role' => 'user', + 'created' => '2008-03-25 02:45:46', + 'modified' => '2008-03-25 02:45:46' ), array( - 'id' => '37ea303a-3bdc-4251-b315-1316c0b300fa', - 'username' => 'user1', + 'id' => '37ea303a-3bdc-4251-b315-1316c0b300fa', + 'username' => 'user1', 'slug' => 'user1', - 'password' => 'newpass', // newpass - 'password_token' => '', + 'password' => 'newpass', // newpass + 'password_token' => '', 'email' => 'testuser1@testuser.com', 'email_verified' => 0, 'email_token' => 'testtoken2', 'email_token_expires' => '2008-03-28 02:45:46', 'tos' => 0, 'active' => 0, - 'last_action' => '2008-03-25 02:45:46', + 'last_action' => '2008-03-25 02:45:46', 'last_login' => '2008-03-25 02:45:46', 'is_admin' => 0, - 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' + 'role' => 'user', + 'created' => '2008-03-25 02:45:46', + 'modified' => '2008-03-25 02:45:46' ), array( 'id' => '495e36a2-1f00-46b9-8247-58a367265f11', - 'username' => 'oidtest', + 'username' => 'oidtest', 'slug' => 'oistest', - 'password' => 'newpass', // newpass - 'password_token' => '', + 'password' => 'newpass', // newpass + 'password_token' => '', 'email' => 'oidtest@testuser.com', 'email_verified' => 0, 'email_token' => 'testtoken2', 'email_token_expires' => '2008-03-28 02:45:46', 'tos' => 0, 'active' => 0, - 'last_action' => '2008-03-25 02:45:46', + 'last_action' => '2008-03-25 02:45:46', 'last_login' => '2008-03-25 02:45:46', 'is_admin' => 0, 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' + 'created' => '2008-03-25 02:45:46', + 'modified' => '2008-03-25 02:45:46' ), array( 'id' => '315e36a2-1fxj-46b9-8247-58a367265f11', - 'username' => 'oidtest2', + 'username' => 'oidtest2', 'slug' => 'oistest', - 'password' => 'newpass', // newpass - 'password_token' => '', + 'password' => 'newpass', // newpass + 'password_token' => '', 'email' => 'oidtest2@testuser.com', 'email_verified' => 0, 'email_token' => 'testtoken2', 'email_token_expires' => '2008-03-28 02:45:46', 'tos' => 1, 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', + 'last_action' => '2008-03-25 02:45:46', 'last_login' => '2008-03-25 02:45:46', 'is_admin' => 0, 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' + 'created' => '2008-03-25 02:45:46', + 'modified' => '2008-03-25 02:45:46' ), array( 'id' => '515e36a2-5fjj-46b9-8247-584367265f11', - 'username' => 'resetuser', + 'username' => 'resetuser', 'slug' => 'resetuser', - 'password' => 'newpass', // newpass - 'password_token' => 'testtoken', + 'password' => 'newpass', // newpass + 'password_token' => 'testtoken', 'email' => 'resetuser@testuser.com', 'email_verified' => 1, 'email_token' => 'testtoken', 'email_token_expires' => '2008-03-28 02:45:46', 'tos' => 1, 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', + 'last_action' => '2008-03-25 02:45:46', 'last_login' => '2008-03-25 02:45:46', 'is_admin' => 0, 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' + 'created' => '2008-03-25 02:45:46', + 'modified' => '2008-03-25 02:45:46' ) ); diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index 28a30006d..30ef0e74e 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -35,9 +35,9 @@ $i = 0; foreach ($users as $user): $class = null; - if ($i++ % 2 == 0) { + if ($i++ % 2 == 0) : $class = ' class="altrow"'; - } + endif; ?> > diff --git a/View/Users/index.ctp b/View/Users/index.ctp index 77363618c..ee04d2ae9 100644 --- a/View/Users/index.ctp +++ b/View/Users/index.ctp @@ -28,9 +28,9 @@ $i = 0; foreach ($users as $user): $class = null; - if ($i++ % 2 == 0) { + if ($i++ % 2 == 0) : $class = ' class="altrow"'; - } + endif; ?> > Html->link($user[$model]['username'], array('action' => 'view', $user[$model]['id'])); ?> diff --git a/View/Users/search.ctp b/View/Users/search.ctp index 862945fad..552d88f9e 100644 --- a/View/Users/search.ctp +++ b/View/Users/search.ctp @@ -38,9 +38,9 @@ $i = 0; foreach ($users as $user): $class = null; - if ($i++ % 2 == 0) { + if ($i++ % 2 == 0) : $class = ' class="altrow"'; - } + endif; ?> > diff --git a/View/Users/view.ctp b/View/Users/view.ctp index d2f51d6ba..85f92d86c 100644 --- a/View/Users/view.ctp +++ b/View/Users/view.ctp @@ -23,14 +23,14 @@   $details) { - foreach ($details as $field => $value) { + if (!empty($user['UserDetail'])) : + foreach ($user['UserDetail'] as $section => $details) : + foreach ($details as $field => $value) : echo '
' . $section . ' - ' . $field . '
'; echo '
' . $value . '
'; - } - } - } + endforeach; + endforeach; + endif; ?> From eea58c128c1a7a3235a316d7ad441d04b0983606 Mon Sep 17 00:00:00 2001 From: Andre Cardoso Date: Thu, 6 Feb 2014 22:41:41 -0200 Subject: [PATCH 0088/1476] Added missing dependency (Utils Plugin) --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5971277c7..23e79f73e 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ ], "require": { "composer/installers": "*", - "cakedc/search": "*" + "cakedc/search": "*", + "cakedc/utils": "*" } } From b63001b6bc725b711bbc54cd02cc7fd0d4c5b414 Mon Sep 17 00:00:00 2001 From: Zachary Wilson Date: Fri, 14 Feb 2014 14:30:17 -0600 Subject: [PATCH 0089/1476] Redundant Cookie::destroy() An identical call to Cookie destroy is called in the subsequent call RememberMe::destroyCookie() --- Controller/UsersController.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index c81339d39..d847da8a3 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -543,9 +543,6 @@ public function search() { public function logout() { $user = $this->Auth->user(); $this->Session->destroy(); - if (isset($_COOKIE[$this->Cookie->name])) { - $this->Cookie->destroy(); - } $this->RememberMe->destroyCookie(); $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged out'), $user[$this->{$this->modelClass}->displayField])); $this->redirect($this->Auth->logout()); From f53b19cb5366af5a9492c32a5cabe18a10f15021 Mon Sep 17 00:00:00 2001 From: Zachary Wilson Date: Wed, 26 Feb 2014 20:00:05 -0600 Subject: [PATCH 0090/1476] User password edit / unit tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Users could not properly update their password using the User::edit method. The User::resetPassword also had validation commented out, which caused unit tests to fail and thus password resets didn’t validate properly. First off, there was a unit test for a method that no longer existed. Also updated a few exception tests that were incorrect. Added tests for user password edits. --- Model/User.php | 23 ++++++++----- Test/Case/Model/UserTest.php | 67 ++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 34 deletions(-) mode change 100644 => 100755 Model/User.php mode change 100644 => 100755 Test/Case/Model/UserTest.php diff --git a/Model/User.php b/Model/User.php old mode 100644 new mode 100755 index f26d8b83c..e24fb0e18 --- a/Model/User.php +++ b/Model/User.php @@ -64,7 +64,7 @@ class User extends UsersAppModel { public $emailTokenExpirationTime = 86400; /** - * Validation domain for translations + * Validation domain for translations * * @var string */ @@ -348,8 +348,8 @@ public function setUpResetPasswordValidationRules() { public function resetPassword($postData = array()) { $result = false; - //$tmp = $this->validate; - //$this->validate = $this->setUpResetPasswordValidationRules(); + $tmp = $this->validate; + $this->validate = $this->setUpResetPasswordValidationRules(); $this->set($postData); if ($this->validates()) { @@ -360,7 +360,7 @@ public function resetPassword($postData = array()) { 'callbacks' => false)); } - //$this->validate = $tmp; + $this->validate = $tmp; return $result; } @@ -829,12 +829,17 @@ public function edit($userId = null, $postData = null) { throw new NotFoundException(__d('users', 'Invalid User')); } - if (!empty($postData)) { + if(!empty($postData)) { $this->set($postData); - $result = $this->save(null, true); - if ($result) { - $this->data = $result; - return true; + if ($this->validates()) { + if(isset($this->data[$this->alias]['password'])) { + $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['password'], 'sha1', true); + } + $result = $this->save(null, false); + if ($result) { + $this->data = $result; + return true; + } } else { return $postData; } diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php old mode 100644 new mode 100755 index 82ce49578..866eb027f --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -1,4 +1,4 @@ -User->generateToken(); $this->assertInternalType('string', $result); } -/** - * testValidateToken - * - * @return void - */ - public function testValidateToken() { - $result = $this->User->validateToken('no valid token'); - $this->assertFalse($result); - - $now = strtotime('2008-03-25 02:48:46'); - $result = $this->User->validateToken('testtoken2', false, $now); - $this->assertInternalType('array', $result); - - $now = strtotime('2008-03-29 02:48:46'); - $result = $this->User->validateToken('testtoken2', false, $now); - $this->assertFalse($result); - } - /** * testUpdateLastActivity * @@ -145,6 +127,7 @@ public function testUpdateLastActivity() { $this->assertFalse($this->User->updateLastActivity('invalid-id!')); } + /** * testResetPassword * @@ -236,7 +219,7 @@ public function testView() { $result = $this->User->view('adminuser'); $this->assertTrue(is_array($result) && !empty($result)); - $this->expectException('OutOfBoundsException'); + $this->expectException('NotFoundException'); $result = $this->User->view('non-existing-user-slug'); } @@ -346,7 +329,7 @@ public function testCompareFields() { } /** - * Test resending of the email authentication + * Test resending of the email authentication * * @return void */ @@ -373,7 +356,7 @@ public function testResendVerification() { } /** - * Test resending of the email authentication + * Test resending of the email authentication * * @return void */ @@ -425,11 +408,45 @@ public function testEdit() { $userId = '1'; $data = $this->User->read(null, $userId); $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; + $result = $this->User->edit(1, $data); $this->assertTrue($result); + $result = $this->User->read(null, 1); $this->assertEqual($result['User']['username'], $data['User']['username']); $this->assertEqual($result['User']['email'], $data['User']['email']); + + $result = $this->User->edit(1); + $this->assertNull($result); + } + +/** + * testEditPassword + * + * @return void + **/ + public function testEditPassword() { + $userId = '1'; + $data = $this->User->read(null, $userId); + $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; + $data['User']['password'] = 'anotherNewPassword'; + $data['User']['temppassword'] = 'anotherNewPassword'; + + $result = $this->User->edit(1, $data); + + $hashPassword = $this->User->hash($data['User']['password'], 'sha1', true); + $this->assertTrue($result); + $this->assertEqual($this->User->data['User']['password'], $hashPassword); + + $data2['User']['email'] = 'anotherEmail@anotheremail.com'; + $data2['User']['password'] = 'anotherNewPassword'; + $data2['User']['temppassword'] = 'differentPassword'; + + $result = $this->User->edit(1, $data2); + $hashPassword = $this->User->hash($data2['User']['password'], 'sha1', true); + + $this->assertNull($result); + $this->assertNotEqual($data, $data2); } /** @@ -438,7 +455,7 @@ public function testEdit() { * @return void */ public function testEditException() { - $this->setExpectedException('OutOfBoundsException'); + $this->setExpectedException('NotFoundException'); $userId = '1'; $data = $this->User->read(null, $userId); $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; From c62aa198ace9428da99e888ffb72de2245c67866 Mon Sep 17 00:00:00 2001 From: Zach Wilson Date: Mon, 3 Mar 2014 10:05:33 -0700 Subject: [PATCH 0091/1476] Formatting fixes Cleaned up whitespace / syntax --- Model/User.php | 2 +- Test/Case/Model/UserTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Model/User.php b/Model/User.php index e24fb0e18..300157356 100755 --- a/Model/User.php +++ b/Model/User.php @@ -829,7 +829,7 @@ public function edit($userId = null, $postData = null) { throw new NotFoundException(__d('users', 'Invalid User')); } - if(!empty($postData)) { + if (!empty($postData)) { $this->set($postData); if ($this->validates()) { if(isset($this->data[$this->alias]['password'])) { diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index 866eb027f..5e2a4d36e 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -62,7 +62,7 @@ public function tearDown() { } /** - * + * Test User Instance * * @return void */ @@ -105,7 +105,7 @@ public function testConfirmEmail() { * * @return void */ - function testGenerateToken() { + public function testGenerateToken() { $result = $this->User->generateToken(); $this->assertInternalType('string', $result); } From c07e7c6ced57fbcba2a3a6b93ac7058e309c70dc Mon Sep 17 00:00:00 2001 From: Stone Lasley Date: Mon, 3 Mar 2014 14:53:24 -0700 Subject: [PATCH 0092/1476] updated deprecated assertEqual --- .../Component/RememberMeComponentTest.php | 4 +-- Test/Case/Controller/UsersControllerTest.php | 22 ++++++++-------- Test/Case/Model/UserTest.php | 26 +++++++++---------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php index 492459479..daf0e63e1 100644 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -109,7 +109,7 @@ public function testRestoreLoginFromCookie() { // even if we post "test" user, we have a remember me cookie set and will priorize the cookie over the post // NOTE we check if the user is logged in in the startup method of the Component - $this->assertEqual($this->RememberMe->request->data, array( + $this->assertEquals($this->RememberMe->request->data, array( 'User' => $this->usersData['admin'])); } @@ -133,7 +133,7 @@ public function testRestoreLoginFromCookieIncorrectLogin() { // post has "test" data $this->__setPostData(array('User' => $this->usersData['test'])); $this->RememberMe->restoreLoginFromCookie(); - $this->assertEqual($this->RememberMe->request->data, array( + $this->assertEquals($this->RememberMe->request->data, array( 'User' => $this->usersData['test'])); } diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index cebbb85da..e7561011b 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -277,7 +277,7 @@ public function testUserLogin() { ->method('destroyCookie'); $this->Users->login(); - $this->assertEqual(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); + $this->assertEquals(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); } /** @@ -408,7 +408,7 @@ public function testLogout() { ->method('destroyCookie'); $this->Users->logout(); - $this->assertEqual($this->Users->redirectUrl, '/'); + $this->assertEquals($this->Users->redirectUrl, '/'); } /** @@ -432,7 +432,7 @@ public function testView() { $this->assertTrue(isset($this->Users->viewVars['user'])); $this->Users->view('INVALID-SLUG'); - $this->assertEqual($this->Users->redirectUrl, '/'); + $this->assertEquals($this->Users->redirectUrl, '/'); } /** @@ -457,7 +457,7 @@ public function testChangePassword() { ->method('destroyCookie'); $this->Users->change_password(); - $this->assertEqual($this->Users->redirectUrl, '/'); + $this->assertEquals($this->Users->redirectUrl, '/'); } /** @@ -475,13 +475,13 @@ public function testResetPassword() { 'User' => array( 'email' => 'adminuser@cakedc.com')); $this->Users->reset_password(); - $this->assertEqual($this->Users->redirectUrl, array('action' => 'login')); + $this->assertEquals($this->Users->redirectUrl, array('action' => 'login')); $this->Users->data = array( 'User' => array( 'new_password' => 'newpassword', 'confirm_password' => 'newpassword')); $this->Users->reset_password('testtoken'); - $this->assertEqual($this->Users->redirectUrl, $this->Users->Auth->loginAction); + $this->assertEquals($this->Users->redirectUrl, $this->Users->Auth->loginAction); } /** @@ -518,10 +518,10 @@ public function testAdminDelete() { $this->Users->User->id = '1'; $this->assertTrue($this->Users->User->exists(true)); $this->Users->admin_delete('1'); - $this->assertEqual($this->Users->redirectUrl, array('action' => 'index')); + $this->assertEquals($this->Users->redirectUrl, array('action' => 'index')); $this->assertFalse($this->Users->User->exists(true)); $this->Users->admin_delete('INVALID-ID'); - $this->assertEqual($this->Users->redirectUrl, array('action' => 'index')); + $this->assertEquals($this->Users->redirectUrl, array('action' => 'index')); } /** @@ -545,7 +545,7 @@ public function testSetCookie() { ->method('setCookie'); $this->Users->setCookie(array( 'name' => 'userTestCookie')); - $this->assertEqual($this->Users->RememberMe->settings['cookieKey'], 'rememberMe'); + $this->assertEquals($this->Users->RememberMe->settings['cookieKey'], 'rememberMe'); } /** @@ -555,10 +555,10 @@ public function testSetCookie() { */ public function testGetMailInstance() { $defaultConfig = $this->Users->getMailInstance()->config(); - $this->assertEqual($defaultConfig['from'], 'default@example.com'); + $this->assertEquals($defaultConfig['from'], 'default@example.com'); Configure::write('Users.emailConfig', 'another'); $anotherConfig = $this->Users->getMailInstance()->config(); - $this->assertEqual($anotherConfig['from'], 'another@example.com'); + $this->assertEquals($anotherConfig['from'], 'another@example.com'); $this->setExpectedException('ConfigureException'); Configure::write('Users.emailConfig', 'doesnotexist'); $anotherConfig = $this->Users->getMailInstance()->config(); diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index 5e2a4d36e..b9686b333 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -241,7 +241,7 @@ public function testRegister() { 'tos' => 0)); $result = $this->User->register($postData); $this->assertFalse($result); - $this->assertEqual(array_keys($this->User->invalidFields()), array( + $this->assertEquals(array_keys($this->User->invalidFields()), array( 'username', 'email', 'temppassword', 'tos')); $postData = array('User' => array( @@ -252,7 +252,7 @@ public function testRegister() { 'tos' => 1)); $result = $this->User->register($postData); $this->assertFalse($result); - $this->assertEqual(array_keys($this->User->invalidFields()), array( + $this->assertEquals(array_keys($this->User->invalidFields()), array( 'password')); $postData = array('User' => array( @@ -265,12 +265,12 @@ public function testRegister() { $this->assertTrue($result); $result = $this->User->data; - $this->assertEqual($result['User']['active'], 1); - $this->assertEqual($result['User']['password'], $this->User->hash('password', 'sha1', true)); + $this->assertEquals($result['User']['active'], 1); + $this->assertEquals($result['User']['password'], $this->User->hash('password', 'sha1', true)); $this->assertTrue(is_string($result['User']['email_token'])); $result = $this->User->findById($this->User->id); - $this->assertEqual($result['User']['id'], $this->User->id); + $this->assertEquals($result['User']['id'], $this->User->id); } /** @@ -292,7 +292,7 @@ public function testChangePassword() { $result = $this->User->changePassword($postData); $this->assertFalse($result); - $this->assertEqual(array('new_password', 'confirm_password'), array_keys($this->User->invalidFields())); + $this->assertEquals(array('new_password', 'confirm_password'), array_keys($this->User->invalidFields())); $postData = array( 'User' => array( @@ -306,7 +306,7 @@ public function testChangePassword() { 'recursive' => -1, 'conditions' => array( 'User.id' => 1))); - $this->assertEqual($ressult['User']['password'], $this->User->hash('testtest', null, true)); + $this->assertEquals($ressult['User']['password'], $this->User->hash('testtest', null, true)); } /** @@ -363,11 +363,11 @@ public function testResendVerification() { public function testGeneratePassword() { $result = $this->User->generatePassword(); $this->assertInternalType('string', $result); - $this->assertEqual(strlen($result), 10); + $this->assertEquals(strlen($result), 10); $result = $this->User->generatePassword(15); $this->assertInternalType('string', $result); - $this->assertEqual(strlen($result), 15); + $this->assertEquals(strlen($result), 15); } /** @@ -413,8 +413,8 @@ public function testEdit() { $this->assertTrue($result); $result = $this->User->read(null, 1); - $this->assertEqual($result['User']['username'], $data['User']['username']); - $this->assertEqual($result['User']['email'], $data['User']['email']); + $this->assertEquals($result['User']['username'], $data['User']['username']); + $this->assertEquals($result['User']['email'], $data['User']['email']); $result = $this->User->edit(1); $this->assertNull($result); @@ -436,7 +436,7 @@ public function testEditPassword() { $hashPassword = $this->User->hash($data['User']['password'], 'sha1', true); $this->assertTrue($result); - $this->assertEqual($this->User->data['User']['password'], $hashPassword); + $this->assertEquals($this->User->data['User']['password'], $hashPassword); $data2['User']['email'] = 'anotherEmail@anotheremail.com'; $data2['User']['password'] = 'anotherNewPassword'; @@ -446,7 +446,7 @@ public function testEditPassword() { $hashPassword = $this->User->hash($data2['User']['password'], 'sha1', true); $this->assertNull($result); - $this->assertNotEqual($data, $data2); + $this->assertNotEquals($data, $data2); } /** From aea36c31ca3956cb4e97d26f4eee566cffa29a0e Mon Sep 17 00:00:00 2001 From: Stone Lasley Date: Mon, 3 Mar 2014 15:22:24 -0700 Subject: [PATCH 0093/1476] Fix testEditPassword --- Test/Case/Model/UserTest.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index b9686b333..de6b06944 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -442,10 +442,12 @@ public function testEditPassword() { $data2['User']['password'] = 'anotherNewPassword'; $data2['User']['temppassword'] = 'differentPassword'; - $result = $this->User->edit(1, $data2); - $hashPassword = $this->User->hash($data2['User']['password'], 'sha1', true); + $this->User->edit(1, $data2); - $this->assertNull($result); + $invalid = $this->User->invalidFields(); + + $this->assertTrue(isset($invalid['temppassword'])); + $this->assertFalse($this->User->validates()); $this->assertNotEquals($data, $data2); } From 69b901e18ef13bb7eb9591ecbdb45ff70963b178 Mon Sep 17 00:00:00 2001 From: Stone Lasley Date: Tue, 4 Mar 2014 10:27:43 -0700 Subject: [PATCH 0094/1476] Controller Test Fixed All tests run with 2.4.5 --- Test/Case/Controller/UsersControllerTest.php | 43 ++++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index e7561011b..ecb84cfaf 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -69,7 +69,7 @@ public function setCookie($options = array()) { } /** - * Public intefface to _getMailInstance + * Public intefface to _getMailInstance */ public function getMailInstance() { return parent::_getMailInstance(); @@ -127,7 +127,7 @@ protected function _getMailInstance() { } /** - * Email configuration override for testing + * Email configuration override for testing */ class EmailConfig { @@ -205,6 +205,8 @@ public function setUp() { 'plugin' => 'users', 'url' => array()); + $this->Users->Prg = $this->getMock('Prg', array('commonProcess')); + $this->Users->CakeEmail = $this->getMock('CakeEmail'); $this->Users->CakeEmail->expects($this->any()) ->method('to') @@ -228,6 +230,10 @@ public function setUp() { $this->Users->Components->disable('Security'); } + public function testTestTest() { + $this->assertTrue(true); + } + /** * Test controller instance * @@ -248,7 +254,13 @@ public function testUserLogin() { $this->Users->request->url = '/users/users/login'; $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Auth = $this->getMock('AuthComponent', array('login', 'user', 'redirect'), array($this->Collection)); + $session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Session = $session; + $this->Users->Session->expects($this->any()) + ->method('setFlash') + ->with(__d('users', 'adminuser you have successfully logged in')); + $this->Users->Auth = $this->getMock('AuthComponent', array('login', 'user', 'redirectUrl'), array($this->Collection)); + $this->Users->Auth->Session = $session; $this->Users->Auth->expects($this->once()) ->method('login') ->will($this->returnValue(true)); @@ -264,14 +276,12 @@ public function testUserLogin() { ->method('user') ->with('username') ->will($this->returnValue('adminuser')); + $this->Users->Auth->expects($this->once()) - ->method('redirect') + ->method('redirectUrl') ->with(null) ->will($this->returnValue(Router::normalize('/'))); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->any()) - ->method('setFlash') - ->with(__d('users', 'adminuser you have successfully logged in')); + $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); $this->Users->RememberMe->expects($this->any()) ->method('destroyCookie'); @@ -312,7 +322,7 @@ public function testFailedUserLogin() { ->will($this->returnValue(false)); $this->Users->Auth->expects($this->once()) ->method('flash') - ->with(__d('users', 'Invalid e-mail / password combination. Please try again')); + ->with(__d('users', 'Invalid e-mail / password combination. Please try again')); $this->Users->login(); } @@ -389,13 +399,13 @@ public function testVerify() { public function testLogout() { $this->Users->beforeFilter(); $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Cookie = $this->getMock('CookieComponent', array('destroy'), array($this->Collection)); - $this->Users->Cookie->expects($this->once()) - ->method('destroy'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); + $this->Users->Cookie = $this->getMock('CookieComponent', array(), array($this->Collection)); + $this->Users->Session = $this->getMock('SessionComponent', array('setFlash', 'destroy'), array($this->Collection)); $this->Users->Session->expects($this->once()) ->method('setFlash') ->with(__d('users', 'testuser you have successfully logged out')); + $this->Users->Session->expects($this->once()) + ->method('destroy'); $this->Users->Auth = $this->getMock('AuthComponent', array('logout', 'user'), array($this->Collection)); $this->Users->Auth->expects($this->once()) ->method('logout') @@ -444,9 +454,9 @@ public function testChangePassword() { $this->Collection = $this->getMock('ComponentCollection'); $this->Users->Auth = $this->getMock('AuthComponent', array('user'), array($this->Collection)); $this->Users->Auth->staticExpects($this->once()) - ->method('user') - ->with('id') - ->will($this->returnValue(1)); + ->method('user') + ->with('id') + ->will($this->returnValue(1)); $this->__setPost(array( 'User' => array( 'new_password' => 'newpassword', @@ -591,7 +601,6 @@ private function __setGet() { * @return void */ public function endTest($method) { - $this->Users->Session->destroy(); unset($this->Users); ClassRegistry::flush(); } From 33b7029172ae53fa43758e9e07e002829c1fb6b4 Mon Sep 17 00:00:00 2001 From: Stone Lasley Date: Tue, 4 Mar 2014 11:04:53 -0700 Subject: [PATCH 0095/1476] Removed testTest --- Test/Case/Controller/UsersControllerTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index ecb84cfaf..1649b1469 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -230,10 +230,6 @@ public function setUp() { $this->Users->Components->disable('Security'); } - public function testTestTest() { - $this->assertTrue(true); - } - /** * Test controller instance * From 835a2a5e1929e635b43a8e3549119e26e29d79be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 17 Apr 2014 12:42:42 +0200 Subject: [PATCH 0096/1476] Fixing missing ' in the readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 5c704694b..0eadd135e 100644 --- a/readme.md +++ b/readme.md @@ -77,7 +77,7 @@ The code will read the login credentials from the cookie and log the user in bas To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php ```php -Configure::write('App.defaultEmail', your@email.com); +Configure::write('App.defaultEmail', 'your@email.com'); ``` If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. From a473132019613edac46a4e88490bc4a4f1d47c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 17 Apr 2014 13:34:56 +0200 Subject: [PATCH 0097/1476] Working on the documentation --- Docs/Documentation/Configuration.md | 113 ++++++++ Docs/Documentation/Extending-The-Plugin.md | 95 ++++++ Docs/Documentation/How-To-Use-It.md | 51 ++++ Docs/Documentation/Installation.md | 16 + Docs/Home.md | 24 ++ readme.md | 322 ++------------------- 6 files changed, 324 insertions(+), 297 deletions(-) create mode 100644 Docs/Documentation/Configuration.md create mode 100644 Docs/Documentation/Extending-The-Plugin.md create mode 100644 Docs/Documentation/How-To-Use-It.md create mode 100644 Docs/Documentation/Installation.md create mode 100644 Docs/Home.md diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md new file mode 100644 index 000000000..f3e815ceb --- /dev/null +++ b/Docs/Documentation/Configuration.md @@ -0,0 +1,113 @@ +Routes for pretty URLs +---------------------- + +To remove the second users from /users/users in the url you can use routes. + +The plugin itself comes with a routes file but you need to explicitly load them. + +```php +CakePlugin::load('Users', array('routes' => true)); +``` + +List of the used routes: + +```php +Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); +Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); +Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); +``` + +If you're extending the plugin remove the plugin from the route by setting it to null and replace the controller with your controller extending the plugins users controller. + +Feel free to change the routes here or add others as you need for your application. + +Email Templates +--------------- + +To modify the templates as needed copy them to + +``` +/app/View/Plugin/Users/Emails/ +``` + +Note that you will have to overwrite any view that is linking to the plugin like the email verification email. + +## Configuration options + +### Disable Slugs + +If the Utils plugin is present the users model will auto attach and use the sluggable behavior. + +To not create slugs for a new user records put this in your configuration: Configure::write('Users.disableSlugs', true); + +### Email configuration + +The plugin uses the $default email configuration (should be present in your Config/email.php file), but you can override it using + +```php +Configure::write('Users.emailConfig', 'default'); +``` + +## Roles Management + +You can add Users.roles on bootstrap.php file and these roles will be used on Admin Add / Edit pages. i.e: + +```php +Configure::write('Users.roles', array('admin' => 'Admin', 'registered' => 'Registered')); +``` + +If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered role setting Users.defaultRole on bootstrap.php. i.e: + +```php +Configure::write('Users.defaultRole', 'user_registered'); +``` + +## Enabling / Disabling Registration + +Some application won't need to have registration enable so you can define Users.allowRegistration on bootstrap.php to enable / disable registration. By default registration will be enabled. + +## Configuration options + +The configuration settings can be written by using the Configure class. + + Users.disableDefaultAuth + +Disables/enables the default auth setup that is implemented in the plugins UsersController::_setupAuth() + + Users.allowRegistration + +Disables/enables the user registration. + + Users.roles + +Optional array of user roles if you need it. This is not activly used by the plugin by default. + + Users.sendPassword + +Disables/enables the password reset functionality + + Users.emailConfig + +Email configuration settings array used by this plugin + +Events +------ + +Events follow these conventions: + +* Users.Controller.Users.someCallBack +* Users.Model.User.someCallBack +* ... + +Triggered events are: + + * Users.Controller.Users.beforeRegister + * Users.Controller.Users.afterRegister + * Users.Controller.Users.beforeLogin + * Users.Controller.Users.afterLogin + * Users.Model.User.beforeRegister + * Users.Model.User.afterRegister \ No newline at end of file diff --git a/Docs/Documentation/Extending-The-Plugin.md b/Docs/Documentation/Extending-The-Plugin.md new file mode 100644 index 000000000..0b11f9a7f --- /dev/null +++ b/Docs/Documentation/Extending-The-Plugin.md @@ -0,0 +1,95 @@ +## How to extend the plugin ## + +### Changing the default "from" email setting ### + +To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php + +```php +Configure::write('App.defaultEmail', 'your@email.com'); +``` + +If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. + +### Extending the controller ### + +Declare the controller class + +```php +App::uses('UsersController', 'Users.Controller'); +class AppUsersController extends UsersController { + public $name = 'AppUsers'; +} +``` + +In the case you want to extend also the user model it's required to set the right user class in the beforeFilter() because the controller will use the inherited model which would be Users.User. + +```php +public function beforeFilter() { + parent::beforeFilter(); + $this->User = ClassRegistry::init('AppUser'); + $this->set('model', 'AppUser'); +} +``` + +You can overwrite the render() method to fall back to the plugin views in the case you want to use some of them + +```php +public function render($view = null, $layout = null) { + if (is_null($view)) { + $view = $this->action; + } + $viewPath = substr(get_class($this), 0, strlen(get_class($this)) - 10); + if (!file_exists(APP . 'View' . DS . $viewPath . DS . $view . '.ctp')) { + $this->plugin = 'Users'; + } else { + $this->viewPath = $viewPath; + } + return parent::render($view, $layout); +} +``` + +Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory + +### Overwriting the default auth settings provided by the plugin + +To use the basics the plugin already offers but changing some of the settings overwrite the _setupAuth() method in the extending controller. + +```php +protected function _setupAuth() { + parent::_setupAuth(); + $this->Auth->loginRedirect = array( + 'plugin' => null, + 'admin' => false, + 'controller' => 'app_users', + 'action' => 'login' + ); +} +``` + +If you want to disable it simply overwrite it without any body + +```php +protected function _setupAuth() { +} +``` + +or you can use the configuration settings to disable it, for example in your boostrap.php + +```php +Configure::write('Users.disableDefaultAuth'); +``` + +### Extending the model ### + +Declare the model + +```php +App::uses('User', 'Users.Model'); +class AppUser extends User { + public $useTable = 'users'; +} +``` + +It's important to override the AppUser::useTable property with the 'users' table. + +You can override/extend all methods or properties like validation rules to suit your needs. diff --git a/Docs/Documentation/How-To-Use-It.md b/Docs/Documentation/How-To-Use-It.md new file mode 100644 index 000000000..b24c4cdb4 --- /dev/null +++ b/Docs/Documentation/How-To-Use-It.md @@ -0,0 +1,51 @@ +How to use it +============= + +You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. + +The plugin itself is already capable of: + +* User registration (Enable by default) +* Account verification by a token sent via email +* User login (email / password) +* Password reset based on requesting a token by email and entering a new password +* Simple profiles for users +* User search (requires the CakeDC Search plugin) +* User management using the "admin" section (add / edit / delete) +* Simple roles management + +The default password reset process requires the user to enter his email address, an email is sent to the user with a link and a token. When the user accesses the URL with the token he can enter a new password. + +Using the "remember me" functionality +------------------------------------- + +To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. + +```php +public $components = array( + 'Users.RememberMe' +); +``` + +If you are using another user model than 'User' you'll have to configure it: + + public $components = array( + 'Users.RememberMe' => array( + 'userModel' => 'AppUser'); + +And add this line + +```php +$this->RememberMe->restoreLoginFromCookie() +``` + +to your controllers beforeFilter() callack + +```php +public function beforeFilter() { + parent::beforeFilter(); + $this->RememberMe->restoreLoginFromCookie(); +} +``` + +The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md new file mode 100644 index 000000000..37394a419 --- /dev/null +++ b/Docs/Documentation/Installation.md @@ -0,0 +1,16 @@ +Installation +============ + +The plugin is pretty easy to set up, all you need to do is to copy it to you application plugins folder and load the needed tables. You can create database tables using either the schema shell or the [CakeDC Migrations plugin](http://github.com/CakeDC/migrations): + +``` +./Console/cake schema create users --plugin Users +``` + +or + +``` +./Console/cake Migrations.migration run all --plugin Users +``` + +You will also need the [CakeDC Search plugin](http://github.com/CakeDC/search), just grab it and put it into your application's plugin folder. \ No newline at end of file diff --git a/Docs/Home.md b/Docs/Home.md new file mode 100644 index 000000000..53a4ee61d --- /dev/null +++ b/Docs/Home.md @@ -0,0 +1,24 @@ +Home +==== + +The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. + +The plugin is thought as a base to extend your app specific users controller and model from. + +That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. You will have to extend the plugin on app level to customize it. Read the instructions carefully. + +Requirements +------------ + +* CakePHP 2.5+ +* PHP 5.2.8+ +* [CakeDC Utils plugin](http://github.com/CakeDC/utils) +* [CakeDC Search plugin](http://github.com/CakeDC/search) + +Documentation +------------- + +* [Installation](Documentation/Installation.md) +* [Configuration](Documentation/Configuration.md) +* [How to use it](Documentation/How-To-Use-It.md) +* [Extending the Plugin](Documentation/Extending-The-Plugin.md) diff --git a/readme.md b/readme.md index 0eadd135e..77cb5c01e 100644 --- a/readme.md +++ b/readme.md @@ -1,317 +1,45 @@ -# Users Plugin for CakePHP # +CakeDC Users Plugin +=================== -for cake 2.x +[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/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) -The users plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. +The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. The plugin is thought as a base to extend your app specific users controller and model from. -That it works out of the box does not mean it is thought to be used exactly like it is but to provide you a kick start. You will have to extend the plugin on app level to customize it. Read the how to use it instructions carefully. +That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. You will have to extend the plugin on app level to customize it. Read the instructions carefully. -## Installation ## -The plugin is pretty easy to set up, all you need to do is to copy it to you application plugins folder and load the needed tables. You can create database tables using either the schema shell or the [CakeDC Migrations plugin](http://github.com/CakeDC/migrations): +Requirements +------------ - ./Console/cake schema create users --plugin Users - -or - - ./Console/cake Migrations.migration run all --plugin Users - -You will also need the [CakeDC Search plugin](http://github.com/CakeDC/search), just grab it and put it into your application's plugin folder. - -## How to use it ## - -You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. - -The plugin itself is already capable of: - -* User registration (Enable by default) -* Account verification by a token sent via email -* User login (email / password) -* Password reset based on requesting a token by email and entering a new password -* Simple profiles for users -* User search (requires the CakeDC Search plugin) -* User management using the "admin" section (add / edit / delete) -* Simple roles management - -The default password reset process requires the user to enter his email address, an email is sent to the user with a link and a token. When the user accesses the URL with the token he can enter a new password. - -### Using the "remember me" functionality ### - -To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. - -```php -public $components = array( - 'Users.RememberMe' -); -``` - -If you are using another user model than 'User' you'll have to configure it: - - public $components = array( - 'Users.RememberMe' => array( - 'userModel' => 'AppUser'); - -And add this line - -```php -$this->RememberMe->restoreLoginFromCookie() -``` - -to your controllers beforeFilter() callack - -```php -public function beforeFilter() { - parent::beforeFilter(); - $this->RememberMe->restoreLoginFromCookie(); -} -``` - -The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. - -## How to extend the plugin ## - -### Changing the default "from" email setting ### - -To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php - -```php -Configure::write('App.defaultEmail', 'your@email.com'); -``` - -If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. - -### Extending the controller ### - -Declare the controller class - -```php -App::uses('UsersController', 'Users.Controller'); -class AppUsersController extends UsersController { - public $name = 'AppUsers'; -} -``` - -In the case you want to extend also the user model it's required to set the right user class in the beforeFilter() because the controller will use the inherited model which would be Users.User. - -```php -public function beforeFilter() { - parent::beforeFilter(); - $this->User = ClassRegistry::init('AppUser'); - $this->set('model', 'AppUser'); -} -``` - -You can overwrite the render() method to fall back to the plugin views in the case you want to use some of them - -```php -public function render($view = null, $layout = null) { - if (is_null($view)) { - $view = $this->action; - } - $viewPath = substr(get_class($this), 0, strlen(get_class($this)) - 10); - if (!file_exists(APP . 'View' . DS . $viewPath . DS . $view . '.ctp')) { - $this->plugin = 'Users'; - } else { - $this->viewPath = $viewPath; - } - return parent::render($view, $layout); -} -``` - -Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory - -### Overwriting the default auth settings provided by the plugin - -To use the basics the plugin already offers but changing some of the settings overwrite the _setupAuth() method in the extending controller. - -```php -protected function _setupAuth() { - parent::_setupAuth(); - $this->Auth->loginRedirect = array( - 'plugin' => null, - 'admin' => false, - 'controller' => 'app_users', - 'action' => 'login' - ); -} -``` - -If you want to disable it simply overwrite it without any body - -```php -protected function _setupAuth() { -} -``` - -or you can use the configuration settings to disable it, for example in your boostrap.php - -```php -Configure::write('Users.disableDefaultAuth'); -``` - -### Extending the model ### - -Declare the model - -```php -App::uses('User', 'Users.Model'); -class AppUser extends User { - public $useTable = 'users'; -} -``` - -It's important to override the AppUser::useTable property with the 'users' table. - -You can override/extend all methods or properties like validation rules to suit your needs. - -### Routes for pretty URLs ### - -To remove the second users from /users/users in the url you can use routes. - -The plugin itself comes with a routes file but you need to explicitly load them. - -```php -CakePlugin::load('Users', array('routes' => true)); -``` - -List of the used routes: - -```php -Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); -Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); -Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); -``` - -If you're extending the plugin remove the plugin from the route by setting it to null and replace the controller with your controller extending the plugins users controller. - -Feel free to change the routes here or add others as you need for your application. - -### Email Templates - -To modify the templates as needed copy them to - - /app/View/Plugin/Users/Emails/ - -Note that you will have to overwrite any view that is linking to the plugin like the email verification email. - -## Configuration options - -### Disable Slugs - -If the Utils plugin is present the users model will auto attach and use the sluggable behavior. - -To not create slugs for a new user records put this in your configuration: Configure::write('Users.disableSlugs', true); - -### Email configuration - -The plugin uses the $default email configuration (should be present in your Config/email.php file), but you can override it using - -```php -Configure::write('Users.emailConfig', 'default'); -``` - -## Roles Management - -You can add Users.roles on bootstrap.php file and these roles will be used on Admin Add / Edit pages. i.e: - -```php -Configure::write('Users.roles', array('admin' => 'Admin', 'registered' => 'Registered')); -``` - -If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered role setting Users.defaultRole on bootstrap.php. i.e: - -```php -Configure::write('Users.defaultRole', 'user_registered'); -``` - -## Enabling / Disabling Registration - -Some application won't need to have registration enable so you can define Users.allowRegistration on bootstrap.php to enable / disable registration. By default registration will be enabled. - -## Configuration options - -The configuration settings can be written by using the Configure class. - - Users.disableDefaultAuth - -Disables/enables the default auth setup that is implemented in the plugins UsersController::_setupAuth() - - Users.allowRegistration - -Disables/enables the user registration. - - Users.roles - -Optional array of user roles if you need it. This is not activly used by the plugin by default. - - Users.sendPassword - -Disables/enables the password reset functionality - - Users.emailConfig - -Email configuration settings array used by this plugin - -## Events ## - -Events follow these conventions: - - Users.Controller.Users.someCallBack - Users.Model.User.someCallBack - ... - -Triggered events are: - - * Users.Controller.Users.beforeRegister - * Users.Controller.Users.afterRegister - * Users.Controller.Users.beforeLogin - * Users.Controller.Users.afterLogin - * Users.Model.User.beforeRegister - * Users.Model.User.afterRegister - -## Requirements ## - -* PHP version: PHP 5.2+ -* CakePHP version: Cakephp 2.0 +* CakePHP 2.5+ +* PHP 5.2.8+ * [CakeDC Utils plugin](http://github.com/CakeDC/utils) * [CakeDC Search plugin](http://github.com/CakeDC/search) -## Support ## - -For support and feature request, please visit the [Users Plugin Support Site](http://cakedc.lighthouseapp.com/projects/60126-users-plugin/). - -For more information about our Professional CakePHP Services please visit the [Cake Development Corporation website](http://cakedc.com). - -## Branch strategy ## - -The master branch holds the STABLE latest version of the plugin. -Develop branch is UNSTABLE and used to test new features before releasing them. +Documentation +------------- -Previous maintenance versions are named after the CakePHP compatible version, for example, branch 1.3 is the maintenance version compatible with CakePHP 1.3. -All versions are updated with security patches. +For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory of this repository. -## Contributing to this Plugin ## +Support +------- -Please feel free to contribute to the plugin with new issues, requests, unit tests and code fixes or new features. If you want to contribute some code, create a feature branch from develop, and send us your pull request. Unit tests for new features and issues detected are mandatory to keep quality high. +For bugs and feature requests, please use the [issues](https://github.com/CakeDC/users/issues) section of this repository. -## License ## +Commercial support is also available, [contact us](http://cakedc.com/contact) for more information. -Copyright 2009-2013, [Cake Development Corporation](http://cakedc.com) +Contributing +------------ -Licensed under [The MIT License](http://www.opensource.org/licenses/mit-license.php)
-Redistributions of files must retain the above copyright notice. +This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/contribution-guidelines) for detailed instructions. -## Copyright ### +License +------- -Copyright 2009-2013
-[Cake Development Corporation](http://cakedc.com)
-1785 E. Sahara Avenue, Suite 490-423
-Las Vegas, Nevada 89104
-http://cakedc.com
+Copyright 2007-2014 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 effa068daf5aa45c9de7dc2572e7f2ff2b0003d8 Mon Sep 17 00:00:00 2001 From: Walter Nasich Date: Sun, 20 Apr 2014 16:29:32 -0300 Subject: [PATCH 0098/1476] Fixing typo in error message --- Locale/deu/LC_MESSAGES/users.po | 2 +- Locale/fra/LC_MESSAGES/users.po | 2 +- Locale/nld/LC_MESSAGES/users.po | 2 +- Locale/pt_BR/LC_MESSAGES/users.po | 2 +- Locale/users.pot | 2 +- Locale/zh_TW/LC_MESSAGES/users.po | 2 +- Model/User.php | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Locale/deu/LC_MESSAGES/users.po b/Locale/deu/LC_MESSAGES/users.po index 4fb1b4703..282922603 100644 --- a/Locale/deu/LC_MESSAGES/users.po +++ b/Locale/deu/LC_MESSAGES/users.po @@ -245,7 +245,7 @@ msgid "The email address does not exist in the system" msgstr "Diese Email-Adresse existiert nicht im System" #: /models/user.php:520 -msgid "Your account is already authenticaed." +msgid "Your account is already authenticated." msgstr "Dein Account ist bereits bestätigt." #: /models/user.php:525 diff --git a/Locale/fra/LC_MESSAGES/users.po b/Locale/fra/LC_MESSAGES/users.po index a3e8843bb..7810b4eea 100644 --- a/Locale/fra/LC_MESSAGES/users.po +++ b/Locale/fra/LC_MESSAGES/users.po @@ -232,7 +232,7 @@ msgid "The email address does not exist in the system" msgstr "Cette adresse email n'existe pas dans le système." #: /models/user.php:520 -msgid "Your account is already authenticaed." +msgid "Your account is already authenticated." msgstr "Votre compte est déjà authentifié." #: /models/user.php:525 diff --git a/Locale/nld/LC_MESSAGES/users.po b/Locale/nld/LC_MESSAGES/users.po index 76f9095dc..d869aae26 100644 --- a/Locale/nld/LC_MESSAGES/users.po +++ b/Locale/nld/LC_MESSAGES/users.po @@ -190,7 +190,7 @@ msgid "The email address does not exist in the system" msgstr "Het emailadres bestaat niet in dit systeem" #: Model/User.php:566 -msgid "Your account is already authenticaed." +msgid "Your account is already authenticated." msgstr "Uw account is al geverifiëerd." #: Model/User.php:571 diff --git a/Locale/pt_BR/LC_MESSAGES/users.po b/Locale/pt_BR/LC_MESSAGES/users.po index eddc80325..ffb50702b 100644 --- a/Locale/pt_BR/LC_MESSAGES/users.po +++ b/Locale/pt_BR/LC_MESSAGES/users.po @@ -244,7 +244,7 @@ msgid "The email address does not exist in the system" msgstr "O endereço de e-mail não existe no sistema" #: /models/user.php:520 -msgid "Your account is already authenticaed." +msgid "Your account is already authenticated." msgstr "Sua conta já está autenticada." #: /models/user.php:525 diff --git a/Locale/users.pot b/Locale/users.pot index b3204a817..ca48a99b2 100644 --- a/Locale/users.pot +++ b/Locale/users.pot @@ -177,7 +177,7 @@ msgid "The email address does not exist in the system" msgstr "" #: Model/User.php:596 -msgid "Your account is already authenticaed." +msgid "Your account is already authenticated." msgstr "" #: Model/User.php:601 diff --git a/Locale/zh_TW/LC_MESSAGES/users.po b/Locale/zh_TW/LC_MESSAGES/users.po index 80f820e3e..c677a24cc 100644 --- a/Locale/zh_TW/LC_MESSAGES/users.po +++ b/Locale/zh_TW/LC_MESSAGES/users.po @@ -242,7 +242,7 @@ msgid "The email address does not exist in the system" msgstr "系統中不存在該電子郵件信箱。" #: /models/user.php:520 -msgid "Your account is already authenticaed." +msgid "Your account is already authenticated." msgstr "您的帳號已經認證。" #: /models/user.php:525 diff --git a/Model/User.php b/Model/User.php index 300157356..bb0148163 100755 --- a/Model/User.php +++ b/Model/User.php @@ -593,7 +593,7 @@ public function resendVerification($postData = array()) { } if ($user[$this->alias]['email_verified'] == 1) { - $this->invalidate('email', __d('users', 'Your account is already authenticaed.')); + $this->invalidate('email', __d('users', 'Your account is already authenticated.')); return false; } From 29537ad8336cafdb49b30bb4ef9e21e022f77636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 20 Apr 2014 23:22:34 +0200 Subject: [PATCH 0099/1476] Changing .travis and updating composer.json --- .travis.yml | 54 ++++++++++--------- ...llUsersPluginTest.php => AllUsersTest.php} | 0 composer.json | 37 +++++++------ 3 files changed, 49 insertions(+), 42 deletions(-) rename Test/Case/{AllUsersPluginTest.php => AllUsersTest.php} (100%) diff --git a/.travis.yml b/.travis.yml index df0078024..fe320e06d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,32 +1,36 @@ language: php - + php: - - 5.2.8 - 5.3 - 5.4 - + - 5.5 + +env: + global: + - PLUGIN_NAME=Users + - DB=mysql + +matrix: + include: + - php: 5.3 + env: + - CAKE_VERSION=master + - php: 5.4 + env: + - CAKE_VERSION=master + - php: 5.5 + env: + - CAKE_VERSION=master + before_script: - - git clone --depth 1 git://github.com/cakephp/cakephp ../cakephp && cd ../cakephp - - git clone --depth 1 --branch develop git://github.com/CakeDC/search plugins/search - - cd plugins/Search - - git submodule update --init --recursive - - cd ../../ - - mv ../Users plugins/Users - - sh -c "mysql -e 'CREATE DATABASE cakephp_test;'" - - chmod -R 777 ../cakephp/app/tmp - - echo " 'Database/Mysql', - 'database' => 'cakephp_test', - 'host' => '0.0.0.0', - 'login' => 'travis', - 'persistent' => false, - ); - }" > ../cakephp/app/Config/database.php - + - git clone https://github.com/burzum/travis.git --depth 1 ../travis + - ../travis/before_script.sh + script: - - ./lib/Cake/Console/cake test Users AllUsersPlugin --stderr - + - ../travis/script.sh + +after_success: + - ../travis/after_success.sh + notifications: - email: false \ No newline at end of file + email: false diff --git a/Test/Case/AllUsersPluginTest.php b/Test/Case/AllUsersTest.php similarity index 100% rename from Test/Case/AllUsersPluginTest.php rename to Test/Case/AllUsersTest.php diff --git a/composer.json b/composer.json index 23e79f73e..07ce3d564 100644 --- a/composer.json +++ b/composer.json @@ -1,19 +1,22 @@ { - "name": "cakedc/users", - "type": "cakephp-plugin", - "description": "Users Plugin for CakePHP", - "keywords": ["cakephp","users","auth"], - "homepage": "http://cakedc.com", - "license": "MIT", - "authors": [ - { - "name": "Cake Development Corporation", - "homepage": "http://cakedc.com" - } - ], - "require": { - "composer/installers": "*", - "cakedc/search": "*", - "cakedc/utils": "*" - } + "name": "cakedc/users", + "type": "cakephp-plugin", + "description": "Users Plugin for CakePHP", + "keywords": ["cakephp","users","auth"], + "homepage": "http://cakedc.com", + "license": "MIT", + "authors": [ + { + "name": "Cake Development Corporation", + "homepage": "http://cakedc.com" + } + ], + "require": { + "composer/installers": "*", + "cakedc/search": "*", + "cakedc/utils": "*" + }, + "extra": { + "installer-name": "Users" + } } From dde4f608cdc7de9584c01a2eb5a6489015964742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 20 Apr 2014 23:39:27 +0200 Subject: [PATCH 0100/1476] Changing .travis --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index fe320e06d..51708d571 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,9 @@ env: - PLUGIN_NAME=Users - DB=mysql + matrix: + - DB=mysql CAKE_VERSION=master + matrix: include: - php: 5.3 From 3a66dd227db88f41d2d3959c934f7f251bced89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 27 Apr 2014 18:52:12 +0200 Subject: [PATCH 0101/1476] Fixing some upper cased controller names in sidebar.ctp which causes the urls to not work --- View/Elements/Users/sidebar.ctp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/View/Elements/Users/sidebar.ctp b/View/Elements/Users/sidebar.ctp index 95671713a..68bc08a98 100644 --- a/View/Elements/Users/sidebar.ctp +++ b/View/Elements/Users/sidebar.ctp @@ -1,18 +1,18 @@
    Session->read('Auth.User.id')) : ?> -
  • Html->link(__d('users', 'Login'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'login')); ?>
  • +
  • Html->link(__d('users', 'Login'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); ?>
  • -
  • Html->link(__d('users', 'Register an account'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'add')); ?>
  • +
  • Html->link(__d('users', 'Register an account'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); ?>
  • -
  • Html->link(__d('users', 'Logout'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'logout')); ?> -
  • Html->link(__d('users', 'My Account'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'edit')); ?> -
  • Html->link(__d('users', 'Change password'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'change_password')); ?> +
  • Html->link(__d('users', 'Logout'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); ?> +
  • Html->link(__d('users', 'My Account'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'edit')); ?> +
  • Html->link(__d('users', 'Change password'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'change_password')); ?> Session->read('Auth.User.is_admin')) : ?>
  •  
  • -
  • Html->link(__d('users', 'List Users'), array('plugin' => 'Users', 'controller' => 'users', 'action' => 'index'));?>
  • +
  • Html->link(__d('users', 'List Users'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'index'));?>
From eb96de0297c72d4ad2af938688da6e6ab1de8580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 27 Apr 2014 18:52:31 +0200 Subject: [PATCH 0102/1476] Just some CS fixes --- Controller/Component/RememberMeComponent.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 34e36b0d0..b045bc464 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -28,7 +28,8 @@ class RememberMeComponent extends Component { */ public $components = array( 'Cookie', - 'Auth'); + 'Auth' + ); /** * Request object @@ -55,11 +56,14 @@ class RememberMeComponent extends Component { 'cookieKey' => 'rememberMe', 'cookieLifeTime' => '+1 year', 'cookie' => array( - 'name' => 'User'), + 'name' => 'User' + ), 'fields' => array( 'email', 'username', - 'password')); + 'password' + ) + ); /** * Constructor From a4e6a95338728163ac49e1fa4609574d913e955e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 27 Apr 2014 18:54:03 +0200 Subject: [PATCH 0103/1476] Fixing https://github.com/CakeDC/users/pull/174 --- Controller/UsersController.php | 6 +++++- Model/User.php | 13 +++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index d847da8a3..b61c0b6d8 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -268,7 +268,9 @@ public function view($slug = null) { } /** - * Edit + * Edit the current logged in user + * + * Extend the plugin and implement your custom logic here * * @return void */ @@ -346,6 +348,7 @@ public function admin_edit($userId = null) { $this->Session->setFlash(__d('users', 'User saved')); $this->redirect(array('action' => 'index')); } else { + unset($result[$this->modelClass]['password']); $this->request->data = $result; } } catch (OutOfBoundsException $e) { @@ -355,6 +358,7 @@ public function admin_edit($userId = null) { if (empty($this->request->data)) { $this->request->data = $this->{$this->modelClass}->read(null, $userId); + unset($this->request->data[$this->modelClass]['password']); } $this->set('roles', Configure::read('Users.roles')); } diff --git a/Model/User.php b/Model/User.php index bb0148163..62148b88d 100755 --- a/Model/User.php +++ b/Model/User.php @@ -817,6 +817,8 @@ public function add($postData = null) { /** * Edits an existing user * + * When saving a password it get hashed if the field is present AND not empty + * * @param string $userId User ID * @param array $postData controller post data usually $this->data * @throws NotFoundException @@ -825,14 +827,10 @@ public function add($postData = null) { public function edit($userId = null, $postData = null) { $user = $this->getUserForEditing($userId); $this->set($user); - if (empty($user)) { - throw new NotFoundException(__d('users', 'Invalid User')); - } - if (!empty($postData)) { $this->set($postData); if ($this->validates()) { - if(isset($this->data[$this->alias]['password'])) { + if (!empty($this->data[$this->alias]['password'])) { $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['password'], 'sha1', true); } $result = $this->save(null, false); @@ -859,7 +857,10 @@ public function edit($userId = null, $postData = null) { public function getUserForEditing($userId = null, $options = array()) { $defaults = array( 'contain' => array(), - 'conditions' => array($this->alias . '.id' => $userId)); + 'conditions' => array( + $this->alias . '.id' => $userId + ) + ); $options = Set::merge($defaults, $options); $user = $this->find('first', $options); From 8939e5e1be7a3a2ffa7aca9939d0e67096e38dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Fri, 23 May 2014 17:04:27 +0200 Subject: [PATCH 0104/1476] Updating travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 51708d571..b9b76039b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ env: global: - PLUGIN_NAME=Users - DB=mysql + - REQUIRE="phpunit/phpunit:3.7.31" matrix: - DB=mysql CAKE_VERSION=master From 50f059724014e579a7df696228d3ea8382b139b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Fri, 23 May 2014 17:04:37 +0200 Subject: [PATCH 0105/1476] Adding semver and CONTRIBUTING.md --- .semver | 5 +++++ CONTRIBUTING.md | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 .semver create mode 100644 CONTRIBUTING.md diff --git a/.semver b/.semver new file mode 100644 index 000000000..8b186ad64 --- /dev/null +++ b/.semver @@ -0,0 +1,5 @@ +--- +:major: 2 +:minor: 2 +:patch: 0 +:special: '' \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..408e81198 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing +============ + +This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugins). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/plugins) for detailed instructions. \ No newline at end of file From 0a6c672d63495df1a5f18980d04946c2c6fe0f8e Mon Sep 17 00:00:00 2001 From: xubuntu Date: Fri, 23 May 2014 11:07:28 -0400 Subject: [PATCH 0106/1476] Renaming a few files to be upper cased --- license.txt => LICENSE.txt | 0 readme.md => README.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename license.txt => LICENSE.txt (100%) rename readme.md => README.md (100%) diff --git a/license.txt b/LICENSE.txt similarity index 100% rename from license.txt rename to LICENSE.txt diff --git a/readme.md b/README.md similarity index 100% rename from readme.md rename to README.md From f9c07ec6f18717aa6d3f3fb57a94ef4c688a6f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 27 May 2014 12:43:21 +0200 Subject: [PATCH 0107/1476] Adding information about the legacy user details to the documentation --- Docs/Documentation/User-Details.md | 28 ++++++++++++++++++++++++++++ Docs/Home.md | 1 + 2 files changed, 29 insertions(+) create mode 100644 Docs/Documentation/User-Details.md diff --git a/Docs/Documentation/User-Details.md b/Docs/Documentation/User-Details.md new file mode 100644 index 000000000..2a4bbc27a --- /dev/null +++ b/Docs/Documentation/User-Details.md @@ -0,0 +1,28 @@ +User Details +============ + +The plugin contains an `user_details` table. This table is a key-value store and is not used by the plugin any more but kept for legacy apps. + +If you want to use it you'll have to add the associations by extending the plugin or add your own profiles table which is recommend to use instead of a key-value store. + +```php +class AppUser extends User { + public $hasMany = array( + 'UserDetail' => arraya( + 'className' => 'Users.'UserDetail' + ) + ); +} +``` + +Or using your custom profiles table. + +```php +class AppUser extends User { + public $hasOne = array( + 'Profile' => arraya( + 'className' => 'Profile' + ) + ); +} +``` \ No newline at end of file diff --git a/Docs/Home.md b/Docs/Home.md index 53a4ee61d..90a45d809 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -21,4 +21,5 @@ Documentation * [Installation](Documentation/Installation.md) * [Configuration](Documentation/Configuration.md) * [How to use it](Documentation/How-To-Use-It.md) +* [User Details (Legacy)](Documentation/User-Details.md) * [Extending the Plugin](Documentation/Extending-The-Plugin.md) From 7c238cc0b7217ad4740f9fca66555f17d2f11371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 27 May 2014 12:53:00 +0200 Subject: [PATCH 0108/1476] Fixing a typo in the docs --- Docs/Documentation/User-Details.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/User-Details.md b/Docs/Documentation/User-Details.md index 2a4bbc27a..be365ec93 100644 --- a/Docs/Documentation/User-Details.md +++ b/Docs/Documentation/User-Details.md @@ -8,7 +8,7 @@ If you want to use it you'll have to add the associations by extending the plugi ```php class AppUser extends User { public $hasMany = array( - 'UserDetail' => arraya( + 'UserDetail' => array( 'className' => 'Users.'UserDetail' ) ); @@ -25,4 +25,4 @@ class AppUser extends User { ) ); } -``` \ No newline at end of file +``` From 6884dcfa5b5706d8d3169839070badf8a4fc53bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 27 May 2014 12:53:39 +0200 Subject: [PATCH 0109/1476] Fixing a typo in the docs --- Docs/Documentation/User-Details.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/User-Details.md b/Docs/Documentation/User-Details.md index be365ec93..b98813683 100644 --- a/Docs/Documentation/User-Details.md +++ b/Docs/Documentation/User-Details.md @@ -9,7 +9,7 @@ If you want to use it you'll have to add the associations by extending the plugi class AppUser extends User { public $hasMany = array( 'UserDetail' => array( - 'className' => 'Users.'UserDetail' + 'className' => 'Users.UserDetail' ) ); } @@ -20,7 +20,7 @@ Or using your custom profiles table. ```php class AppUser extends User { public $hasOne = array( - 'Profile' => arraya( + 'Profile' => array( 'className' => 'Profile' ) ); From 4b0b21033c8d896b113114696ad003c68d26f6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 18 Jun 2014 18:09:00 +0200 Subject: [PATCH 0110/1476] Replacing Set with Hash --- Controller/Component/RememberMeComponent.php | 2 +- Controller/UsersController.php | 2 +- Model/User.php | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index b045bc464..497f7fba2 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -75,7 +75,7 @@ public function __construct(ComponentCollection $collection, $settings = array() parent::__construct($collection, $settings); $this->_checkAndSetCookieLifeTime(); - $this->settings = Set::merge($this->_defaults, $settings); + $this->settings = Hash::merge($this->_defaults, $settings); $this->configureCookie($this->settings['cookie']); } diff --git a/Controller/UsersController.php b/Controller/UsersController.php index b61c0b6d8..19a86d0bd 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -816,7 +816,7 @@ protected function _resetPassword($token) { $this->redirect(array('action' => 'reset_password')); } - if (!empty($this->request->data) && $this->{$this->modelClass}->resetPassword(Set::merge($user, $this->request->data))) { + if (!empty($this->request->data) && $this->{$this->modelClass}->resetPassword(Hash::merge($user, $this->request->data))) { if ($this->RememberMe->cookieIsSet()) { $this->Session->setFlash(__d('users', 'Password changed.')); $this->_setCookie(); diff --git a/Model/User.php b/Model/User.php index 62148b88d..fc042c7ea 100755 --- a/Model/User.php +++ b/Model/User.php @@ -710,17 +710,17 @@ protected function _findSearch($state, $query, $results = array()) { switch ($by) { case 'username': - $results['conditions'] = Set::merge( + $results['conditions'] = Hash::merge( $query['conditions'], array($this->alias . '.username LIKE' => $like)); break; case 'email': - $results['conditions'] = Set::merge( + $results['conditions'] = Hash::merge( $query['conditions'], array($this->alias . '.email LIKE' => $like)); break; case 'any': - $results['conditions'] = Set::merge( + $results['conditions'] = Hash::merge( $query['conditions'], array('OR' => array( array($this->alias . '.username LIKE' => $like), @@ -730,7 +730,7 @@ protected function _findSearch($state, $query, $results = array()) { $results['conditions'] = $query['conditions']; break; default : - $results['conditions'] = Set::merge( + $results['conditions'] = Hash::merge( $query['conditions'], array($this->alias . '.username LIKE' => $like)); break; @@ -861,7 +861,7 @@ public function getUserForEditing($userId = null, $options = array()) { $this->alias . '.id' => $userId ) ); - $options = Set::merge($defaults, $options); + $options = Hash::merge($defaults, $options); $user = $this->find('first', $options); @@ -882,7 +882,8 @@ public function getUserForEditing($userId = null, $options = array()) { protected function _removeExpiredRegistrations() { $this->deleteAll(array( $this->alias . '.email_verified' => 0, - $this->alias . '.email_token_expires <' => date('Y-m-d H:i:s'))); + $this->alias . '.email_token_expires <' => date('Y-m-d H:i:s')) + ); } } From 2f24ce5c871f40cbe24a5c29b2a24ba7c303e499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 18 Jun 2014 18:37:03 +0200 Subject: [PATCH 0111/1476] Working on the documentation and tests --- CHANGELOG.md | 0 Controller/Component/RememberMeComponent.php | 1 + Controller/UsersController.php | 9 +- Docs/Documentation/Configuration.md | 92 +++++++------------ Docs/Documentation/Events.md | 19 ++++ Docs/Documentation/Extending-The-Plugin.md | 16 ++-- Docs/Documentation/Features.md | 16 ++++ Docs/Documentation/How-To-Use-It.md | 51 ---------- Docs/Documentation/Installation.md | 30 +++++- Docs/Documentation/Remember-Me-Component.md | 37 ++++++++ Docs/Documentation/Routing.md | 26 ++++++ Docs/Documentation/User-Details.md | 8 +- Docs/Home.md | 5 +- Model/User.php | 7 +- Test/Case/AllUsersTest.php | 15 ++- .../Component/Auth/CookieAuthenticateTest.php | 4 +- .../Auth/MultiColumnAuthenticateTest.php | 4 +- .../Component/Auth/TokenAuthenticateTest.php | 4 +- Test/Case/Model/UserTest.php | 1 + Test/Fixture/MultiUserFixture.php | 1 - 20 files changed, 199 insertions(+), 147 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 Docs/Documentation/Events.md create mode 100644 Docs/Documentation/Features.md delete mode 100644 Docs/Documentation/How-To-Use-It.md create mode 100644 Docs/Documentation/Remember-Me-Component.md create mode 100644 Docs/Documentation/Routing.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..e69de29bb diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 497f7fba2..72af406b8 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -70,6 +70,7 @@ class RememberMeComponent extends Component { * * @param ComponentCollection $collection A ComponentCollection for this component * @param array $settings Array of settings. + * @return RememberMeComponent */ public function __construct(ComponentCollection $collection, $settings = array()) { parent::__construct($collection, $settings); diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 19a86d0bd..367def837 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -531,9 +531,12 @@ public function search() { 'by' => $by, 'search' => $searchTerm, 'conditions' => array( - 'AND' => array( - $this->modelClass . '.active' => 1, - $this->modelClass . '.email_verified' => 1))); + 'AND' => array( + $this->modelClass . '.active' => 1, + $this->modelClass . '.email_verified' => 1 + ) + ) + ); $this->set('users', $this->Paginator->paginate($this->modelClass)); $this->set('searchTerm', $searchTerm); diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index f3e815ceb..fdb3ef5e6 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -1,29 +1,5 @@ -Routes for pretty URLs ----------------------- - -To remove the second users from /users/users in the url you can use routes. - -The plugin itself comes with a routes file but you need to explicitly load them. - -```php -CakePlugin::load('Users', array('routes' => true)); -``` - -List of the used routes: - -```php -Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); -Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); -Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); -``` - -If you're extending the plugin remove the plugin from the route by setting it to null and replace the controller with your controller extending the plugins users controller. - -Feel free to change the routes here or add others as you need for your application. +Configuration +============= Email Templates --------------- @@ -36,15 +12,15 @@ To modify the templates as needed copy them to Note that you will have to overwrite any view that is linking to the plugin like the email verification email. -## Configuration options - -### Disable Slugs +Disable Slugs +------------- If the Utils plugin is present the users model will auto attach and use the sluggable behavior. To not create slugs for a new user records put this in your configuration: Configure::write('Users.disableSlugs', true); -### Email configuration +Email configuration +------------------- The plugin uses the $default email configuration (should be present in your Config/email.php file), but you can override it using @@ -52,7 +28,8 @@ The plugin uses the $default email configuration (should be present in your Conf Configure::write('Users.emailConfig', 'default'); ``` -## Roles Management +Roles Management +---------------- You can add Users.roles on bootstrap.php file and these roles will be used on Admin Add / Edit pages. i.e: @@ -66,48 +43,47 @@ If you don't specify roles it will use 'admin' role (if is_admin is checked) or Configure::write('Users.defaultRole', 'user_registered'); ``` -## Enabling / Disabling Registration +Enabling / Disabling Registration +--------------------------------- -Some application won't need to have registration enable so you can define Users.allowRegistration on bootstrap.php to enable / disable registration. By default registration will be enabled. +Some application won't need to have registration enable so you can define ```Users.allowRegistration``` in ```bootstrap.php``` to enable or disable registration. By default registration will be enabled. + +``` +// Disables the registration +Configure::write('Users.allowRegistration', false); +``` -## Configuration options +Configuration options +--------------------- The configuration settings can be written by using the Configure class. - Users.disableDefaultAuth +``` +Users.disableDefaultAuth +``` Disables/enables the default auth setup that is implemented in the plugins UsersController::_setupAuth() - Users.allowRegistration +``` +Users.allowRegistration +``` Disables/enables the user registration. - Users.roles +``` +Users.roles +``` Optional array of user roles if you need it. This is not activly used by the plugin by default. - Users.sendPassword +``` +Users.sendPassword +``` Disables/enables the password reset functionality - Users.emailConfig - -Email configuration settings array used by this plugin - -Events ------- - -Events follow these conventions: - -* Users.Controller.Users.someCallBack -* Users.Model.User.someCallBack -* ... - -Triggered events are: +``` +Users.emailConfig +``` - * Users.Controller.Users.beforeRegister - * Users.Controller.Users.afterRegister - * Users.Controller.Users.beforeLogin - * Users.Controller.Users.afterLogin - * Users.Model.User.beforeRegister - * Users.Model.User.afterRegister \ No newline at end of file +Email configuration settings array used by this plugin. diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md new file mode 100644 index 000000000..d8fcb06da --- /dev/null +++ b/Docs/Documentation/Events.md @@ -0,0 +1,19 @@ +Events +====== + +If you're not familiar with events look them up in [the official documentation](http://book.cakephp.org/2.0/en/core-libraries/events.html). + +Events follow these conventions: + +* Users.Controller.Users.someCallBack +* Users.Model.User.someCallBack +* ... + +Triggered events are: + + * Users.Controller.Users.beforeRegister + * Users.Controller.Users.afterRegister + * Users.Controller.Users.beforeLogin + * Users.Controller.Users.afterLogin + * Users.Model.User.beforeRegister + * Users.Model.User.afterRegister \ No newline at end of file diff --git a/Docs/Documentation/Extending-The-Plugin.md b/Docs/Documentation/Extending-The-Plugin.md index 0b11f9a7f..8d5063f30 100644 --- a/Docs/Documentation/Extending-The-Plugin.md +++ b/Docs/Documentation/Extending-The-Plugin.md @@ -1,4 +1,5 @@ -## How to extend the plugin ## +Extending the Plugin +==================== ### Changing the default "from" email setting ### @@ -10,7 +11,8 @@ Configure::write('App.defaultEmail', 'your@email.com'); If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. -### Extending the controller ### +Extending the controller +------------------------ Declare the controller class @@ -50,7 +52,8 @@ public function render($view = null, $layout = null) { Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory -### Overwriting the default auth settings provided by the plugin +Overwriting the default auth settings +------------------------------------- To use the basics the plugin already offers but changing some of the settings overwrite the _setupAuth() method in the extending controller. @@ -73,7 +76,7 @@ protected function _setupAuth() { } ``` -or you can use the configuration settings to disable it, for example in your boostrap.php +or you can use the configuration settings to disable it, for example in your ```bootstrap.php``` ```php Configure::write('Users.disableDefaultAuth'); @@ -86,10 +89,11 @@ Declare the model ```php App::uses('User', 'Users.Model'); class AppUser extends User { + public $name = 'AppUser'; public $useTable = 'users'; } ``` -It's important to override the AppUser::useTable property with the 'users' table. +It's important to override the AppUser::useTable property with the ```users``` table. -You can override/extend all methods or properties like validation rules to suit your needs. +You can override/extend all methods or properties like validation rules to suit your needs. \ No newline at end of file diff --git a/Docs/Documentation/Features.md b/Docs/Documentation/Features.md new file mode 100644 index 000000000..756b6b8a9 --- /dev/null +++ b/Docs/Documentation/Features.md @@ -0,0 +1,16 @@ +Features +======== + +You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. + +The plugin itself is already capable of: + +* User registration (Enable by default) +* Account verification by a token sent via email +* User login (email / password) +* Password reset based on requesting a token by email and entering a new password +* User search (requires the CakeDC Search plugin) +* User management using the "admin" section (add / edit / delete) +* Simple roles management + +The default password reset process requires the user to enter his email address, an email is sent to the user with a link and a token. When the user accesses the URL with the token he can enter a new password. diff --git a/Docs/Documentation/How-To-Use-It.md b/Docs/Documentation/How-To-Use-It.md deleted file mode 100644 index b24c4cdb4..000000000 --- a/Docs/Documentation/How-To-Use-It.md +++ /dev/null @@ -1,51 +0,0 @@ -How to use it -============= - -You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. - -The plugin itself is already capable of: - -* User registration (Enable by default) -* Account verification by a token sent via email -* User login (email / password) -* Password reset based on requesting a token by email and entering a new password -* Simple profiles for users -* User search (requires the CakeDC Search plugin) -* User management using the "admin" section (add / edit / delete) -* Simple roles management - -The default password reset process requires the user to enter his email address, an email is sent to the user with a link and a token. When the user accesses the URL with the token he can enter a new password. - -Using the "remember me" functionality -------------------------------------- - -To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. - -```php -public $components = array( - 'Users.RememberMe' -); -``` - -If you are using another user model than 'User' you'll have to configure it: - - public $components = array( - 'Users.RememberMe' => array( - 'userModel' => 'AppUser'); - -And add this line - -```php -$this->RememberMe->restoreLoginFromCookie() -``` - -to your controllers beforeFilter() callack - -```php -public function beforeFilter() { - parent::beforeFilter(); - $this->RememberMe->restoreLoginFromCookie(); -} -``` - -The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 37394a419..062580fe5 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -1,16 +1,36 @@ Installation ============ -The plugin is pretty easy to set up, all you need to do is to copy it to you application plugins folder and load the needed tables. You can create database tables using either the schema shell or the [CakeDC Migrations plugin](http://github.com/CakeDC/migrations): +To install the plugin, place the files in a directory labelled "Users/" in your "app/Plugin/" directory. + +Git Submodule +------------- + +If you're using git for version control, you may want to add the **Users** plugin as a submodule on your repository. To do so, run the following command from the base of your repository: + +``` +git submodule add git@github.com:CakeDC/users.git app/Plugin/Users +``` + +After doing so, you will see the submodule in your changes pending, plus the file ".gitmodules". Simply commit and push to your repository. + +To initialize the submodule(s) run the following command: ``` -./Console/cake schema create users --plugin Users +git submodule update --init --recursive ``` -or +To retreive the latest updates to the plugin, assuming you're using the "master" branch, go to "app/Plugin/Users" and run the following command: ``` -./Console/cake Migrations.migration run all --plugin Users +git pull origin master ``` -You will also need the [CakeDC Search plugin](http://github.com/CakeDC/search), just grab it and put it into your application's plugin folder. \ No newline at end of file +If you're using another branch, just change "master" for the branch you are currently using. + +If any updates are added, go back to the base of your own repository, commit and push your changes. This will update your repository to point to the latest updates to the plugin. + +Composer +-------- + +The plugin also provides a "composer.json" file, to easily use the plugin through the Composer dependency manager. \ No newline at end of file diff --git a/Docs/Documentation/Remember-Me-Component.md b/Docs/Documentation/Remember-Me-Component.md new file mode 100644 index 000000000..b002f543a --- /dev/null +++ b/Docs/Documentation/Remember-Me-Component.md @@ -0,0 +1,37 @@ +Remember Me Component +===================== + +To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. + +```php +public $components = array( + 'Users.RememberMe' +); +``` + +If you are using another user model than ```User``` you'll have to configure it: + +```php + public $components = array( + 'Users.RememberMe' => array( + 'userModel' => 'AppUser' + ) + ); +``` + +And add this line + +```php +$this->RememberMe->restoreLoginFromCookie() +``` + +to your controllers beforeFilter() callack + +```php +public function beforeFilter() { + parent::beforeFilter(); + $this->RememberMe->restoreLoginFromCookie(); +} +``` + +The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. diff --git a/Docs/Documentation/Routing.md b/Docs/Documentation/Routing.md new file mode 100644 index 000000000..1958fc282 --- /dev/null +++ b/Docs/Documentation/Routing.md @@ -0,0 +1,26 @@ +Routing +======= + +To remove the second users from ```/users/users``` in the url you can use routes. + +The plugin itself comes with a routes file but you need to explicitly load them. + +```php +CakePlugin::load('Users', array('routes' => true)); +``` + +List of the used routes: + +```php +Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); +Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); +Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); +Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); +``` + +If you're extending the plugin remove the plugin from the route by setting it to null and replace the controller with your controller extending the plugins users controller. + +Feel free to change the routes here or add others as you need for your application. \ No newline at end of file diff --git a/Docs/Documentation/User-Details.md b/Docs/Documentation/User-Details.md index b98813683..117951288 100644 --- a/Docs/Documentation/User-Details.md +++ b/Docs/Documentation/User-Details.md @@ -1,9 +1,9 @@ -User Details -============ +User Details (Legacy) +===================== -The plugin contains an `user_details` table. This table is a key-value store and is not used by the plugin any more but kept for legacy apps. +The plugin contains an ```user_details``` table. This table is a key-value store and is not used by the plugin any more but kept for legacy apps. -If you want to use it you'll have to add the associations by extending the plugin or add your own profiles table which is recommend to use instead of a key-value store. +If you want to use it you'll have to add the associations by extending the plugin or add your own profiles table which is recommend to use instead of a key-value store. But be aware that this model is very like removed in future versions of the plugin. ```php class AppUser extends User { diff --git a/Docs/Home.md b/Docs/Home.md index 90a45d809..af6f0a000 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -20,6 +20,9 @@ Documentation * [Installation](Documentation/Installation.md) * [Configuration](Documentation/Configuration.md) -* [How to use it](Documentation/How-To-Use-It.md) +* [Routing](Documentation/Routing.md) +* [Features](Documentation/Features.md) * [User Details (Legacy)](Documentation/User-Details.md) +* [Events](Documentation/Events.md) +* [Remember Me Component](Documentation/Remember-Me-Component.md) * [Extending the Plugin](Documentation/Extending-The-Plugin.md) diff --git a/Model/User.php b/Model/User.php index fc042c7ea..31b1a6048 100755 --- a/Model/User.php +++ b/Model/User.php @@ -135,14 +135,15 @@ public function __construct($id = false, $table = null, $ds = null) { * @link https://github.com/CakeDC/utils */ protected function _setupBehaviors() { - if (class_exists('SearchableBehavior')) { + if (CakePlugin::loaded('Search') && class_exists('SearchableBehavior')) { $this->actsAs[] = 'Search.Searchable'; } - if (class_exists('SluggableBehavior') && Configure::read('Users.disableSlugs') !== true) { + if (CakePlugin::loaded('Utils') && class_exists('SluggableBehavior') && Configure::read('Users.disableSlugs') !== true) { $this->actsAs['Utils.Sluggable'] = array( 'label' => 'username', - 'method' => 'multibyteSlug'); + 'method' => 'multibyteSlug' + ); } } diff --git a/Test/Case/AllUsersTest.php b/Test/Case/AllUsersTest.php index a4ad671d4..4679b8111 100644 --- a/Test/Case/AllUsersTest.php +++ b/Test/Case/AllUsersTest.php @@ -17,17 +17,14 @@ class AllTagsPluginTest extends PHPUnit_Framework_TestSuite { * @return void */ public static function suite() { - $suite = new PHPUnit_Framework_TestSuite('All Users Plugin Tests'); + $Suite = new CakeTestSuite('All Comments Plugin tests'); $basePath = CakePlugin::path('Users') . DS . 'Test' . DS . 'Case' . DS; - - // controllers - $suite->addTestFile($basePath . 'Controller' . DS . 'UsersControllerTest.php'); - - // models - $suite->addTestFile($basePath . 'Model' . DS . 'UserTest.php'); - - return $suite; + $Suite->addTestDirectory($basePath . DS . 'Controller'); + $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component'); + $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component' . DS . 'Auth'); + $Suite->addTestDirectory($basePath . DS . 'Model'); + return $Suite; } } \ No newline at end of file diff --git a/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php b/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php index eb9415bd1..1ca0188e8 100644 --- a/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php +++ b/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php @@ -18,7 +18,7 @@ */ App::uses('ComponentCollection', 'Controller'); -App::uses('CookieAuthenticate', 'Authenticate.Controller/Component/Auth'); +App::uses('CookieAuthenticate', 'Users.Controller/Component/Auth'); App::uses('CookieComponent', 'Controller/Component'); App::uses('SessionComponent', 'Controller/Component'); App::uses('AppModel', 'Model'); @@ -33,7 +33,7 @@ */ class CookieAuthenticateTest extends CakeTestCase { - public $fixtures = array('plugin.authenticate.multi_user'); + public $fixtures = array('plugin.users.multi_user'); /** * setup diff --git a/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php b/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php index 9ffa17637..2097812de 100644 --- a/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php +++ b/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php @@ -18,7 +18,7 @@ */ App::uses('AuthComponent', 'Controller/Component'); -App::uses('MultiColumnAuthenticate', 'Authenticate.Controller/Component/Auth'); +App::uses('MultiColumnAuthenticate', 'Users.Controller/Component/Auth'); App::uses('AppModel', 'Model'); App::uses('CakeRequest', 'Network'); App::uses('CakeResponse', 'Network'); @@ -30,7 +30,7 @@ */ class MultiColumnAuthenticateTest extends CakeTestCase { - public $fixtures = array('plugin.authenticate.multi_user'); + public $fixtures = array('plugin.users.multi_user'); /** * setup diff --git a/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php b/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php index 8b992e258..3befe1282 100644 --- a/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php +++ b/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php @@ -18,7 +18,7 @@ */ App::uses('AuthComponent', 'Controller/Component'); -App::uses('TokenAuthenticate', 'Authenticate.Controller/Component/Auth'); +App::uses('TokenAuthenticate', 'Users.Controller/Component/Auth'); App::uses('AppModel', 'Model'); App::uses('CakeRequest', 'Network'); App::uses('CakeResponse', 'Network'); @@ -37,7 +37,7 @@ class TokenAuthenticateTest extends CakeTestCase { * @var array */ public $fixtures = array( - 'plugin.authenticate.multi_user' + 'plugin.users.multi_user' ); /** diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index de6b06944..db8333816 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -46,6 +46,7 @@ class UserTestCase extends CakeTestCase { * @return void */ public function setUp() { + parent::setUp(); Configure::write('App.UserClass', null); $this->User = ClassRegistry::init('Users.User'); } diff --git a/Test/Fixture/MultiUserFixture.php b/Test/Fixture/MultiUserFixture.php index 0c59ae023..230ecb2fe 100644 --- a/Test/Fixture/MultiUserFixture.php +++ b/Test/Fixture/MultiUserFixture.php @@ -34,6 +34,5 @@ class MultiUserFixture extends CakeTestFixture { array('user' => 'larry', 'email' => 'larry@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '34567', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31'), array('user' => 'garrett', 'email' => 'garrett@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '45678', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31'), array('user' => 'chartjes', 'email' => 'chartjes@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '56789', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31'), - ); } From 0be7a140a8849551d812caddc7d8b99255b1e634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 22 Jun 2014 23:07:47 +0200 Subject: [PATCH 0112/1476] Correcting .semver --- .semver | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.semver b/.semver index 8b186ad64..4b3e02978 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 2 -:minor: 2 +:minor: 1 :patch: 0 -:special: '' \ No newline at end of file +:special: '' From f4f07263544d48603caaca4ec60c17e90386a60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 23 Jun 2014 12:50:15 +0200 Subject: [PATCH 0113/1476] Fixing tests and working on the documentation --- Controller/Component/RememberMeComponent.php | 2 +- Controller/UsersController.php | 12 +++--- Docs/Documentation/Configuration.md | 13 +++++- Docs/Documentation/Extending-The-Plugin.md | 19 +++------ Docs/Documentation/Installation.md | 2 +- Model/User.php | 42 +++++++++++++------ .../Component/RememberMeComponentTest.php | 29 ++++++++----- Test/Case/Controller/UsersControllerTest.php | 21 +++++++--- Test/Case/Model/UserTest.php | 2 + 9 files changed, 93 insertions(+), 49 deletions(-) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 72af406b8..7971d6b62 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -36,7 +36,7 @@ class RememberMeComponent extends Component { * * @var CakeRequest */ - public $request; + public $request = null; /** * Settings diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 367def837..8c45de65c 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -65,7 +65,6 @@ class UsersController extends UsersAppController { 'Cookie', 'Paginator', 'Security', - 'Search.Prg', 'Users.RememberMe', ); @@ -284,10 +283,12 @@ public function edit() { * @return void */ public function admin_index() { - $this->Prg->commonProcess(); - unset($this->{$this->modelClass}->validate['username']); - unset($this->{$this->modelClass}->validate['email']); - $this->{$this->modelClass}->data[$this->modelClass] = $this->passedArgs; + if ($this->{$this->modelClass}->Behaviors->loaded('Searchable')) { + $this->Prg->commonProcess(); + unset($this->{$this->modelClass}->validate['username']); + unset($this->{$this->modelClass}->validate['email']); + $this->{$this->modelClass}->data[$this->modelClass] = $this->passedArgs; + } if ($this->{$this->modelClass}->Behaviors->loaded('Searchable')) { $parsedConditions = $this->{$this->modelClass}->parseCriteria($this->passedArgs); @@ -817,6 +818,7 @@ protected function _resetPassword($token) { if (empty($user)) { $this->Session->setFlash(__d('users', 'Invalid password reset token, try again.')); $this->redirect(array('action' => 'reset_password')); + return; } if (!empty($this->request->data) && $this->{$this->modelClass}->resetPassword(Hash::merge($user, $this->request->data))) { diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index fdb3ef5e6..eb8eadcda 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -28,10 +28,21 @@ The plugin uses the $default email configuration (should be present in your Conf Configure::write('Users.emailConfig', 'default'); ``` +Default Email Address +--------------------- + +To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php + +```php +Configure::write('App.defaultEmail', 'your@email.com'); +``` + +If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. + Roles Management ---------------- -You can add Users.roles on bootstrap.php file and these roles will be used on Admin Add / Edit pages. i.e: +You can add ```Users.roles``` in the ```bootstrap.php``` file and these roles will be used on Admin Add / Edit pages. i.e: ```php Configure::write('Users.roles', array('admin' => 'Admin', 'registered' => 'Registered')); diff --git a/Docs/Documentation/Extending-The-Plugin.md b/Docs/Documentation/Extending-The-Plugin.md index 8d5063f30..0a28dd40e 100644 --- a/Docs/Documentation/Extending-The-Plugin.md +++ b/Docs/Documentation/Extending-The-Plugin.md @@ -1,20 +1,10 @@ Extending the Plugin ==================== -### Changing the default "from" email setting ### - -To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php - -```php -Configure::write('App.defaultEmail', 'your@email.com'); -``` - -If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. - Extending the controller ------------------------ -Declare the controller class +Declare the controller class. It is important to set the ```$name``` property here to make sure the controller initializes everything correct. If not setting the name the name setting is inherited and won't match the new controllers name. ```php App::uses('UsersController', 'Users.Controller'); @@ -82,9 +72,10 @@ or you can use the configuration settings to disable it, for example in your ``` Configure::write('Users.disableDefaultAuth'); ``` -### Extending the model ### +Extending the model +------------------- -Declare the model +Declare the model. Same as in the controller, set the ```$name``` property and set the ```$useTable``` property to ```users```. ```php App::uses('User', 'Users.Model'); @@ -94,6 +85,6 @@ class AppUser extends User { } ``` -It's important to override the AppUser::useTable property with the ```users``` table. +It's important to override the AppUser::useTable property with the ```users``` table. It won't use the correct table otherwise. You can override/extend all methods or properties like validation rules to suit your needs. \ No newline at end of file diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 062580fe5..635866a2e 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -9,7 +9,7 @@ Git Submodule If you're using git for version control, you may want to add the **Users** plugin as a submodule on your repository. To do so, run the following command from the base of your repository: ``` -git submodule add git@github.com:CakeDC/users.git app/Plugin/Users +git submodule add git@github.com:CakeDC/migrations.git app/Plugin/Users ``` After doing so, you will see the submodule in your changes pending, plus the file ".gitmodules". Simply commit and push to your repository. diff --git a/Model/User.php b/Model/User.php index 31b1a6048..766bef3de 100755 --- a/Model/User.php +++ b/Model/User.php @@ -80,37 +80,51 @@ class User extends UsersAppModel { 'required' => array( 'rule' => array('notEmpty'), 'required' => true, 'allowEmpty' => false, - 'message' => 'Please enter a username.'), + 'message' => 'Please enter a username.' + ), 'alpha' => array( 'rule' => array('alphaNumeric'), - 'message' => 'The username must be alphanumeric.'), + 'message' => 'The username must be alphanumeric.' + ), 'unique_username' => array( 'rule' => array('isUnique', 'username'), - 'message' => 'This username is already in use.'), + 'message' => 'This username is already in use.' + ), 'username_min' => array( 'rule' => array('minLength', '3'), - 'message' => 'The username must have at least 3 characters.')), + 'message' => 'The username must have at least 3 characters.' + ) + ), 'email' => array( 'isValid' => array( 'rule' => 'email', 'required' => true, - 'message' => 'Please enter a valid email address.'), + 'message' => 'Please enter a valid email address.' + ), 'isUnique' => array( 'rule' => array('isUnique', 'email'), - 'message' => 'This email is already in use.')), + 'message' => 'This email is already in use.' + ) + ), 'password' => array( 'too_short' => array( 'rule' => array('minLength', '6'), - 'message' => 'The password must have at least 6 characters.'), + 'message' => 'The password must have at least 6 characters.' + ), 'required' => array( 'rule' => 'notEmpty', - 'message' => 'Please enter a password.')), + 'message' => 'Please enter a password.' + ) + ), 'temppassword' => array( 'rule' => 'confirmPassword', - 'message' => 'The passwords are not equal, please try again.'), + 'message' => 'The passwords are not equal, please try again.' + ), 'tos' => array( 'rule' => array('custom','[1]'), - 'message' => 'You must agree to the terms of use.')); + 'message' => 'You must agree to the terms of use.' + ) + ); /** * Constructor @@ -337,7 +351,10 @@ public function setUpResetPasswordValidationRules() { 'confirm_password' => array( 'required' => array( 'rule' => array('compareFields', 'new_password', 'confirm_password'), - 'message' => __d('users', 'The passwords are not equal.')))); + 'message' => __d('users', 'The passwords are not equal.') + ) + ) + ); } /** @@ -358,7 +375,8 @@ public function resetPassword($postData = array()) { $this->data[$this->alias]['password_token'] = null; $result = $this->save($this->data, array( 'validate' => false, - 'callbacks' => false)); + 'callbacks' => false) + ); } $this->validate = $tmp; diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php index daf0e63e1..15f04beac 100644 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -26,7 +26,8 @@ class RememberMeComponentTestController extends Controller { */ public $components = array( 'Users.RememberMe', - 'Auth'); + 'Auth' + ); } class RememberMeComponentTest extends CakeTestCase { @@ -45,10 +46,13 @@ class RememberMeComponentTest extends CakeTestCase { public $usersData = array( 'test' => array( 'email' => 'test@cakedc.com', - 'password' => 'test'), + 'password' => 'test' + ), 'admin' => array( 'email' => 'admin@cakedc.com', - 'password' => 'admin')); + 'password' => 'admin' + ) + ); /** * start @@ -58,7 +62,8 @@ class RememberMeComponentTest extends CakeTestCase { public function setUp() { $_COOKIE = array(); Configure::write('Config.language', 'eng'); - $this->Controller = new RememberMeComponentTestController(new CakeRequest(), new CakeResponse()); + $this->request = new CakeRequest(); + $this->Controller = new RememberMeComponentTestController($this->request, new CakeResponse()); $this->Controller->constructClasses(); $this->RememberMe = $this->Controller->RememberMe; @@ -68,6 +73,7 @@ public function setUp() { $this->RememberMe->Auth = $this->getMock('AuthComponent', array(), array($this->Controller->Components)); + $this->RememberMe->request = $this->request; } /** @@ -85,7 +91,9 @@ public function testSetCookie() { $this->RememberMe->setCookie(array( 'User' => array( 'email' => 'email', - 'password' => 'password'))); + 'password' => 'password') + ) + ); } /** @@ -94,7 +102,7 @@ public function testSetCookie() { * @return void */ public function testRestoreLoginFromCookie() { - $this->RememberMe->Cookie->expects($this->once()) + $this->RememberMe->Cookie->expects($this->any()) ->method('read') ->with($this->equalTo('rememberMe')) ->will($this->returnValue($this->usersData['admin'])); @@ -107,10 +115,11 @@ public function testRestoreLoginFromCookie() { $this->RememberMe->restoreLoginFromCookie(); - // even if we post "test" user, we have a remember me cookie set and will priorize the cookie over the post + // even if we post "test" user, we have a remember me cookie set and will prioritize the cookie over the post // NOTE we check if the user is logged in in the startup method of the Component $this->assertEquals($this->RememberMe->request->data, array( - 'User' => $this->usersData['admin'])); + 'User' => $this->usersData['admin'] + )); } /** @@ -122,7 +131,7 @@ public function testRestoreLoginFromCookie() { */ public function testRestoreLoginFromCookieIncorrectLogin() { // cookie will hold "admin" data, and post request will have "test" - $this->RememberMe->Cookie->expects($this->once()) + $this->RememberMe->Cookie->expects($this->any()) ->method('read') ->with($this->equalTo('rememberMe')) ->will($this->returnValue($this->usersData['admin'])); @@ -157,6 +166,6 @@ public function testDestroyCookie() { */ private function __setPostData($data = array()) { $_SERVER['REQUEST_METHOD'] = 'POST'; - $this->RememberMe->request->data = array_merge($data); + $this->RememberMe->request->data = $data; } } diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 1649b1469..90c34909a 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -58,7 +58,10 @@ public function beforeFilter() { $this->Auth->userScope = array( 'OR' => array( 'AND' => - array('User.active' => 1, 'User.email_verified' => 1))); + array('User.active' => 1, 'User.email_verified' => 1 + ) + ) + ); } /** @@ -205,7 +208,11 @@ public function setUp() { 'plugin' => 'users', 'url' => array()); - $this->Users->Prg = $this->getMock('Prg', array('commonProcess')); + if (CakePlugin::loaded('Search')) { + $this->Users->Prg = $this->getMock('PrgComponent', + array('commonProcess'), + array($this->Users->Components)); + } $this->Users->CakeEmail = $this->getMock('CakeEmail'); $this->Users->CakeEmail->expects($this->any()) @@ -479,15 +486,19 @@ public function testResetPassword() { $this->Users->User->saveField('email_token_expires', date('Y-m-d H:i:s', strtotime('+1 year'))); $this->Users->data = array( 'User' => array( - 'email' => 'adminuser@cakedc.com')); + 'email' => 'adminuser@cakedc.com' + ) + ); $this->Users->reset_password(); $this->assertEquals($this->Users->redirectUrl, array('action' => 'login')); $this->Users->data = array( 'User' => array( 'new_password' => 'newpassword', - 'confirm_password' => 'newpassword')); + 'confirm_password' => 'newpassword' + ) + ); $this->Users->reset_password('testtoken'); - $this->assertEquals($this->Users->redirectUrl, $this->Users->Auth->loginAction); + $this->assertEquals($this->Users->redirectUrl, array('action' => 'reset_password')); } /** diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index db8333816..38ac433db 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -471,6 +471,8 @@ public function testEditException() { * @return void */ public function testDisableSlugs() { + $this->skipIf(CakePlugin::loaded('Utils') === false, __('Utils plugin not present, test skipped.')); + ClassRegistry::flush(); $this->User = ClassRegistry::init('Users.User'); $this->User->create(); From aa5b58d06ed46fea90ad6b444d5fd17febce977c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 23 Jun 2014 12:55:47 +0200 Subject: [PATCH 0114/1476] Fixing the PrgComponent mock so that the plugin tests work until the fix for the 2nd arg of the PrgConstuctor appears in the master branch. --- Test/Case/Controller/UsersControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php index 90c34909a..144dec1c4 100644 --- a/Test/Case/Controller/UsersControllerTest.php +++ b/Test/Case/Controller/UsersControllerTest.php @@ -211,7 +211,7 @@ public function setUp() { if (CakePlugin::loaded('Search')) { $this->Users->Prg = $this->getMock('PrgComponent', array('commonProcess'), - array($this->Users->Components)); + array($this->Users->Components, array())); } $this->Users->CakeEmail = $this->getMock('CakeEmail'); From 5ffc69e3bd1ebd0c0d75a29ad9695fba3041a243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 23 Jun 2014 16:09:26 +0200 Subject: [PATCH 0115/1476] Working on the documentation --- .../Documentation/Auth-In-The-Users-Plugin.md | 39 +++++++++++++++++++ Docs/Documentation/Configuration.md | 16 +++++--- Docs/Documentation/Events.md | 4 +- Docs/Documentation/Extending-The-Plugin.md | 39 ++++--------------- Docs/Documentation/Routing.md | 14 ++++++- Docs/Home.md | 3 +- 6 files changed, 72 insertions(+), 43 deletions(-) create mode 100644 Docs/Documentation/Auth-In-The-Users-Plugin.md diff --git a/Docs/Documentation/Auth-In-The-Users-Plugin.md b/Docs/Documentation/Auth-In-The-Users-Plugin.md new file mode 100644 index 000000000..75d657726 --- /dev/null +++ b/Docs/Documentation/Auth-In-The-Users-Plugin.md @@ -0,0 +1,39 @@ +Auth In The Users Plugin +======================== + +The users plugin is made to work out of the box with some default settings. If you want to customize them or user your application level auth settings you'll have to do a few things that are explained in this document. + +Disable The Default Auth Settings +--------------------------------- + +In the case you want to user your customized auth settings of your application, for example declared in the AppController::beforeFilter() method, you'll have to disable the default auth of the users plugin. + +You can use the configuration settings to disable it, for example in your ```bootstrap.php``` + +```php +Configure::write('Users.disableDefaultAuth'); +``` + +Or when extending the UsersController simply overwrite the ```_setupAuth()``` method. + +```php +protected function _setupAuth() { +} +``` + +Overwriting the default auth settings +------------------------------------- + +If you want to change some of the default auth settings of the users controller overwrite the _setupAuth() method in the extending controller. + +```php +protected function _setupAuth() { + parent::_setupAuth(); + $this->Auth->loginRedirect = array( + 'plugin' => null, + 'admin' => false, + 'controller' => 'app_users', + 'action' => 'login' + ); +} +``` \ No newline at end of file diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index eb8eadcda..c5e5272f4 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -17,7 +17,11 @@ Disable Slugs If the Utils plugin is present the users model will auto attach and use the sluggable behavior. -To not create slugs for a new user records put this in your configuration: Configure::write('Users.disableSlugs', true); +If you don't want to create slugs for new users put this in your configuration: + +```php +Configure::write('Users.disableSlugs', true); +``` Email configuration ------------------- @@ -28,9 +32,6 @@ The plugin uses the $default email configuration (should be present in your Conf Configure::write('Users.emailConfig', 'default'); ``` -Default Email Address ---------------------- - To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php ```php @@ -45,7 +46,10 @@ Roles Management You can add ```Users.roles``` in the ```bootstrap.php``` file and these roles will be used on Admin Add / Edit pages. i.e: ```php -Configure::write('Users.roles', array('admin' => 'Admin', 'registered' => 'Registered')); +Configure::write('Users.roles', array( + 'admin' => 'Admin', + 'registered' => 'Registered' +)); ``` If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered role setting Users.defaultRole on bootstrap.php. i.e: @@ -85,7 +89,7 @@ Disables/enables the user registration. Users.roles ``` -Optional array of user roles if you need it. This is not activly used by the plugin by default. +Optional array of user roles if you need it. This is not actively used by the plugin by default. ``` Users.sendPassword diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index d8fcb06da..2969de294 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -3,13 +3,13 @@ Events If you're not familiar with events look them up in [the official documentation](http://book.cakephp.org/2.0/en/core-libraries/events.html). -Events follow these conventions: +Events follow these conventions ...: * Users.Controller.Users.someCallBack * Users.Model.User.someCallBack * ... -Triggered events are: +Events that are triggered in this plugin are: * Users.Controller.Users.beforeRegister * Users.Controller.Users.afterRegister diff --git a/Docs/Documentation/Extending-The-Plugin.md b/Docs/Documentation/Extending-The-Plugin.md index 0a28dd40e..041a9e2dc 100644 --- a/Docs/Documentation/Extending-The-Plugin.md +++ b/Docs/Documentation/Extending-The-Plugin.md @@ -23,7 +23,7 @@ public function beforeFilter() { } ``` -You can overwrite the render() method to fall back to the plugin views in the case you want to use some of them +You can overwrite the ```Controller::render()``` method to fall back to the plugin views in the case you want to use some of them ```php public function render($view = null, $layout = null) { @@ -42,36 +42,6 @@ public function render($view = null, $layout = null) { Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory -Overwriting the default auth settings -------------------------------------- - -To use the basics the plugin already offers but changing some of the settings overwrite the _setupAuth() method in the extending controller. - -```php -protected function _setupAuth() { - parent::_setupAuth(); - $this->Auth->loginRedirect = array( - 'plugin' => null, - 'admin' => false, - 'controller' => 'app_users', - 'action' => 'login' - ); -} -``` - -If you want to disable it simply overwrite it without any body - -```php -protected function _setupAuth() { -} -``` - -or you can use the configuration settings to disable it, for example in your ```bootstrap.php``` - -```php -Configure::write('Users.disableDefaultAuth'); -``` - Extending the model ------------------- @@ -87,4 +57,9 @@ class AppUser extends User { It's important to override the AppUser::useTable property with the ```users``` table. It won't use the correct table otherwise. -You can override/extend all methods or properties like validation rules to suit your needs. \ No newline at end of file +You can override/extend all methods or properties like validation rules to suit your needs. + +Routing to preserve the /users URL when extending the plugin +------------------------------------------------------------ + +See the [Routing](Routing.md) documentation. \ No newline at end of file diff --git a/Docs/Documentation/Routing.md b/Docs/Documentation/Routing.md index 1958fc282..7782817df 100644 --- a/Docs/Documentation/Routing.md +++ b/Docs/Documentation/Routing.md @@ -6,7 +6,9 @@ To remove the second users from ```/users/users``` in the url you can use routes The plugin itself comes with a routes file but you need to explicitly load them. ```php -CakePlugin::load('Users', array('routes' => true)); +CakePlugin::load('Users', array( + 'routes' => true +)); ``` List of the used routes: @@ -21,6 +23,14 @@ Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); ``` -If you're extending the plugin remove the plugin from the route by setting it to null and replace the controller with your controller extending the plugins users controller. +Changing the routes +------------------- + +If you're extending the plugin remove the plugin from the route by setting it to ```null``` and replace the controller with your controller extending the plugins users controller. + +```php +Router::connect('/users', array('plugin' => null, 'controller' => 'app_users')); +/* ... */ +``` Feel free to change the routes here or add others as you need for your application. \ No newline at end of file diff --git a/Docs/Home.md b/Docs/Home.md index af6f0a000..5c54d8053 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -18,10 +18,11 @@ Requirements Documentation ------------- +* [Features](Documentation/Features.md) * [Installation](Documentation/Installation.md) * [Configuration](Documentation/Configuration.md) * [Routing](Documentation/Routing.md) -* [Features](Documentation/Features.md) +* [Auth in the Users plugin](Documentation/Auth-In-The-Users-Plugin.md) * [User Details (Legacy)](Documentation/User-Details.md) * [Events](Documentation/Events.md) * [Remember Me Component](Documentation/Remember-Me-Component.md) From 71b921d756ece71b89ddd3b87cd7b1b7aa9cfd37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 23 Jun 2014 16:09:39 +0200 Subject: [PATCH 0116/1476] Adding the CHANGELOG.md data --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb..e8a46b909 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,28 @@ +Changelog +========= + +Release 2.1.0 +------------- + +https://github.com/CakeDC/migrations/tree/2.3.0 + + * [aa5b58d](https://github.com/CakeDC/users/commit/aa5b58d) Fixing the PrgComponent mock so that the plugin tests work until the fix for the 2nd arg of the PrgConstuctor appears in the master branch. + * [4b0b210](https://github.com/CakeDC/users/commit/4b0b210) Replacing Set with Hash + * [f9c07ec](https://github.com/CakeDC/users/commit/f9c07ec) Adding information about the legacy user details to the documentation + * [50f0597](https://github.com/CakeDC/users/commit/50f0597) Adding semver and CONTRIBUTING.md + * [a4e6a95](https://github.com/CakeDC/users/commit/a4e6a95) Fixing https://github.com/CakeDC/users/pull/174 + * [3a66dd2](https://github.com/CakeDC/users/commit/3a66dd2) Fixing some upper cased controller names in sidebar.ctp which causes the urls to not work + * [33b7029](https://github.com/CakeDC/users/commit/33b7029) Removed testTest + * [69b901e](https://github.com/CakeDC/users/commit/69b901e) Controller Test Fixed + * [aea36c3](https://github.com/CakeDC/users/commit/aea36c3) Fix testEditPassword + * [c07e7c6](https://github.com/CakeDC/users/commit/c07e7c6) Updated deprecated assertEqual + * [f53b19c](https://github.com/CakeDC/users/commit/f53b19c) User password edit / unit tests + * [b63001b](https://github.com/CakeDC/users/commit/b63001b) Redundant Cookie::destroy() + * [eea58c1](https://github.com/CakeDC/users/commit/eea58c1) Added missing dependency (Utils Plugin) + * [7e273f1](https://github.com/CakeDC/users/commit/7e273f1) File linting and function docs + * [4c08b47](https://github.com/CakeDC/users/commit/4c08b47) Changed portuguese translation path and fixed some strings + * [3caf6db](https://github.com/CakeDC/users/commit/3caf6db) Fixed some linting issues. + * [f93ce41](https://github.com/CakeDC/users/commit/f93ce41) Minor improvement to the flash message that shows the username in the UsersController.php + * [b6ee0ad](https://github.com/CakeDC/users/commit/b6ee0ad) Refs https://github.com/CakeDC/users/issues/145, fixing the links in the sidebar when not used from the plugin + * [720ebb5](https://github.com/CakeDC/users/commit/720ebb5) Refs https://github.com/CakeDC/users/pull/146 + * [46d6321](https://github.com/CakeDC/users/commit/46d6321) Renamed locale fre => fra, since 2.3 CakePHP uses ISO standard. \ No newline at end of file From 09e1e3cbecaf482f3dd74e7ff0d51b4022804b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 23 Jun 2014 16:48:37 +0200 Subject: [PATCH 0117/1476] Minor documentation changes --- Docs/Documentation/Auth-In-The-Users-Plugin.md | 4 ++-- Docs/Documentation/Extending-The-Plugin.md | 4 ++-- Docs/Documentation/Remember-Me-Component.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Docs/Documentation/Auth-In-The-Users-Plugin.md b/Docs/Documentation/Auth-In-The-Users-Plugin.md index 75d657726..2cb1ceb6c 100644 --- a/Docs/Documentation/Auth-In-The-Users-Plugin.md +++ b/Docs/Documentation/Auth-In-The-Users-Plugin.md @@ -6,7 +6,7 @@ The users plugin is made to work out of the box with some default settings. If y Disable The Default Auth Settings --------------------------------- -In the case you want to user your customized auth settings of your application, for example declared in the AppController::beforeFilter() method, you'll have to disable the default auth of the users plugin. +In the case you want to user your customized auth settings of your application, for example declared in the ```AppController::beforeFilter()``` method, you'll have to disable the default auth of the users plugin. You can use the configuration settings to disable it, for example in your ```bootstrap.php``` @@ -24,7 +24,7 @@ protected function _setupAuth() { Overwriting the default auth settings ------------------------------------- -If you want to change some of the default auth settings of the users controller overwrite the _setupAuth() method in the extending controller. +If you want to change some of the default auth settings of the users controller overwrite the ```_setupAuth()``` method in the extending controller. ```php protected function _setupAuth() { diff --git a/Docs/Documentation/Extending-The-Plugin.md b/Docs/Documentation/Extending-The-Plugin.md index 041a9e2dc..ab62128f1 100644 --- a/Docs/Documentation/Extending-The-Plugin.md +++ b/Docs/Documentation/Extending-The-Plugin.md @@ -55,9 +55,9 @@ class AppUser extends User { } ``` -It's important to override the AppUser::useTable property with the ```users``` table. It won't use the correct table otherwise. +It's important to override the ```AppUser::$useTable``` property with the ```users``` table. It won't use the correct table otherwise. -You can override/extend all methods or properties like validation rules to suit your needs. +You can override / extend all methods or properties like validation rules to suit your needs. Routing to preserve the /users URL when extending the plugin ------------------------------------------------------------ diff --git a/Docs/Documentation/Remember-Me-Component.md b/Docs/Documentation/Remember-Me-Component.md index b002f543a..5a1352dd9 100644 --- a/Docs/Documentation/Remember-Me-Component.md +++ b/Docs/Documentation/Remember-Me-Component.md @@ -22,10 +22,10 @@ If you are using another user model than ```User``` you'll have to configure it: And add this line ```php -$this->RememberMe->restoreLoginFromCookie() +$this->RememberMe->restoreLoginFromCookie(); ``` -to your controllers beforeFilter() callack +to your controllers ```beforeFilter()``` callback ```php public function beforeFilter() { From 8a4f144571cab8bca35aa0175430f45c842d9b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 7 Jul 2014 11:59:01 +0200 Subject: [PATCH 0118/1476] Updating CHANGELOG.md --- CHANGELOG.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8a46b909..1fbfebc42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,24 +4,27 @@ Changelog Release 2.1.0 ------------- -https://github.com/CakeDC/migrations/tree/2.3.0 - * [aa5b58d](https://github.com/CakeDC/users/commit/aa5b58d) Fixing the PrgComponent mock so that the plugin tests work until the fix for the 2nd arg of the PrgConstuctor appears in the master branch. + * [f4f0726](https://github.com/CakeDC/users/commit/f4f0726) Fixing tests and working on the documentation * [4b0b210](https://github.com/CakeDC/users/commit/4b0b210) Replacing Set with Hash * [f9c07ec](https://github.com/CakeDC/users/commit/f9c07ec) Adding information about the legacy user details to the documentation * [50f0597](https://github.com/CakeDC/users/commit/50f0597) Adding semver and CONTRIBUTING.md * [a4e6a95](https://github.com/CakeDC/users/commit/a4e6a95) Fixing https://github.com/CakeDC/users/pull/174 * [3a66dd2](https://github.com/CakeDC/users/commit/3a66dd2) Fixing some upper cased controller names in sidebar.ctp which causes the urls to not work + * [29537ad](https://github.com/CakeDC/users/commit/29537ad) Changing .travis and updating composer.json + * [effa068](https://github.com/CakeDC/users/commit/effa068) Fixing typo in error message + * [835a2a5](https://github.com/CakeDC/users/commit/835a2a5) Fixing missing ' in the readme.md * [33b7029](https://github.com/CakeDC/users/commit/33b7029) Removed testTest * [69b901e](https://github.com/CakeDC/users/commit/69b901e) Controller Test Fixed * [aea36c3](https://github.com/CakeDC/users/commit/aea36c3) Fix testEditPassword * [c07e7c6](https://github.com/CakeDC/users/commit/c07e7c6) Updated deprecated assertEqual + * [c62aa19](https://github.com/CakeDC/users/commit/c62aa19) Formatting fixes * [f53b19c](https://github.com/CakeDC/users/commit/f53b19c) User password edit / unit tests * [b63001b](https://github.com/CakeDC/users/commit/b63001b) Redundant Cookie::destroy() * [eea58c1](https://github.com/CakeDC/users/commit/eea58c1) Added missing dependency (Utils Plugin) - * [7e273f1](https://github.com/CakeDC/users/commit/7e273f1) File linting and function docs * [4c08b47](https://github.com/CakeDC/users/commit/4c08b47) Changed portuguese translation path and fixed some strings - * [3caf6db](https://github.com/CakeDC/users/commit/3caf6db) Fixed some linting issues. + * [3caf6db](https://github.com/CakeDC/users/commit/3caf6db) Fixed some linting issues + * [226e3a4](https://github.com/CakeDC/users/commit/226e3a4) Code typos in readme * [f93ce41](https://github.com/CakeDC/users/commit/f93ce41) Minor improvement to the flash message that shows the username in the UsersController.php * [b6ee0ad](https://github.com/CakeDC/users/commit/b6ee0ad) Refs https://github.com/CakeDC/users/issues/145, fixing the links in the sidebar when not used from the plugin * [720ebb5](https://github.com/CakeDC/users/commit/720ebb5) Refs https://github.com/CakeDC/users/pull/146 From 31d67a13997d096375b2863482fa2b57918a41c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 00:17:00 +0200 Subject: [PATCH 0119/1476] Updating the copyright year --- Config/Migration/001_initialize_users_schema.php | 4 ++-- Config/Migration/002_renaming.php | 4 ++-- Config/Migration/map.php | 4 ++-- Config/Schema/schema.php | 4 ++-- Controller/Component/RememberMeComponent.php | 4 ++-- Controller/UsersAppController.php | 4 ++-- Controller/UsersController.php | 4 ++-- Model/User.php | 4 ++-- Model/UsersAppModel.php | 4 ++-- Test/Case/AllUsersTest.php | 4 ++-- Test/Case/Controller/Component/RememberMeComponentTest.php | 4 ++-- Test/Case/Controller/UsersControllerTest.php | 4 ++-- Test/Case/Model/UserTest.php | 4 ++-- Test/Fixture/UserFixture.php | 4 ++-- View/Elements/pagination.ctp | 4 ++-- View/Emails/text/account_verification.ctp | 4 ++-- View/Emails/text/new_password.ctp | 4 ++-- View/Emails/text/password_reset_request.ctp | 4 ++-- View/Users/add.ctp | 4 ++-- View/Users/admin_add.ctp | 4 ++-- View/Users/admin_edit.ctp | 4 ++-- View/Users/admin_index.ctp | 4 ++-- View/Users/admin_view.ctp | 4 ++-- View/Users/change_password.ctp | 4 ++-- View/Users/dashboard.ctp | 4 ++-- View/Users/edit.ctp | 4 ++-- View/Users/index.ctp | 4 ++-- View/Users/login.ctp | 4 ++-- View/Users/request_password_change.ctp | 4 ++-- View/Users/resend_verification.ctp | 4 ++-- View/Users/search.ctp | 4 ++-- View/Users/view.ctp | 4 ++-- 32 files changed, 64 insertions(+), 64 deletions(-) diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php index db36cd21c..2fc9753db 100644 --- a/Config/Migration/001_initialize_users_schema.php +++ b/Config/Migration/001_initialize_users_schema.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2013, Cake Development Corporation + * Copyright 2010 - 2014, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2013, Cake Development Corporation + * @Copyright 2010 - 2014, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.migrations * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Config/Migration/002_renaming.php b/Config/Migration/002_renaming.php index d9874316b..4b116a71c 100644 --- a/Config/Migration/002_renaming.php +++ b/Config/Migration/002_renaming.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2013, Cake Development Corporation + * Copyright 2010 - 2014, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2013, Cake Development Corporation + * @Copyright 2010 - 2014, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.migrations * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Config/Migration/map.php b/Config/Migration/map.php index 5d69f5f89..8281b4d9e 100644 --- a/Config/Migration/map.php +++ b/Config/Migration/map.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2013, Cake Development Corporation + * Copyright 2010 - 2014, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2013, Cake Development Corporation + * @Copyright 2010 - 2014, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.migrations * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php index 6bbacbd0e..2d8643536 100644 --- a/Config/Schema/schema.php +++ b/Config/Schema/schema.php @@ -2,14 +2,14 @@ /** * Users CakePHP Plugin * - * Copyright 2010 - 2013, Cake Development Corporation + * Copyright 2010 - 2014, Cake Development Corporation * 1785 E. Sahara Avenue, Suite 490-423 * Las Vegas, Nevada 89104 * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * - * @Copyright 2010 - 2013, Cake Development Corporation + * @Copyright 2010 - 2014, Cake Development Corporation * @link http://github.com/CakeDC/users * @package plugins.users.config.schema * @license MIT License (http://www.opensource.org/licenses/mit-license.php) diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php index 7971d6b62..fdd2a7dc1 100644 --- a/Controller/Component/RememberMeComponent.php +++ b/Controller/Component/RememberMeComponent.php @@ -1,11 +1,11 @@ diff --git a/View/Emails/text/account_verification.ctp b/View/Emails/text/account_verification.ctp index 611eb687d..e884215e5 100644 --- a/View/Emails/text/account_verification.ctp +++ b/View/Emails/text/account_verification.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_add.ctp b/View/Users/admin_add.ctp index 1e8a2945c..8b0efff4e 100644 --- a/View/Users/admin_add.ctp +++ b/View/Users/admin_add.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_edit.ctp b/View/Users/admin_edit.ctp index 7c4b85f89..94efcc98c 100644 --- a/View/Users/admin_edit.ctp +++ b/View/Users/admin_edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index 30ef0e74e..0b408492e 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/admin_view.ctp b/View/Users/admin_view.ctp index 5c37c8d2f..8960a41ba 100644 --- a/View/Users/admin_view.ctp +++ b/View/Users/admin_view.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/change_password.ctp b/View/Users/change_password.ctp index 7dcaf378f..3817a0532 100644 --- a/View/Users/change_password.ctp +++ b/View/Users/change_password.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/dashboard.ctp b/View/Users/dashboard.ctp index f510421a6..41cccf50b 100644 --- a/View/Users/dashboard.ctp +++ b/View/Users/dashboard.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/edit.ctp b/View/Users/edit.ctp index 4cfbcbf5d..93b87479e 100644 --- a/View/Users/edit.ctp +++ b/View/Users/edit.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/index.ctp b/View/Users/index.ctp index ee04d2ae9..82116ca27 100644 --- a/View/Users/index.ctp +++ b/View/Users/index.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/login.ctp b/View/Users/login.ctp index 08c73cb29..ff35d908c 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/request_password_change.ctp b/View/Users/request_password_change.ctp index 4c566d1b2..a62b0a3d2 100644 --- a/View/Users/request_password_change.ctp +++ b/View/Users/request_password_change.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/resend_verification.ctp b/View/Users/resend_verification.ctp index e48925de7..cfa55f022 100644 --- a/View/Users/resend_verification.ctp +++ b/View/Users/resend_verification.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/search.ctp b/View/Users/search.ctp index 552d88f9e..4e10d788e 100644 --- a/View/Users/search.ctp +++ b/View/Users/search.ctp @@ -1,11 +1,11 @@ diff --git a/View/Users/view.ctp b/View/Users/view.ctp index 85f92d86c..c80f27152 100644 --- a/View/Users/view.ctp +++ b/View/Users/view.ctp @@ -1,11 +1,11 @@ From aa27ba6f9a60666cb1a81329e462c551d113cd2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 00:32:05 +0200 Subject: [PATCH 0120/1476] Working on the documentation, some CS fixes --- CHANGELOG.md | 2 + .../Migration/001_initialize_users_schema.php | 59 ++++++++++--------- .../Documentation/Auth-In-The-Users-Plugin.md | 2 +- Docs/Documentation/Configuration.md | 2 +- Docs/Documentation/Events.md | 4 +- Docs/Documentation/Features.md | 4 +- Docs/Home.md | 4 +- README.md | 4 +- composer.json | 20 +++++-- 9 files changed, 58 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fbfebc42..5818e418f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Changelog Release 2.1.0 ------------- +https://github.com/CakeDC/users/tree/2.1.0 + * [aa5b58d](https://github.com/CakeDC/users/commit/aa5b58d) Fixing the PrgComponent mock so that the plugin tests work until the fix for the 2nd arg of the PrgConstuctor appears in the master branch. * [f4f0726](https://github.com/CakeDC/users/commit/f4f0726) Fixing tests and working on the documentation * [4b0b210](https://github.com/CakeDC/users/commit/4b0b210) Replacing Set with Hash diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php index 2fc9753db..f90c981af 100644 --- a/Config/Migration/001_initialize_users_schema.php +++ b/Config/Migration/001_initialize_users_schema.php @@ -32,38 +32,39 @@ class M49c3417a54874a9d276811502cedc421 extends CakeMigration { 'up' => array( 'create_table' => array( 'user_details' => array( - 'id' => array('type'=>'string', 'null' => false, 'default' => NULL, 'length' => 36, 'key' => 'primary'), - 'user_id' => array('type'=>'string', 'null' => false, 'default' => NULL, 'length' => 36), - 'position' => array('type'=>'float', 'null' => false, 'default' => '1', 'length' => 4), - 'field' => array('type'=>'string', 'null' => false, 'default' => NULL, 'key' => 'index', 'length' => 60), - 'value' => array('type'=>'text', 'null' => true, 'default' => NULL), - 'input' => array('type'=>'string', 'null' => false, 'default' => NULL, 'length' => 16), - 'data_type' => array('type'=>'string', 'null' => false, 'default' => NULL, 'length' => 16), - 'label' => array('type'=>'string', 'null' => false, 'default' => '', 'length' => 128), - 'created' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'modified' => array('type'=>'datetime', 'null' => true, 'default' => NULL), + 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), + 'user_id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36), + 'position' => array('type' => 'float', 'null' => false, 'default' => '1', 'length' => 4), + 'field' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'length' => 60), + 'value' => array('type' => 'text', 'null' => true, 'default' => null), + 'input' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), + 'data_type' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), + 'label' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => 128), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1), - 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1)) + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1) + ) ), 'users' => array( - 'id' => array('type'=>'string', 'null' => false, 'default' => NULL, 'length' => 36, 'key' => 'primary'), - 'username' => array('type'=>'string', 'null' => false, 'default' => NULL), - 'slug' => array('type'=>'string', 'null' => false, 'default' => NULL), - 'password' => array('type'=>'string', 'null' => true, 'default' => NULL, 'length' => 128), - 'password_token' => array('type'=>'string', 'null' => true, 'default' => NULL, 'length' => 128), - 'email' => array('type'=>'string', 'null' => true, 'default' => NULL), - 'email_verified' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'email_token' => array('type'=>'string', 'null' => true, 'default' => NULL), - 'email_token_expiry' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'tos' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'active' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'last_login' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'last_action' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'is_admin' => array('type'=>'boolean', 'null' => true, 'default' => '0'), - 'role' => array('type'=>'string', 'null' => true, 'default' => NULL), - 'created' => array('type'=>'datetime', 'null' => true, 'default' => NULL), - 'modified' => array('type'=>'datetime', 'null' => true, 'default' => NULL), + 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), + 'username' => array('type' => 'string', 'null' => false, 'default' => null), + 'slug' => array('type' => 'string', 'null' => false, 'default' => null), + 'password' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), + 'password_token' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), + 'email' => array('type' => 'string', 'null' => true, 'default' => null), + 'email_verified' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'email_token' => array('type' => 'string', 'null' => true, 'default' => null), + 'email_token_expiry' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'tos' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'active' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'last_login' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'last_action' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'is_admin' => array('type' => 'boolean', 'null' => true, 'default' => '0'), + 'role' => array('type' => 'string', 'null' => true, 'default' => null), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'BY_USERNAME' => array('column' => array('username'), 'unique' => 0), diff --git a/Docs/Documentation/Auth-In-The-Users-Plugin.md b/Docs/Documentation/Auth-In-The-Users-Plugin.md index 2cb1ceb6c..f88afcb23 100644 --- a/Docs/Documentation/Auth-In-The-Users-Plugin.md +++ b/Docs/Documentation/Auth-In-The-Users-Plugin.md @@ -1,4 +1,4 @@ -Auth In The Users Plugin +Auth in the Users Plugin ======================== The users plugin is made to work out of the box with some default settings. If you want to customize them or user your application level auth settings you'll have to do a few things that are explained in this document. diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index c5e5272f4..22b05ec20 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -52,7 +52,7 @@ Configure::write('Users.roles', array( )); ``` -If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered role setting Users.defaultRole on bootstrap.php. i.e: +If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered' role setting Users.defaultRole on bootstrap.php. i.e: ```php Configure::write('Users.defaultRole', 'user_registered'); diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index 2969de294..5107404ba 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -1,9 +1,9 @@ Events ====== -If you're not familiar with events look them up in [the official documentation](http://book.cakephp.org/2.0/en/core-libraries/events.html). +If you're not familiar with events please look them up in [the official documentation](http://book.cakephp.org/2.0/en/core-libraries/events.html). -Events follow these conventions ...: +The events in this plugin follow these conventions ...: * Users.Controller.Users.someCallBack * Users.Model.User.someCallBack diff --git a/Docs/Documentation/Features.md b/Docs/Documentation/Features.md index 756b6b8a9..4b7164bbc 100644 --- a/Docs/Documentation/Features.md +++ b/Docs/Documentation/Features.md @@ -1,4 +1,4 @@ -Features +Overview ======== You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. @@ -9,7 +9,7 @@ The plugin itself is already capable of: * Account verification by a token sent via email * User login (email / password) * Password reset based on requesting a token by email and entering a new password -* User search (requires the CakeDC Search plugin) +* User search (requires the [CakeDC Search](http://github.com/CakeDC/search) plugin) * User management using the "admin" section (add / edit / delete) * Simple roles management diff --git a/Docs/Home.md b/Docs/Home.md index 5c54d8053..25d52771c 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -12,8 +12,8 @@ Requirements * CakePHP 2.5+ * PHP 5.2.8+ -* [CakeDC Utils plugin](http://github.com/CakeDC/utils) -* [CakeDC Search plugin](http://github.com/CakeDC/search) +* [CakeDC Utils plugin](http://github.com/CakeDC/utils) (Optional but recommended) +* [CakeDC Search plugin](http://github.com/CakeDC/search) (Optional but recommended) Documentation ------------- diff --git a/README.md b/README.md index 77cb5c01e..84c5e08fe 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ Requirements * CakePHP 2.5+ * PHP 5.2.8+ -* [CakeDC Utils plugin](http://github.com/CakeDC/utils) -* [CakeDC Search plugin](http://github.com/CakeDC/search) +* [CakeDC Utils plugin](http://github.com/CakeDC/utils) (Optional but recommended) +* [CakeDC Search plugin](http://github.com/CakeDC/search) (Optional but recommended) Documentation ------------- diff --git a/composer.json b/composer.json index 07ce3d564..883464c4c 100644 --- a/composer.json +++ b/composer.json @@ -1,20 +1,32 @@ { "name": "cakedc/users", - "type": "cakephp-plugin", "description": "Users Plugin for CakePHP", + "type": "cakephp-plugin", "keywords": ["cakephp","users","auth"], "homepage": "http://cakedc.com", "license": "MIT", "authors": [ { "name": "Cake Development Corporation", + "email": "team@cakedc.com", "homepage": "http://cakedc.com" } ], + "support": { + "email": "team@cakedc.com", + "issues": "https://github.com/CakeDC/migrations/issues", + "forum": "http://stackoverflow.com/tags/cakedc", + "wiki": "https://github.com/CakeDC/migrations/blob/master/Docs/Home.md", + "irc": "irc://irc.freenode.org/cakephp", + "source": "https://github.com/CakeDC/migrations" + }, "require": { - "composer/installers": "*", - "cakedc/search": "*", - "cakedc/utils": "*" + "php": ">=5.2.8", + "composer/installers": "*" + }, + "suggest": { + "cakedc/search": "Search functionality for the admin.", + "cakedc/utils": "If you want to generate slugs based on the username." }, "extra": { "installer-name": "Users" From 5a847623ac9a4f4c451a78ceb11662d033435b4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 7 Jul 2014 18:36:14 -0400 Subject: [PATCH 0121/1476] Renaming some documentation files --- .../{Auth-In-The-Users-Plugin.md => Auth-in-the-Users-Plugin.md} | 0 .../{Extending-The-Plugin.md => Extending-the-Plugin.md} | 0 Docs/Documentation/{Features.md => Overview.md} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Docs/Documentation/{Auth-In-The-Users-Plugin.md => Auth-in-the-Users-Plugin.md} (100%) rename Docs/Documentation/{Extending-The-Plugin.md => Extending-the-Plugin.md} (100%) rename Docs/Documentation/{Features.md => Overview.md} (100%) diff --git a/Docs/Documentation/Auth-In-The-Users-Plugin.md b/Docs/Documentation/Auth-in-the-Users-Plugin.md similarity index 100% rename from Docs/Documentation/Auth-In-The-Users-Plugin.md rename to Docs/Documentation/Auth-in-the-Users-Plugin.md diff --git a/Docs/Documentation/Extending-The-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md similarity index 100% rename from Docs/Documentation/Extending-The-Plugin.md rename to Docs/Documentation/Extending-the-Plugin.md diff --git a/Docs/Documentation/Features.md b/Docs/Documentation/Overview.md similarity index 100% rename from Docs/Documentation/Features.md rename to Docs/Documentation/Overview.md From 62eeb869ce4641159f1c8b9855ca18e40c7a1e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 00:37:49 +0200 Subject: [PATCH 0122/1476] Updating documentation to reflect the renamed files. --- Docs/Home.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Docs/Home.md b/Docs/Home.md index 25d52771c..ca146c92a 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -18,12 +18,12 @@ Requirements Documentation ------------- -* [Features](Documentation/Features.md) +* [Overview](Documentation/Overview.md) * [Installation](Documentation/Installation.md) * [Configuration](Documentation/Configuration.md) * [Routing](Documentation/Routing.md) -* [Auth in the Users plugin](Documentation/Auth-In-The-Users-Plugin.md) +* [Auth in the Users Plugin](Documentation/Auth-in-the-Users-Plugin.md) * [User Details (Legacy)](Documentation/User-Details.md) * [Events](Documentation/Events.md) * [Remember Me Component](Documentation/Remember-Me-Component.md) -* [Extending the Plugin](Documentation/Extending-The-Plugin.md) +* [Extending the Plugin](Documentation/Extending-the-Plugin.md) From f3ef99504bd2a3e9f50584b560231daba1c9db1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 00:46:16 +0200 Subject: [PATCH 0123/1476] Working on the documentation --- Docs/Documentation/Configuration.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 22b05ec20..195238470 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -43,7 +43,7 @@ If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from ema Roles Management ---------------- -You can add ```Users.roles``` in the ```bootstrap.php``` file and these roles will be used on Admin Add / Edit pages. i.e: +You can add `Users.roles` in `app/Config/bootstrap.php` file and these roles will be used on Admin Add / Edit pages. i.e: ```php Configure::write('Users.roles', array( @@ -52,7 +52,7 @@ Configure::write('Users.roles', array( )); ``` -If you don't specify roles it will use 'admin' role (if is_admin is checked) or 'registered' role otherwise. You can override 'registered' role setting Users.defaultRole on bootstrap.php. i.e: +If you don't specify roles it will use 'admin' role (if `is_admin` is checked) or 'registered' role otherwise. You can override 'registered' role setting Users.defaultRole in `app/Config/bootstrap.php`. i.e: ```php Configure::write('Users.defaultRole', 'user_registered'); @@ -61,7 +61,7 @@ Configure::write('Users.defaultRole', 'user_registered'); Enabling / Disabling Registration --------------------------------- -Some application won't need to have registration enable so you can define ```Users.allowRegistration``` in ```bootstrap.php``` to enable or disable registration. By default registration will be enabled. +Some application won't need to have registration enable so you can define `Users.allowRegistration` in `app/Config/bootstrap.php` to enable or disable registration. By default registration will be enabled. ``` // Disables the registration @@ -77,7 +77,7 @@ The configuration settings can be written by using the Configure class. Users.disableDefaultAuth ``` -Disables/enables the default auth setup that is implemented in the plugins UsersController::_setupAuth() +Disables/enables the default auth setup that is implemented in the plugins `UsersController::_setupAuth()`. ``` Users.allowRegistration @@ -95,7 +95,7 @@ Optional array of user roles if you need it. This is not actively used by the pl Users.sendPassword ``` -Disables/enables the password reset functionality +Disables/enables the password reset functionality. ``` Users.emailConfig From 9e208bb24b63e5d9d6f09d2655cf3164d241ae21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 00:58:10 +0200 Subject: [PATCH 0124/1476] Updating composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 883464c4c..1e3049c06 100644 --- a/composer.json +++ b/composer.json @@ -14,9 +14,9 @@ ], "support": { "email": "team@cakedc.com", - "issues": "https://github.com/CakeDC/migrations/issues", + "issues": "https://github.com/CakeDC/users/issues", "forum": "http://stackoverflow.com/tags/cakedc", - "wiki": "https://github.com/CakeDC/migrations/blob/master/Docs/Home.md", + "wiki": "https://github.com/CakeDC/users/blob/master/Docs/Home.md", "irc": "irc://irc.freenode.org/cakephp", "source": "https://github.com/CakeDC/migrations" }, From edeb9614ff368cb5cde877a2a58420a10ea46b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 00:59:16 +0200 Subject: [PATCH 0125/1476] Fixing the copyright year in LICENSE.txt --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 011c22241..e6bdcdf69 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License -Copyright 2009-2013 +Copyright 2009-2014 Cake Development Corporation 1785 E. Sahara Avenue, Suite 490-423 Las Vegas, Nevada 89104 From 533cd710709bb57d9d219814260fc86fc9caf20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 01:03:40 +0200 Subject: [PATCH 0126/1476] Updating composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1e3049c06..994be689f 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "forum": "http://stackoverflow.com/tags/cakedc", "wiki": "https://github.com/CakeDC/users/blob/master/Docs/Home.md", "irc": "irc://irc.freenode.org/cakephp", - "source": "https://github.com/CakeDC/migrations" + "source": "https://github.com/CakeDC/users" }, "require": { "php": ">=5.2.8", From c1c951bebcad523b550610f6d932acd917f510f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 01:22:37 +0200 Subject: [PATCH 0127/1476] CS fixes to schema.php --- Config/Schema/schema.php | 64 ++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php index 2d8643536..827c14344 100644 --- a/Config/Schema/schema.php +++ b/Config/Schema/schema.php @@ -15,46 +15,54 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ class usersSchema extends CakeSchema { - var $name = 'users'; - function before($event = array()) { + public $name = 'users'; + + public function before($event = array()) { return true; } - function after($event = array()) { + public function after($event = array()) { } - var $user_details = array( - 'id' => array('type' => 'string', 'null' => false, 'default' => NULL, 'length' => 36, 'key' => 'primary'), - 'user_id' => array('type' => 'string', 'null' => false, 'default' => NULL, 'length' => 36), + public $user_details = array( + 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), + 'user_id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36), 'position' => array('type' => 'float', 'null' => false, 'default' => '1'), - 'field' => array('type' => 'string', 'null' => false, 'default' => NULL, 'key' => 'index'), - 'value' => array('type' => 'text', 'null' => true, 'default' => NULL), - 'input' => array('type' => 'string', 'null' => false, 'default' => NULL, 'length' => 16), - 'data_type' => array('type' => 'string', 'null' => false, 'default' => NULL, 'length' => 16), + 'field' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index'), + 'value' => array('type' => 'text', 'null' => true, 'default' => null), + 'input' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), + 'data_type' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), 'label' => array('type' => 'string', 'null' => false, 'length' => 128), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => NULL), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => NULL), - 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1)) + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), + 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1) + ) ); - var $users = array( - 'id' => array('type' => 'string', 'null' => false, 'default' => NULL, 'length' => 36, 'key' => 'primary'), - 'username' => array('type' => 'string', 'null' => false, 'default' => NULL, 'key' => 'index'), - 'slug' => array('type' => 'string', 'null' => false, 'default' => NULL), - 'password' => array('type' => 'string', 'null' => true, 'default' => NULL, 'length' => 128), - 'password_token' => array('type' => 'string', 'null' => true, 'default' => NULL, 'length' => 128), - 'email' => array('type' => 'string', 'null' => true, 'default' => NULL, 'key' => 'index'), + + public $users = array( + 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), + 'username' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index'), + 'slug' => array('type' => 'string', 'null' => false, 'default' => null), + 'password' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), + 'password_token' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), + 'email' => array('type' => 'string', 'null' => true, 'default' => null, 'key' => 'index'), 'email_verified' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'email_token' => array('type' => 'string', 'null' => true, 'default' => NULL), - 'email_token_expires' => array('type' => 'datetime', 'null' => true, 'default' => NULL), + 'email_token' => array('type' => 'string', 'null' => true, 'default' => null), + 'email_token_expires' => array('type' => 'datetime', 'null' => true, 'default' => null), 'tos' => array('type' => 'boolean', 'null' => true, 'default' => '0'), 'active' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'last_login' => array('type' => 'datetime', 'null' => true, 'default' => NULL), - 'last_action' => array('type' => 'datetime', 'null' => true, 'default' => NULL), + 'last_login' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'last_action' => array('type' => 'datetime', 'null' => true, 'default' => null), 'is_admin' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'role' => array('type' => 'string', 'null' => true, 'default' => NULL), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => NULL), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => NULL), - 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'BY_USERNAME' => array('column' => array('username'), 'unique' => 0), 'BY_EMAIL' => array('column' => array('email'), 'unique' => 0)) + 'role' => array('type' => 'string', 'null' => true, 'default' => null), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'BY_USERNAME' => array('column' => array('username'), 'unique' => 0), + 'BY_EMAIL' => array('column' => array('email'), 'unique' => 0) + ) ); } From 6ce8a032288bd2dfbfd2bd3b513eb4d9660e1ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 8 Jul 2014 01:53:52 +0200 Subject: [PATCH 0128/1476] CS fixes and conditional check in the views to show the search filter based on the presence of the Search plugin --- View/Users/admin_edit.ctp | 16 ++++++++-------- View/Users/admin_index.ctp | 20 +++++++++++--------- View/Users/edit.ctp | 5 ----- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/View/Users/admin_edit.ctp b/View/Users/admin_edit.ctp index 94efcc98c..02cd058ca 100644 --- a/View/Users/admin_edit.ctp +++ b/View/Users/admin_edit.ctp @@ -19,14 +19,14 @@ 'label' => __d('users', 'Username'))); echo $this->Form->input('email', array( 'label' => __d('users', 'Email'))); - if (!empty($roles)) { - echo $this->Form->input('role', array( - 'label' => __d('users', 'Role'), 'values' => $roles)); - } - echo $this->Form->input('is_admin', array( - 'label' => __d('users', 'Is Admin'))); - echo $this->Form->input('active', array( - 'label' => __d('users', 'Active'))); + if (!empty($roles)) { + echo $this->Form->input('role', array( + 'label' => __d('users', 'Role'), 'values' => $roles)); + } + echo $this->Form->input('is_admin', array( + 'label' => __d('users', 'Is Admin'))); + echo $this->Form->input('active', array( + 'label' => __d('users', 'Active'))); ?> Form->end('Submit'); ?> diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp index 0b408492e..b89b567c2 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -12,12 +12,14 @@

-

- Form->create($model, array('action' => 'index')); - echo $this->Form->input('username', array('label' => __d('users', 'Username'))); - echo $this->Form->input('email', array('label' => __d('users', 'Email'))); - echo $this->Form->end(__d('users', 'Search')); + ' . __d('users', 'Filter') . ''; + echo $this->Form->create($model, array('action' => 'index')); + echo $this->Form->input('username', array('label' => __d('users', 'Username'))); + echo $this->Form->input('email', array('label' => __d('users', 'Email'))); + echo $this->Form->end(__d('users', 'Search')); + } ?> element('Users.paging'); ?> @@ -56,9 +58,9 @@ - Html->link(__d('users', 'View'), array('action'=>'view', $user[$model]['id'])); ?> - Html->link(__d('users', 'Edit'), array('action'=>'edit', $user[$model]['id'])); ?> - Html->link(__d('users', 'Delete'), array('action'=>'delete', $user[$model]['id']), null, sprintf(__d('users', 'Are you sure you want to delete # %s?'), $user[$model]['id'])); ?> + Html->link(__d('users', 'View'), array('action' => 'view', $user[$model]['id'])); ?> + Html->link(__d('users', 'Edit'), array('action' => 'edit', $user[$model]['id'])); ?> + Html->link(__d('users', 'Delete'), array('action' => 'delete', $user[$model]['id']), null, sprintf(__d('users', 'Are you sure you want to delete # %s?'), $user[$model]['id'])); ?> diff --git a/View/Users/edit.ctp b/View/Users/edit.ctp index 93b87479e..cc929de0b 100644 --- a/View/Users/edit.ctp +++ b/View/Users/edit.ctp @@ -13,11 +13,6 @@ Form->create($model); ?>
- Form->input('UserDetail.first_name'); - echo $this->Form->input('UserDetail.last_name'); - echo $this->Form->input('UserDetail.birthday'); - ?>

Html->link(__d('users', 'Change your password'), array('action' => 'change_password')); ?>

From d0f330e6f262cc8db3208d9f987df4a8ed0a8e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Thu, 10 Jul 2014 14:34:33 +0200 Subject: [PATCH 0129/1476] Update Installation.md --- Docs/Documentation/Installation.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 635866a2e..3dbd08ab9 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -3,6 +3,12 @@ Installation To install the plugin, place the files in a directory labelled "Users/" in your "app/Plugin/" directory. +Then, include the following line in your `app/Config/bootstrap.php` to load the plugin in your application. + +``` +CakePlugin::load('Users'); +``` + Git Submodule ------------- @@ -33,4 +39,4 @@ If any updates are added, go back to the base of your own repository, commit and Composer -------- -The plugin also provides a "composer.json" file, to easily use the plugin through the Composer dependency manager. \ No newline at end of file +The plugin also provides a "composer.json" file, to easily use the plugin through the Composer dependency manager. From 5770052941ed7c3e13a733a0af7d065c2ddf66cf Mon Sep 17 00:00:00 2001 From: Jonathan Mackenzie Date: Mon, 14 Jul 2014 14:27:36 +0930 Subject: [PATCH 0130/1476] Corrected link for installing as a git submodule The url to add the git submodule from was pointing to migrations instead of users. --- Docs/Documentation/Installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 635866a2e..6bb1bf2ab 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -9,7 +9,7 @@ Git Submodule If you're using git for version control, you may want to add the **Users** plugin as a submodule on your repository. To do so, run the following command from the base of your repository: ``` -git submodule add git@github.com:CakeDC/migrations.git app/Plugin/Users +git submodule add git@github.com:CakeDC/users.git app/Plugin/Users ``` After doing so, you will see the submodule in your changes pending, plus the file ".gitmodules". Simply commit and push to your repository. @@ -33,4 +33,4 @@ If any updates are added, go back to the base of your own repository, commit and Composer -------- -The plugin also provides a "composer.json" file, to easily use the plugin through the Composer dependency manager. \ No newline at end of file +The plugin also provides a "composer.json" file, to easily use the plugin through the Composer dependency manager. From 3e9a378242d6d9481fdd82eb8f8632b1d43cdb8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 16 Jul 2014 13:59:23 +0200 Subject: [PATCH 0131/1476] Refs https://github.com/CakeDC/users/issues/189 Fixing the Email default "from" setting, some CS fixes and some code refactoring as well --- Controller/UsersController.php | 22 +++++++++++++++------- Model/User.php | 24 +++++++++++++++++++++--- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index 0169fe64d..b92e9ea77 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -156,9 +156,22 @@ public function beforeFilter() { $this->_setupPagination(); $this->set('model', $this->modelClass); + $this->_setDefaultEmail(); + } +/** + * Sets the default from email config + * + * @return void + */ + protected function _setDefaultEmail() { if (!Configure::read('App.defaultEmail')) { - Configure::write('App.defaultEmail', 'noreply@' . env('HTTP_HOST')); + $config = $this->_getMailInstance()->config(); + if (!empty($config['from'])) { + Configure::write('App.defaultEmail', $config['from']); + } else { + Configure::write('App.defaultEmail', 'noreply@' . env('HTTP_HOST')); + } } } @@ -841,12 +854,7 @@ protected function _resetPassword($token) { * @link http://book.cakephp.org/2.0/en/core-utility-libraries/email.html */ protected function _getMailInstance() { - $emailConfig = Configure::read('Users.emailConfig'); - if ($emailConfig) { - return new CakeEmail($emailConfig); - } else { - return new CakeEmail('default'); - } + return $this->{$this->modelClass}->getMailInstance(); } /** diff --git a/Model/User.php b/Model/User.php index abd3678c8..31f68c685 100755 --- a/Model/User.php +++ b/Model/User.php @@ -172,7 +172,9 @@ protected function _setupValidation() { 'confirm_password' => array( 'required' => array('rule' => array('compareFields', 'new_password', 'confirm_password'), 'required' => true, 'message' => __d('users', 'The passwords are not equal.'))), 'old_password' => array( - 'to_short' => array('rule' => 'validateOldPassword', 'required' => true, 'message' => __d('users', 'Invalid password.')))); + 'to_short' => array('rule' => 'validateOldPassword', 'required' => true, 'message' => __d('users', 'Invalid password.')) + ) + ); } /** @@ -234,7 +236,9 @@ public function checkEmailVerfificationToken($token = null) { $this->alias . '.email_verified' => 0, $this->alias . '.email_token' => $token), 'fields' => array( - 'id', 'email', 'email_token_expires', 'role'))); + 'id', 'email', 'email_token_expires', 'role') + ) + ); if (empty($result)) { return false; @@ -269,7 +273,8 @@ public function verifyEmail($token = null) { $user = $this->save($user, array( 'validate' => false, - 'callbacks' => false)); + 'callbacks' => false + )); $this->data = $user; return $user; } @@ -905,4 +910,17 @@ protected function _removeExpiredRegistrations() { ); } +/** + * Returns a CakeEmail object + * + * @return object CakeEmail instance + * @link http://book.cakephp.org/2.0/en/core-utility-libraries/email.html + */ + public function getMailInstance() { + $emailConfig = Configure::read('Users.emailConfig'); + if ($emailConfig) { + return new CakeEmail($emailConfig); + } + return new CakeEmail('default'); + } } From 83f502b3ca06bc934eba8ee2a35282394d6d06b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 28 Jul 2014 16:52:00 +0200 Subject: [PATCH 0132/1476] Changing the handling of the return_to parameter in the UsersController --- Controller/UsersController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index b92e9ea77..ab985654e 100755 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -504,6 +504,8 @@ public function login() { } if (isset($this->request->params['named']['return_to'])) { $this->set('return_to', urldecode($this->request->params['named']['return_to'])); + } elseif (isset($this->request->query['return_to'])) { + $this->set('return_to', $this->request->query['return_to']); } else { $this->set('return_to', false); } From 09499fbdec95c9eafa075caf758df63e7e59689b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 30 Jul 2014 13:10:24 +0200 Subject: [PATCH 0133/1476] Fixing some strings in the AllUsersTest.php to make sure the naming is correct --- Test/Case/AllUsersTest.php | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/Test/Case/AllUsersTest.php b/Test/Case/AllUsersTest.php index 006e62e68..49233bf7b 100644 --- a/Test/Case/AllUsersTest.php +++ b/Test/Case/AllUsersTest.php @@ -1,30 +1,30 @@ -addTestDirectory($basePath . DS . 'Controller'); - $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component'); - $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component' . DS . 'Auth'); - $Suite->addTestDirectory($basePath . DS . 'Model'); - return $Suite; - } - +addTestDirectory($basePath . DS . 'Controller'); + $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component'); + $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component' . DS . 'Auth'); + $Suite->addTestDirectory($basePath . DS . 'Model'); + return $Suite; + } + } \ No newline at end of file From 3dd162d8c779b4eb9c266893786f67bda37c2315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 3 Aug 2014 15:51:39 +0200 Subject: [PATCH 0134/1476] Forgot password translation --- Locale/deu/LC_MESSAGES/users.po | 3 +++ Locale/fra/LC_MESSAGES/users.po | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Locale/deu/LC_MESSAGES/users.po b/Locale/deu/LC_MESSAGES/users.po index 282922603..7324227d0 100644 --- a/Locale/deu/LC_MESSAGES/users.po +++ b/Locale/deu/LC_MESSAGES/users.po @@ -721,3 +721,6 @@ msgstr "Resette Dein Passwort" msgid "Search for users" msgstr "Nach Benutzern suchen" +#: View/Users/login.ctp:26 +msgid "I forgot my password" +msgstr "Ich habe mein Passwort vergessen" \ No newline at end of file diff --git a/Locale/fra/LC_MESSAGES/users.po b/Locale/fra/LC_MESSAGES/users.po index 7810b4eea..68c87262c 100644 --- a/Locale/fra/LC_MESSAGES/users.po +++ b/Locale/fra/LC_MESSAGES/users.po @@ -708,3 +708,6 @@ msgstr "Réinitialiser votre mot de passe" msgid "Search for users" msgstr "Rechercher des utilisateurs" +#: View/Users/login.ctp:26 +msgid "I forgot my password" +msgstr "Mot de passe oublié" \ No newline at end of file From f3311907f440664a52c7c46c8e8328a9e22f5ac3 Mon Sep 17 00:00:00 2001 From: Flug Date: Mon, 28 Jul 2014 21:41:35 +0200 Subject: [PATCH 0135/1476] change the permissions on the file --- Model/User.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Model/User.php diff --git a/Model/User.php b/Model/User.php old mode 100755 new mode 100644 From bf54e73455a639d4fa658375c18abfe608aa4fc0 Mon Sep 17 00:00:00 2001 From: Flug Date: Mon, 28 Jul 2014 21:49:15 +0200 Subject: [PATCH 0136/1476] change the permissions on the file --- Controller/UsersController.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Controller/UsersController.php diff --git a/Controller/UsersController.php b/Controller/UsersController.php old mode 100755 new mode 100644 From 73aa350b6fa1f0458d949fe9b2983985cf4e5f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Sun, 3 Aug 2014 23:49:29 +0200 Subject: [PATCH 0137/1476] Fixing an issue with pagination settings for the admin_index() --- Controller/UsersController.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Controller/UsersController.php b/Controller/UsersController.php index ab985654e..74f1df63d 100644 --- a/Controller/UsersController.php +++ b/Controller/UsersController.php @@ -202,11 +202,11 @@ protected function _setupPagination() { * @return void */ protected function _setupAdminPagination() { - $this->Paginator->settings = array( + $this->Paginator->settings[$this->modelClass] = array( 'limit' => 20, 'order' => array( $this->modelClass . '.created' => 'desc' - ) + ), ); } @@ -238,7 +238,10 @@ protected function _setupAuth() { 'userModel' => $this->_pluginDot() . $this->modelClass, 'scope' => array( $this->modelClass . '.active' => 1, - $this->modelClass . '.email_verified' => 1))); + $this->modelClass . '.email_verified' => 1 + ) + ) + ); $this->Auth->loginRedirect = '/'; $this->Auth->logoutRedirect = array('plugin' => Inflector::underscore($this->plugin), 'controller' => 'users', 'action' => 'login'); @@ -282,12 +285,14 @@ public function view($slug = null) { /** * Edit the current logged in user * - * Extend the plugin and implement your custom logic here + * Extend the plugin and implement your custom logic here, mostly thought to be + * used as a dashboard or profile page like method. + * + * See the plugins documentation for how to extend the plugin. * * @return void */ public function edit() { - // @todo replace this with something better than the user details that were removed } /** From 32f57cd08a4a092ffedf9f3983c2685be02448de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Mon, 4 Aug 2014 00:00:53 +0200 Subject: [PATCH 0138/1476] Updating CHANGELOG.md and .semver --- .semver | 2 +- CHANGELOG.md | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.semver b/.semver index 4b3e02978..c8cec4bb8 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 2 :minor: 1 -:patch: 0 +:patch: 1 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 5818e418f..7346d789c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ Changelog ========= +Release 2.1.1 +------------- + +https://github.com/CakeDC/users/tree/2.1.1 + + * [73aa350](https://github.com/cakedc/users/commit/73aa350) Fixing an issue with pagination settings for the admin_index() + * [3dd162d](https://github.com/cakedc/users/commit/3dd162d) Forgot password translation + * [09499fb](https://github.com/cakedc/users/commit/09499fb) Fixing some strings in the AllUsersTest.php to make sure the naming is correct + * [83f502b](https://github.com/cakedc/users/commit/83f502b) Changing the handling of the return_to parameter in the UsersController + * [3e9a378](https://github.com/cakedc/users/commit/3e9a378) Refs https://github.com/CakeDC/users/issues/189 Fixing the Email default "from" setting, some CS fixes and some code refactoring as well + * [d0f330e](https://github.com/cakedc/users/commit/d0f330e) Update Installation.md + + Release 2.1.0 ------------- From a701bc0c905b8d52e7672780f8782f4343faaf95 Mon Sep 17 00:00:00 2001 From: Oka Prinarjaya Date: Thu, 7 Aug 2014 17:07:54 +0700 Subject: [PATCH 0139/1476] Fixing login.ctp Before removing 'action' key the output is WRONG :
Auth->loginRedirect to /admin/users otherwise to /users. So.. i create http://pastebin.com/CwZE3qsM to achieve my goal. Then modify app/Plugin/Users/Config/routes.php Router::connect('/users/:action/*', array('plugin' => null, 'controller' => 'app_users')); if 'action' not removed, i get wrong output. I think not only me will need to override the CakeDC's Users plugin . --- View/Users/login.ctp | 1 - 1 file changed, 1 deletion(-) diff --git a/View/Users/login.ctp b/View/Users/login.ctp index ff35d908c..f6fde0dcc 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -15,7 +15,6 @@
Form->create($model, array( - 'action' => 'login', 'id' => 'LoginForm')); echo $this->Form->input('email', array( 'label' => __d('users', 'Email'))); From 75ce10a055887e84ec46380816011a6271f0f200 Mon Sep 17 00:00:00 2001 From: Travis Rowland Date: Mon, 20 Oct 2014 19:50:18 -0700 Subject: [PATCH 0140/1476] Update Installation.md Added instructions for creating required tables. --- Docs/Documentation/Installation.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 069402a81..1c21786ba 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -40,3 +40,13 @@ Composer -------- The plugin also provides a "composer.json" file, to easily use the plugin through the Composer dependency manager. + +Creating Required Tables +------------------------ +You can create database tables using either the schema shell or the [CakeDC Migrations plugin](http://github.com/CakeDC/migrations): + + ./Console/cake schema create users --plugin Users + +or + + ./Console/cake Migrations.migration run all --plugin Users From e812e302ec211ba5fe089df280312d7026c81409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 23 Jun 2015 09:59:59 +0100 Subject: [PATCH 0141/1476] updating travis to use CakePHP 2.6 --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b9b76039b..f65bc23cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,22 +12,22 @@ env: - REQUIRE="phpunit/phpunit:3.7.31" matrix: - - DB=mysql CAKE_VERSION=master + - DB=mysql CAKE_VERSION=2.6 matrix: include: - php: 5.3 env: - - CAKE_VERSION=master + - CAKE_VERSION=2.6 - php: 5.4 env: - - CAKE_VERSION=master + - CAKE_VERSION=2.6 - php: 5.5 env: - - CAKE_VERSION=master + - CAKE_VERSION=2.6 before_script: - - git clone https://github.com/burzum/travis.git --depth 1 ../travis + - git clone https://github.com/steinkel/travis.git --depth 1 ../travis - ../travis/before_script.sh script: From aa9d4090f47b499ce8f07d6f7fe57a019e5ad6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 29 Jul 2015 18:47:22 +0100 Subject: [PATCH 0142/1476] cleanup 2.x version files --- .../Migration/001_initialize_users_schema.php | 100 -- Config/Migration/002_renaming.php | 66 -- Config/Migration/map.php | 20 - Config/Schema/schema.php | 68 -- Config/routes.php | 8 - .../Component/Auth/CookieAuthenticate.php | 87 -- .../Auth/MultiColumnAuthenticate.php | 84 -- .../Component/Auth/TokenAuthenticate.php | 140 --- Controller/Component/RememberMeComponent.php | 239 ----- Controller/UsersAppController.php | 23 - Controller/UsersController.php | 880 ----------------- .../Documentation/Auth-in-the-Users-Plugin.md | 39 - Docs/Documentation/Configuration.md | 104 -- Docs/Documentation/Events.md | 19 - Docs/Documentation/Extending-the-Plugin.md | 65 -- Docs/Documentation/Installation.md | 52 - Docs/Documentation/Overview.md | 16 - Docs/Documentation/Remember-Me-Component.md | 37 - Docs/Documentation/Routing.md | 36 - Docs/Documentation/User-Details.md | 28 - Docs/Home.md | 29 - Locale/deu/LC_MESSAGES/users.mo | Bin 9265 -> 0 bytes Locale/deu/LC_MESSAGES/users.po | 726 -------------- Locale/fra/LC_MESSAGES/users.po | 713 -------------- Locale/nld/LC_MESSAGES/users.mo | Bin 9670 -> 0 bytes Locale/nld/LC_MESSAGES/users.po | 696 ------------- Locale/pt_BR/LC_MESSAGES/users.po | 722 -------------- Locale/rus/LC_MESSAGES/users.po | 711 -------------- Locale/spa/LC_MESSAGES/users.po | 716 -------------- Locale/users.pot | 526 ---------- Locale/zh_TW/LC_MESSAGES/users.po | 720 -------------- Model/User.php | 926 ------------------ Model/UsersAppModel.php | 65 -- README.md | 45 - Test/Case/AllAuthenticateTest.php | 22 - Test/Case/AllUsersTest.php | 30 - .../Component/Auth/CookieAuthenticateTest.php | 92 -- .../Auth/MultiColumnAuthenticateTest.php | 152 --- .../Component/Auth/TokenAuthenticateTest.php | 120 --- .../Component/RememberMeComponentTest.php | 171 ---- Test/Case/Controller/UsersControllerTest.php | 615 ------------ Test/Case/Model/UserTest.php | 494 ---------- Test/Fixture/MultiUserFixture.php | 38 - Test/Fixture/UserFixture.php | 195 ---- View/Elements/Users/admin_sidebar.ctp | 11 - View/Elements/Users/sidebar.ctp | 18 - View/Elements/pagination.ctp | 18 - View/Elements/paging.ctp | 4 - View/Emails/text/account_verification.ctp | 16 - View/Emails/text/new_password.ctp | 15 - View/Emails/text/password_reset_request.ctp | 14 - View/Users/add.ctp | 36 - View/Users/admin_add.ctp | 41 - View/Users/admin_edit.ctp | 34 - View/Users/admin_index.ctp | 70 -- View/Users/admin_view.ctp | 32 - View/Users/change_password.ctp | 29 - View/Users/dashboard.ctp | 15 - View/Users/edit.ctp | 22 - View/Users/index.ctp | 46 - View/Users/login.ctp | 33 - View/Users/request_password_change.ctp | 26 - View/Users/resend_verification.ctp | 26 - View/Users/reset_password.ctp | 18 - View/Users/search.ctp | 63 -- View/Users/view.ctp | 37 - composer.json | 34 - 67 files changed, 11293 deletions(-) delete mode 100644 Config/Migration/001_initialize_users_schema.php delete mode 100644 Config/Migration/002_renaming.php delete mode 100644 Config/Migration/map.php delete mode 100644 Config/Schema/schema.php delete mode 100644 Config/routes.php delete mode 100644 Controller/Component/Auth/CookieAuthenticate.php delete mode 100644 Controller/Component/Auth/MultiColumnAuthenticate.php delete mode 100644 Controller/Component/Auth/TokenAuthenticate.php delete mode 100644 Controller/Component/RememberMeComponent.php delete mode 100644 Controller/UsersAppController.php delete mode 100644 Controller/UsersController.php delete mode 100644 Docs/Documentation/Auth-in-the-Users-Plugin.md delete mode 100644 Docs/Documentation/Configuration.md delete mode 100644 Docs/Documentation/Events.md delete mode 100644 Docs/Documentation/Extending-the-Plugin.md delete mode 100644 Docs/Documentation/Installation.md delete mode 100644 Docs/Documentation/Overview.md delete mode 100644 Docs/Documentation/Remember-Me-Component.md delete mode 100644 Docs/Documentation/Routing.md delete mode 100644 Docs/Documentation/User-Details.md delete mode 100644 Docs/Home.md delete mode 100644 Locale/deu/LC_MESSAGES/users.mo delete mode 100644 Locale/deu/LC_MESSAGES/users.po delete mode 100644 Locale/fra/LC_MESSAGES/users.po delete mode 100644 Locale/nld/LC_MESSAGES/users.mo delete mode 100644 Locale/nld/LC_MESSAGES/users.po delete mode 100644 Locale/pt_BR/LC_MESSAGES/users.po delete mode 100644 Locale/rus/LC_MESSAGES/users.po delete mode 100644 Locale/spa/LC_MESSAGES/users.po delete mode 100644 Locale/users.pot delete mode 100644 Locale/zh_TW/LC_MESSAGES/users.po delete mode 100644 Model/User.php delete mode 100644 Model/UsersAppModel.php delete mode 100644 README.md delete mode 100644 Test/Case/AllAuthenticateTest.php delete mode 100644 Test/Case/AllUsersTest.php delete mode 100644 Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php delete mode 100644 Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php delete mode 100644 Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php delete mode 100644 Test/Case/Controller/Component/RememberMeComponentTest.php delete mode 100644 Test/Case/Controller/UsersControllerTest.php delete mode 100755 Test/Case/Model/UserTest.php delete mode 100644 Test/Fixture/MultiUserFixture.php delete mode 100644 Test/Fixture/UserFixture.php delete mode 100644 View/Elements/Users/admin_sidebar.ctp delete mode 100644 View/Elements/Users/sidebar.ctp delete mode 100644 View/Elements/pagination.ctp delete mode 100644 View/Elements/paging.ctp delete mode 100644 View/Emails/text/account_verification.ctp delete mode 100644 View/Emails/text/new_password.ctp delete mode 100644 View/Emails/text/password_reset_request.ctp delete mode 100644 View/Users/add.ctp delete mode 100644 View/Users/admin_add.ctp delete mode 100644 View/Users/admin_edit.ctp delete mode 100644 View/Users/admin_index.ctp delete mode 100644 View/Users/admin_view.ctp delete mode 100644 View/Users/change_password.ctp delete mode 100644 View/Users/dashboard.ctp delete mode 100644 View/Users/edit.ctp delete mode 100644 View/Users/index.ctp delete mode 100644 View/Users/login.ctp delete mode 100644 View/Users/request_password_change.ctp delete mode 100644 View/Users/resend_verification.ctp delete mode 100644 View/Users/reset_password.ctp delete mode 100644 View/Users/search.ctp delete mode 100644 View/Users/view.ctp delete mode 100644 composer.json diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php deleted file mode 100644 index f90c981af..000000000 --- a/Config/Migration/001_initialize_users_schema.php +++ /dev/null @@ -1,100 +0,0 @@ - array( - 'create_table' => array( - 'user_details' => array( - 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), - 'user_id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36), - 'position' => array('type' => 'float', 'null' => false, 'default' => '1', 'length' => 4), - 'field' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'length' => 60), - 'value' => array('type' => 'text', 'null' => true, 'default' => null), - 'input' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'data_type' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'label' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => 128), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1), - 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1) - ) - ), - 'users' => array( - 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), - 'username' => array('type' => 'string', 'null' => false, 'default' => null), - 'slug' => array('type' => 'string', 'null' => false, 'default' => null), - 'password' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), - 'password_token' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), - 'email' => array('type' => 'string', 'null' => true, 'default' => null), - 'email_verified' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'email_token' => array('type' => 'string', 'null' => true, 'default' => null), - 'email_token_expiry' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'tos' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'active' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'last_login' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'last_action' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'is_admin' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'role' => array('type' => 'string', 'null' => true, 'default' => null), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1), - 'BY_USERNAME' => array('column' => array('username'), 'unique' => 0), - 'BY_EMAIL' => array('column' => array('email'), 'unique' => 0) - ), - ), - ), - ), - 'down' => array( - 'drop_table' => array( - 'users', 'user_details'), - ) - ); - -/** - * before migration callback - * - * @param string $direction, up or down direction of migration process - */ - public function before($direction) { - return true; - } - -/** - * after migration callback - * - * @param string $direction, up or down direction of migration process - */ - public function after($direction) { - return true; - } - -} diff --git a/Config/Migration/002_renaming.php b/Config/Migration/002_renaming.php deleted file mode 100644 index 4b116a71c..000000000 --- a/Config/Migration/002_renaming.php +++ /dev/null @@ -1,66 +0,0 @@ - array( - 'rename_field' => array( - 'users' => array( - 'email_token_expiry' => 'email_token_expires' - ), - ), - ), - 'down' => array( - 'rename_field' => array( - 'users' => array( - 'email_token_expires' => 'email_token_expiry' - ), - ), - ) - ); - -/** - * before migration callback - * - * @param string $direction, up or down direction of migration process - */ - public function before($direction) { - return true; - } - -/** - * after migration callback - * - * @param string $direction, up or down direction of migration process - */ - public function after($direction) { - return true; - } - -} diff --git a/Config/Migration/map.php b/Config/Migration/map.php deleted file mode 100644 index 8281b4d9e..000000000 --- a/Config/Migration/map.php +++ /dev/null @@ -1,20 +0,0 @@ - array('001_initialize_users_schema' => 'M49c3417a54874a9d276811502cedc421'), - 2 => array('002_renaming' => 'M4ef8ba03ff504ab2b415980575f6eb26') -); diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php deleted file mode 100644 index 827c14344..000000000 --- a/Config/Schema/schema.php +++ /dev/null @@ -1,68 +0,0 @@ - array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), - 'user_id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36), - 'position' => array('type' => 'float', 'null' => false, 'default' => '1'), - 'field' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index'), - 'value' => array('type' => 'text', 'null' => true, 'default' => null), - 'input' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'data_type' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'label' => array('type' => 'string', 'null' => false, 'length' => 128), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), - 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1) - ) - ); - - public $users = array( - 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), - 'username' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index'), - 'slug' => array('type' => 'string', 'null' => false, 'default' => null), - 'password' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), - 'password_token' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), - 'email' => array('type' => 'string', 'null' => true, 'default' => null, 'key' => 'index'), - 'email_verified' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'email_token' => array('type' => 'string', 'null' => true, 'default' => null), - 'email_token_expires' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'tos' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'active' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'last_login' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'last_action' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'is_admin' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'role' => array('type' => 'string', 'null' => true, 'default' => null), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1), - 'BY_USERNAME' => array('column' => array('username'), 'unique' => 0), - 'BY_EMAIL' => array('column' => array('email'), 'unique' => 0) - ) - ); -} diff --git a/Config/routes.php b/Config/routes.php deleted file mode 100644 index 844bd54f0..000000000 --- a/Config/routes.php +++ /dev/null @@ -1,8 +0,0 @@ - 'users', 'controller' => 'users')); -Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/login', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); -Router::connect('/logout', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); -Router::connect('/register', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); \ No newline at end of file diff --git a/Controller/Component/Auth/CookieAuthenticate.php b/Controller/Component/Auth/CookieAuthenticate.php deleted file mode 100644 index 554cb52f8..000000000 --- a/Controller/Component/Auth/CookieAuthenticate.php +++ /dev/null @@ -1,87 +0,0 @@ -Auth->authenticate = array( - * 'Authenticate.Cookie' => array( - * 'fields' => array( - * 'username' => 'username', - * 'password' => 'password' - * ), - * 'userModel' => 'User', - * 'scope' => array('User.active' => 1), - * 'crypt' => 'rijndael', // Defaults to rijndael(safest), optionally set to 'cipher' if required - * 'cookie' => array( - * 'name' => 'RememberMe', - * 'time' => '+2 weeks', - * ) - * ) - * ) - * }}} - * - * @author Ceeram - * @copyright Ceeram - * @license MIT - * @link https://github.com/ceeram/Authenticate - */ -class CookieAuthenticate extends BaseAuthenticate { - - public function __construct(ComponentCollection $collection, $settings) { - $this->settings['cookie'] = array( - 'name' => 'RememberMe', - 'time' => '+2 weeks', - 'base' => Router::getRequest()->base - ); - $this->settings['crypt'] = 'rijndael'; - parent::__construct($collection, $settings); - } - -/** - * Authenticates the identity contained in the cookie. Will use the `settings.userModel`, and `settings.fields` - * to find COOKIE data that is used to find a matching record in the `settings.userModel`. Will return false if - * there is no cookie data, either username or password is missing, of if the scope conditions have not been met. - * - * @param CakeRequest $request The unused request object - * @return mixed False on login failure. An array of User data on success. - * @throws CakeException - */ - public function getUser(CakeRequest $request) { - if (!isset($this->_Collection->Cookie) || !$this->_Collection->Cookie instanceof CookieComponent) { - throw new CakeException('CookieComponent is not loaded'); - } - - $this->_Collection->Cookie->type($this->settings['crypt']); - list(, $model) = pluginSplit($this->settings['userModel']); - - $data = $this->_Collection->Cookie->read($model); - if (empty($data)) { - return false; - } - - extract($this->settings['fields']); - if (empty($data[$username]) || empty($data[$password])) { - return false; - } - - $user = $this->_findUser($data[$username], $data[$password]); - if ($user) { - $this->_Collection->Session->write(AuthComponent::$sessionKey, $user); - return $user; - } - return false; - } - - public function authenticate(CakeRequest $request, CakeResponse $response) { - return $this->getUser($request); - } - - public function logout($user) { - $this->_Collection->Cookie->destroy(); - } - -} diff --git a/Controller/Component/Auth/MultiColumnAuthenticate.php b/Controller/Component/Auth/MultiColumnAuthenticate.php deleted file mode 100644 index 73bca9927..000000000 --- a/Controller/Component/Auth/MultiColumnAuthenticate.php +++ /dev/null @@ -1,84 +0,0 @@ -Auth->authenticate = array( - * 'Authenticate.MultiColumn' => array( - * 'fields' => array( - * 'username' => 'username', - * 'password' => 'password' - * ), - * 'columns' => array('username', 'email'), - * 'userModel' => 'User', - * 'scope' => array('User.active' => 1) - * ) - * ) - * }}} - * - * @author Ceeram - * @copyright Ceeram - * @license MIT - * @link https://github.com/ceeram/Authenticate - */ -class MultiColumnAuthenticate extends FormAuthenticate { - -/** - * Settings for this object. - * - * - `fields` The fields to use to identify a user by. - * - 'columns' array of columns to check username form input against - * - `userModel` The model name of the User, defaults to User. - * - `scope` Additional conditions to use when looking up and authenticating users, - * i.e. `array('User.is_active' => 1).` - * - * @var array - */ - public $settings = array( - 'fields' => array( - 'username' => 'username', - 'password' => 'password' - ), - 'columns' => array(), - 'userModel' => 'User', - 'scope' => array() - ); - -/** - * Find a user record using the standard options. - * - * @param string $username The username/identifier. - * @param string $password The unhashed password. - * @return Mixed Either false on failure, or an array of user data. - */ - protected function _findUser($username, $password = null) { - $userModel = $this->settings['userModel']; - list($plugin, $model) = pluginSplit($userModel); - $fields = $this->settings['fields']; - $conditions = array($model . '.' . $fields['username'] => $username); - if ($this->settings['columns'] && is_array($this->settings['columns'])) { - $columns = array(); - foreach ($this->settings['columns'] as $column) { - $columns[] = array($model . '.' . $column => $username); - } - $conditions = array('OR' => $columns); - } - $conditions = array_merge($conditions, array($model . '.' . $fields['password'] => $this->_password($password))); - if (!empty($this->settings['scope'])) { - $conditions = array_merge($conditions, $this->settings['scope']); - } - $result = ClassRegistry::init($userModel)->find('first', array( - 'conditions' => $conditions, - 'recursive' => 0 - )); - if (empty($result) || empty($result[$model])) { - return false; - } - unset($result[$model][$fields['password']]); - return $result[$model]; - } - -} diff --git a/Controller/Component/Auth/TokenAuthenticate.php b/Controller/Component/Auth/TokenAuthenticate.php deleted file mode 100644 index eaadeaefa..000000000 --- a/Controller/Component/Auth/TokenAuthenticate.php +++ /dev/null @@ -1,140 +0,0 @@ -Auth->authenticate = array( - * 'Authenticate.Token' => array( - * 'fields' => array( - * 'username' => 'username', - * 'password' => 'password', - * 'token' => 'public_key', - * ), - * 'parameter' => '_token', - * 'header' => 'X-MyApiTokenHeader', - * 'userModel' => 'User', - * 'scope' => array('User.active' => 1) - * ) - * ) - * }}} - * - * @author Ceeram - * @copyright Ceeram - * @license MIT - * @link https://github.com/ceeram/Authenticate - */ -class TokenAuthenticate extends BaseAuthenticate { - -/** - * Settings for this object. - * - * - `fields` The fields to use to identify a user by. Make sure `'token'` has been added to the array - * - `parameter` The url parameter name of the token. - * - `header` The token header value. - * - `userModel` The model name of the User, defaults to User. - * - `scope` Additional conditions to use when looking up and authenticating users, - * i.e. `array('User.is_active' => 1).` - * - `recursive` The value of the recursive key passed to find(). Defaults to 0. - * - `contain` Extra models to contain and store in session. - * - * @var array - */ - public $settings = array( - 'fields' => array( - 'username' => 'username', - 'password' => 'password', - 'token' => 'token', - ), - 'parameter' => '_token', - 'header' => 'X-ApiToken', - 'userModel' => 'User', - 'scope' => array(), - 'recursive' => 0, - 'contain' => null, - ); - -/** - * Constructor - * - * @param ComponentCollection $collection The Component collection used on this request. - * @param array $settings Array of settings to use. - * @throws CakeException - */ - public function __construct(ComponentCollection $collection, $settings) { - parent::__construct($collection, $settings); - if (empty($this->settings['parameter']) && empty($this->settings['header'])) { - throw new CakeException(__d('users', 'You need to specify token parameter and/or header')); - } - } - -/** - * Authenticate user - * - * @param CakeRequest $request The request object - * @param CakeResponse $response response object. - * @return mixed. False on login failure. An array of User data on success. - */ - public function authenticate(CakeRequest $request, CakeResponse $response) { - $user = $this->getUser($request); - if (!$user) { - $response->statusCode(401); - $response->send(); - } - return $user; - } - -/** - * Get token information from the request. - * - * @param CakeRequest $request Request object. - * @return mixed Either false or an array of user information - */ - public function getUser(CakeRequest $request) { - if (!empty($this->settings['header'])) { - $token = $request->header($this->settings['header']); - if ($token) { - return $this->_findUser($token, null); - } - } - if (!empty($this->settings['parameter']) && !empty($request->query[$this->settings['parameter']])) { - $token = $request->query[$this->settings['parameter']]; - return $this->_findUser($token); - } - return false; - } - -/** - * Find a user record. - * - * @param string $username The token identifier. - * @param string $password Unused password. - * @return Mixed Either false on failure, or an array of user data. - */ - public function _findUser($username, $password = null) { - $userModel = $this->settings['userModel']; - list($plugin, $model) = pluginSplit($userModel); - $fields = $this->settings['fields']; - - $conditions = array( - $model . '.' . $fields['token'] => $username, - ); - if (!empty($this->settings['scope'])) { - $conditions = array_merge($conditions, $this->settings['scope']); - } - $result = ClassRegistry::init($userModel)->find('first', array( - 'conditions' => $conditions, - 'recursive' => (int)$this->settings['recursive'], - 'contain' => $this->settings['contain'], - )); - if (empty($result) || empty($result[$model])) { - return false; - } - $user = $result[$model]; - unset($user[$fields['password']]); - unset($result[$model]); - return array_merge($user, $result); - } - -} diff --git a/Controller/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php deleted file mode 100644 index fdd2a7dc1..000000000 --- a/Controller/Component/RememberMeComponent.php +++ /dev/null @@ -1,239 +0,0 @@ - true, - 'userModel' => 'User', - 'cookieKey' => 'rememberMe', - 'cookieLifeTime' => '+1 year', - 'cookie' => array( - 'name' => 'User' - ), - 'fields' => array( - 'email', - 'username', - 'password' - ) - ); - -/** - * Constructor - * - * @param ComponentCollection $collection A ComponentCollection for this component - * @param array $settings Array of settings. - * @return RememberMeComponent - */ - public function __construct(ComponentCollection $collection, $settings = array()) { - parent::__construct($collection, $settings); - - $this->_checkAndSetCookieLifeTime(); - $this->settings = Hash::merge($this->_defaults, $settings); - $this->configureCookie($this->settings['cookie']); - } - -/** - * Check if the system is 32bit and uses DateTime() instead strtotime() to get - * an integer instead of a string that is passed on to CookieComponent::write() - * due to problems with strtotime() in CookieComponent::_expire(). See - * the link in this doc block. - * - * This method needs to be called in the constructor before the default config - * values are merged! - * - * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3868-cookiecomponent_expires-fails-on-dates-set-far-in-the-future-on-32bit-systems - * @link http://stackoverflow.com/questions/3266077/php-strtotime-is-returning-false-for-a-future-date - * @return void - */ - protected function _checkAndSetCookieLifeTime() { - $lifeTime = $this->_defaults['cookieLifeTime']; - if (is_string($lifeTime) && strtotime($lifeTime) === false) { - $Date = new DateTime($lifeTime); - $this->_defaults['cookieLifeTime'] = $Date->format('U'); - } - } - -/** - * Initializes RememberMeComponent for use in the controller - * - * @param Controller $controller A reference to the instantiating controller object - * @return void - */ - public function initialize(Controller $controller) { - $this->request = $controller->request; - $this->Auth = $controller->Auth; - } - -/** - * startup - * - * @param Controller $controller - * @return void - */ - public function startup(Controller $controller) { - if ($this->settings['autoLogin'] == true && !$this->Auth->loggedIn()) { - $this->restoreLoginFromCookie(); - } - } - -/** - * Logs the user again in based on the cookie data - * - * @param boolean $checkLoginStatus - * @return boolean True on login success, false on failure - */ - public function restoreLoginFromCookie($checkLoginStatus = true) { - if ($checkLoginStatus && $this->Auth->loggedIn()) { - return true; - } - - if ($this->cookieIsSet()) { - extract($this->settings); - $cookie = $this->Cookie->read($cookieKey); - $request = $this->request->data; - - foreach ($fields as $field) { - if (!empty($cookie[$field])) { - $this->request->data[$userModel][$field] = $cookie[$field]; - } - } - - $result = $this->Auth->login(); - - if (!$result) { - $this->request->data = $request; - } - - return $result; - } - return false; - } - -/** - * Sets the cookie with the specified fields - * - * @param array Optional, login credentials array in the form of Model.field, if empty this->request[''] will be used - * @return boolean - */ - public function setCookie($data = array()) { - extract($this->settings); - - if (empty($data)) { - $data = $this->request->data; - if (empty($data)) { - $data = $this->Auth->user(); - } - } - - if (empty($data)) { - return false; - } - - $cookieData = array(); - - foreach ($fields as $field) { - if (isset($data[$userModel][$field]) && !empty($data[$userModel][$field])) { - $cookieData[$field] = $data[$userModel][$field]; - } - } - - $this->Cookie->write($cookieKey, $cookieData, true, $cookieLifeTime); - return true; - } - -/** - * Checks if the remember me cookie is set - * - * @return boolean - */ - public function cookieIsSet() { - extract($this->settings); - $cookie = $this->Cookie->read($cookieKey); - return (!empty($cookie)); - } - -/** - * Destroys the remember me cookie - * - * @return void - */ - public function destroyCookie() { - extract($this->settings); - if (isset($_COOKIE[$cookie['name']])) { - $this->Cookie->name = $cookie['name']; - $this->Cookie->destroy(); - } - } - -/** - * Configures the cookie component instance - * - * @param array $options - * @throws InvalidArgumentException Thrown if an invalid option key was passed - * @return void - */ - public function configureCookie($options = array()) { - $validProperties = array('domain', 'key', 'name', 'path', 'secure', 'time'); - $defaults = array( - 'time' => '1 month', - 'name' => 'User'); - - $options = array_merge($defaults, $options); - - foreach ($options as $key => $value) { - if (in_array($key, $validProperties)) { - $this->Cookie->{$key} = $value; - } else { - throw new InvalidArgumentException(__d('users', 'Invalid options %s', $key)); - } - } - } -} diff --git a/Controller/UsersAppController.php b/Controller/UsersAppController.php deleted file mode 100644 index baec383d7..000000000 --- a/Controller/UsersAppController.php +++ /dev/null @@ -1,23 +0,0 @@ -_setupComponents(); - parent::__construct($request, $response); - $this->_reInitControllerName(); - } - -/** - * Providing backward compatibility to a fix that was just made recently to the core - * for users that want to upgrade the plugin but not the core - * - * @link http://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3550-inherited-controllers-get-wrong-property-names - * @return void - */ - protected function _reInitControllerName() { - $name = substr(get_class($this), 0, -10); - if ($this->name === null) { - $this->name = $name; - } elseif ($name !== $this->name) { - $this->name = $name; - } - } - -/** - * Returns $this->plugin with a dot, used for plugin loading using the dot notation - * - * @return mixed string|null - */ - protected function _pluginDot() { - if (is_string($this->plugin)) { - return $this->plugin . '.'; - } - return $this->plugin; - } - -/** - * Wrapper for CakePlugin::loaded() - * - * @throws MissingPluginException - * @param string $plugin - * @param boolean $exceiption - * @return boolean - */ - protected function _pluginLoaded($plugin, $exception = true) { - $result = CakePlugin::loaded($plugin); - if ($exception === true && $result === false) { - throw new MissingPluginException(array('plugin' => $plugin)); - } - return $result; - } - -/** - * Setup components based on plugin availability - * - * @return void - * @link https://github.com/CakeDC/search - */ - protected function _setupComponents() { - if ($this->_pluginLoaded('Search', false)) { - $this->components[] = 'Search.Prg'; - } - } - -/** - * beforeFilter callback - * - * @return void - */ - public function beforeFilter() { - parent::beforeFilter(); - $this->_setupAuth(); - $this->_setupPagination(); - - $this->set('model', $this->modelClass); - $this->_setDefaultEmail(); - } - -/** - * Sets the default from email config - * - * @return void - */ - protected function _setDefaultEmail() { - if (!Configure::read('App.defaultEmail')) { - $config = $this->_getMailInstance()->config(); - if (!empty($config['from'])) { - Configure::write('App.defaultEmail', $config['from']); - } else { - Configure::write('App.defaultEmail', 'noreply@' . env('HTTP_HOST')); - } - } - } - -/** - * Sets the default pagination settings up - * - * Override this method or the index action directly if you want to change - * pagination settings. - * - * @return void - */ - protected function _setupPagination() { - $this->Paginator->settings = array( - 'limit' => 12, - 'conditions' => array( - $this->modelClass . '.active' => 1, - $this->modelClass . '.email_verified' => 1 - ) - ); - } - -/** - * Sets the default pagination settings up - * - * Override this method or the index() action directly if you want to change - * pagination settings. admin_index() - * - * @return void - */ - protected function _setupAdminPagination() { - $this->Paginator->settings[$this->modelClass] = array( - 'limit' => 20, - 'order' => array( - $this->modelClass . '.created' => 'desc' - ), - ); - } - -/** - * Setup Authentication Component - * - * @return void - */ - protected function _setupAuth() { - if (Configure::read('Users.disableDefaultAuth') === true) { - return; - } - - $this->Auth->allow('add', 'reset', 'verify', 'logout', 'view', 'reset_password', 'login', 'resend_verification'); - - if (!is_null(Configure::read('Users.allowRegistration')) && !Configure::read('Users.allowRegistration')) { - $this->Auth->deny('add'); - } - - if ($this->request->action == 'register') { - $this->Components->disable('Auth'); - } - - $this->Auth->authenticate = array( - 'Form' => array( - 'fields' => array( - 'username' => 'email', - 'password' => 'password'), - 'userModel' => $this->_pluginDot() . $this->modelClass, - 'scope' => array( - $this->modelClass . '.active' => 1, - $this->modelClass . '.email_verified' => 1 - ) - ) - ); - - $this->Auth->loginRedirect = '/'; - $this->Auth->logoutRedirect = array('plugin' => Inflector::underscore($this->plugin), 'controller' => 'users', 'action' => 'login'); - $this->Auth->loginAction = array('admin' => false, 'plugin' => Inflector::underscore($this->plugin), 'controller' => 'users', 'action' => 'login'); - } - -/** - * Simple listing of all users - * - * @return void - */ - public function index() { - $this->set('users', $this->Paginator->paginate($this->modelClass)); - } - -/** - * The homepage of a users giving him an overview about everything - * - * @return void - */ - public function dashboard() { - $user = $this->{$this->modelClass}->read(null, $this->Auth->user('id')); - $this->set('user', $user); - } - -/** - * Shows a users profile - * - * @param string $slug User Slug - * @return void - */ - public function view($slug = null) { - try { - $this->set('user', $this->{$this->modelClass}->view($slug)); - } catch (Exception $e) { - $this->Session->setFlash($e->getMessage()); - $this->redirect('/'); - } - } - -/** - * Edit the current logged in user - * - * Extend the plugin and implement your custom logic here, mostly thought to be - * used as a dashboard or profile page like method. - * - * See the plugins documentation for how to extend the plugin. - * - * @return void - */ - public function edit() { - } - -/** - * Admin Index - * - * @return void - */ - public function admin_index() { - if ($this->{$this->modelClass}->Behaviors->loaded('Searchable')) { - $this->Prg->commonProcess(); - unset($this->{$this->modelClass}->validate['username']); - unset($this->{$this->modelClass}->validate['email']); - $this->{$this->modelClass}->data[$this->modelClass] = $this->passedArgs; - } - - if ($this->{$this->modelClass}->Behaviors->loaded('Searchable')) { - $parsedConditions = $this->{$this->modelClass}->parseCriteria($this->passedArgs); - } else { - $parsedConditions = array(); - } - - $this->_setupAdminPagination(); - $this->Paginator->settings[$this->modelClass]['conditions'] = $parsedConditions; - $this->set('users', $this->Paginator->paginate()); - } - -/** - * Admin view - * - * @param string $id User ID - * @return void - */ - public function admin_view($id = null) { - try { - $user = $this->{$this->modelClass}->view($id, 'id'); - } catch (NotFoundException $e) { - $this->Session->setFlash(__d('users', 'Invalid User.')); - $this->redirect(array('action' => 'index')); - } - - $this->set('user', $user); - } - -/** - * Admin add - * - * @return void - */ - public function admin_add() { - if (!empty($this->request->data)) { - $this->request->data[$this->modelClass]['tos'] = true; - $this->request->data[$this->modelClass]['email_verified'] = true; - - if ($this->{$this->modelClass}->add($this->request->data)) { - $this->Session->setFlash(__d('users', 'The User has been saved')); - $this->redirect(array('action' => 'index')); - } - } - $this->set('roles', Configure::read('Users.roles')); - } - -/** - * Admin edit - * - * @param null $userId - * @return void - */ - public function admin_edit($userId = null) { - try { - $result = $this->{$this->modelClass}->edit($userId, $this->request->data); - if ($result === true) { - $this->Session->setFlash(__d('users', 'User saved')); - $this->redirect(array('action' => 'index')); - } else { - unset($result[$this->modelClass]['password']); - $this->request->data = $result; - } - } catch (OutOfBoundsException $e) { - $this->Session->setFlash($e->getMessage()); - $this->redirect(array('action' => 'index')); - } - - if (empty($this->request->data)) { - $this->request->data = $this->{$this->modelClass}->read(null, $userId); - unset($this->request->data[$this->modelClass]['password']); - } - $this->set('roles', Configure::read('Users.roles')); - } - -/** - * Delete a user account - * - * @param string $userId User ID - * @return void - */ - public function admin_delete($userId = null) { - if ($this->{$this->modelClass}->delete($userId)) { - $this->Session->setFlash(__d('users', 'User deleted')); - } else { - $this->Session->setFlash(__d('users', 'Invalid User')); - } - - $this->redirect(array('action' => 'index')); - } - -/** - * Search for a user - * - * @return void - */ - public function admin_search() { - $this->search(); - } - -/** - * User register action - * - * @return void - */ - public function add() { - if ($this->Auth->user()) { - $this->Session->setFlash(__d('users', 'You are already registered and logged in!')); - $this->redirect('/'); - } - - if (!empty($this->request->data)) { - $user = $this->{$this->modelClass}->register($this->request->data); - if ($user !== false) { - $Event = new CakeEvent( - 'Users.Controller.Users.afterRegistration', - $this, - array( - 'data' => $this->request->data, - ) - ); - $this->getEventManager()->dispatch($Event); - if ($Event->isStopped()) { - $this->redirect(array('action' => 'login')); - } - - $this->_sendVerificationEmail($this->{$this->modelClass}->data); - $this->Session->setFlash(__d('users', 'Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login.')); - $this->redirect(array('action' => 'login')); - } else { - unset($this->request->data[$this->modelClass]['password']); - unset($this->request->data[$this->modelClass]['temppassword']); - $this->Session->setFlash(__d('users', 'Your account could not be created. Please, try again.'), 'default', array('class' => 'message warning')); - } - } - } - -/** - * Common login action - * - * @return void - */ - public function login() { - $Event = new CakeEvent( - 'Users.Controller.Users.beforeLogin', - $this, - array( - 'data' => $this->request->data, - ) - ); - - $this->getEventManager()->dispatch($Event); - - if ($Event->isStopped()) { - return; - } - - if ($this->request->is('post')) { - if ($this->Auth->login()) { - $Event = new CakeEvent( - 'Users.Controller.Users.afterLogin', - $this, - array( - 'data' => $this->request->data, - 'isFirstLogin' => !$this->Auth->user('last_login') - ) - ); - - $this->getEventManager()->dispatch($Event); - - $this->{$this->modelClass}->id = $this->Auth->user('id'); - $this->{$this->modelClass}->saveField('last_login', date('Y-m-d H:i:s')); - - if ($this->here == $this->Auth->loginRedirect) { - $this->Auth->loginRedirect = '/'; - } - $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged in'), $this->Auth->user($this->{$this->modelClass}->displayField))); - if (!empty($this->request->data)) { - $data = $this->request->data[$this->modelClass]; - if (empty($this->request->data[$this->modelClass]['remember_me'])) { - $this->RememberMe->destroyCookie(); - } else { - $this->_setCookie(); - } - } - - if (empty($data[$this->modelClass]['return_to'])) { - $data[$this->modelClass]['return_to'] = null; - } - - // Checking for 2.3 but keeping a fallback for older versions - if (method_exists($this->Auth, 'redirectUrl')) { - $this->redirect($this->Auth->redirectUrl($data[$this->modelClass]['return_to'])); - } else { - $this->redirect($this->Auth->redirect($data[$this->modelClass]['return_to'])); - } - } else { - $this->Auth->flash(__d('users', 'Invalid e-mail / password combination. Please try again')); - } - } - if (isset($this->request->params['named']['return_to'])) { - $this->set('return_to', urldecode($this->request->params['named']['return_to'])); - } elseif (isset($this->request->query['return_to'])) { - $this->set('return_to', $this->request->query['return_to']); - } else { - $this->set('return_to', false); - } - $allowRegistration = Configure::read('Users.allowRegistration'); - $this->set('allowRegistration', (is_null($allowRegistration) ? true : $allowRegistration)); - } - -/** - * Search - Requires the CakeDC Search plugin to work - * - * @throws MissingPluginException - * @return void - * @link https://github.com/CakeDC/search - */ - public function search() { - $this->_pluginLoaded('Search'); - - $searchTerm = ''; - $this->Prg->commonProcess($this->modelClass); - - $by = null; - if (!empty($this->request->params['named']['search'])) { - $searchTerm = $this->request->params['named']['search']; - $by = 'any'; - } - if (!empty($this->request->params['named']['username'])) { - $searchTerm = $this->request->params['named']['username']; - $by = 'username'; - } - if (!empty($this->request->params['named']['email'])) { - $searchTerm = $this->request->params['named']['email']; - $by = 'email'; - } - $this->request->data[$this->modelClass]['search'] = $searchTerm; - - $this->Paginator->settings = array( - 'search', - 'limit' => 12, - 'by' => $by, - 'search' => $searchTerm, - 'conditions' => array( - 'AND' => array( - $this->modelClass . '.active' => 1, - $this->modelClass . '.email_verified' => 1 - ) - ) - ); - - $this->set('users', $this->Paginator->paginate($this->modelClass)); - $this->set('searchTerm', $searchTerm); - } - -/** - * Common logout action - * - * @return void - */ - public function logout() { - $user = $this->Auth->user(); - $this->Session->destroy(); - $this->RememberMe->destroyCookie(); - $this->Session->setFlash(sprintf(__d('users', '%s you have successfully logged out'), $user[$this->{$this->modelClass}->displayField])); - $this->redirect($this->Auth->logout()); - } - -/** - * Checks if an email is already verified and if not renews the expiration time - * - * @return void - */ - public function resend_verification() { - if ($this->request->is('post')) { - try { - if ($this->{$this->modelClass}->checkEmailVerification($this->request->data)) { - $this->_sendVerificationEmail($this->{$this->modelClass}->data); - $this->Session->setFlash(__d('users', 'The email was resent. Please check your inbox.')); - $this->redirect('login'); - } else { - $this->Session->setFlash(__d('users', 'The email could not be sent. Please check errors.')); - } - } catch (Exception $e) { - $this->Session->setFlash($e->getMessage()); - } - } - } - -/** - * Confirm email action - * - * @param string $type Type, deprecated, will be removed. Its just still there for a smooth transistion. - * @param string $token Token - * @return void - */ - public function verify($type = 'email', $token = null) { - if ($type == 'reset') { - // Backward compatiblity - $this->request_new_password($token); - } - - try { - $this->{$this->modelClass}->verifyEmail($token); - $this->Session->setFlash(__d('users', 'Your e-mail has been validated!')); - return $this->redirect(array('action' => 'login')); - } catch (RuntimeException $e) { - $this->Session->setFlash($e->getMessage()); - return $this->redirect('/'); - } - } - -/** - * This method will send a new password to the user - * - * @param string $token Token - * @throws NotFoundException - * @return void - */ - public function request_new_password($token = null) { - if (Configure::read('Users.sendPassword') !== true) { - throw new NotFoundException(); - } - - $data = $this->{$this->modelClass}->verifyEmail($token); - - if (!$data) { - $this->Session->setFlash(__d('users', 'The url you accessed is not longer valid')); - return $this->redirect('/'); - } - - if ($this->{$this->modelClass}->save($data, array('validate' => false))) { - $this->_sendNewPassword($data); - $this->Session->setFlash(__d('users', 'Your password was sent to your registered email account')); - $this->redirect(array('action' => 'login')); - } - - $this->Session->setFlash(__d('users', 'There was an error verifying your account. Please check the email you were sent, and retry the verification link.')); - $this->redirect('/'); - } - -/** - * Sends the password reset email - * - * @param array - * @return void - */ - protected function _sendNewPassword($userData) { - $Email = $this->_getMailInstance(); - $Email->from(Configure::read('App.defaultEmail')) - ->to($userData[$this->modelClass]['email']) - ->replyTo(Configure::read('App.defaultEmail')) - ->return(Configure::read('App.defaultEmail')) - ->subject(env('HTTP_HOST') . ' ' . __d('users', 'Password Reset')) - ->template($this->_pluginDot() . 'new_password') - ->viewVars(array( - 'model' => $this->modelClass, - 'userData' => $userData)) - ->send(); - } - -/** - * Allows the user to enter a new password, it needs to be confirmed by entering the old password - * - * @return void - */ - public function change_password() { - if ($this->request->is('post')) { - $this->request->data[$this->modelClass]['id'] = $this->Auth->user('id'); - if ($this->{$this->modelClass}->changePassword($this->request->data)) { - $this->Session->setFlash(__d('users', 'Password changed.')); - // we don't want to keep the cookie with the old password around - $this->RememberMe->destroyCookie(); - $this->redirect('/'); - } - } - } - -/** - * Reset Password Action - * - * Handles the trigger of the reset, also takes the token, validates it and let the user enter - * a new password. - * - * @param string $token Token - * @param string $user User Data - * @return void - */ - public function reset_password($token = null, $user = null) { - if (empty($token)) { - $admin = false; - if ($user) { - $this->request->data = $user; - $admin = true; - } - $this->_sendPasswordReset($admin); - } else { - $this->_resetPassword($token); - } - } - -/** - * Sets a list of languages to the view which can be used in selects - * - * @deprecated No fallback provided, use the Utils plugin in your app directly - * @param string $viewVar View variable name, default is languages - * @throws MissingPluginException - * @return void - * @link https://github.com/CakeDC/utils - */ - protected function _setLanguages($viewVar = 'languages') { - $this->_pluginLoaded('Utils'); - - $Languages = new Languages(); - $this->set($viewVar, $Languages->lists('locale')); - } - -/** - * Sends the verification email - * - * This method is protected and not private so that classes that inherit this - * controller can override this method to change the varification mail sending - * in any possible way. - * - * @param string $to Receiver email address - * @param array $options EmailComponent options - * @return void - */ - protected function _sendVerificationEmail($userData, $options = array()) { - $defaults = array( - 'from' => Configure::read('App.defaultEmail'), - 'subject' => __d('users', 'Account verification'), - 'template' => $this->_pluginDot() . 'account_verification', - 'layout' => 'default', - 'emailFormat' => CakeEmail::MESSAGE_TEXT - ); - - $options = array_merge($defaults, $options); - - $Email = $this->_getMailInstance(); - $Email->to($userData[$this->modelClass]['email']) - ->from($options['from']) - ->emailFormat($options['emailFormat']) - ->subject($options['subject']) - ->template($options['template'], $options['layout']) - ->viewVars(array( - 'model' => $this->modelClass, - 'user' => $userData - )) - ->send(); - } - -/** - * Checks if the email is in the system and authenticated, if yes create the token - * save it and send the user an email - * - * @param boolean $admin Admin boolean - * @param array $options Options - * @return void - */ - protected function _sendPasswordReset($admin = null, $options = array()) { - $defaults = array( - 'from' => Configure::read('App.defaultEmail'), - 'subject' => __d('users', 'Password Reset'), - 'template' => $this->_pluginDot() . 'password_reset_request', - 'emailFormat' => CakeEmail::MESSAGE_TEXT, - 'layout' => 'default' - ); - - $options = array_merge($defaults, $options); - - if (!empty($this->request->data)) { - $user = $this->{$this->modelClass}->passwordReset($this->request->data); - - if (!empty($user)) { - - $Email = $this->_getMailInstance(); - $Email->to($user[$this->modelClass]['email']) - ->from($options['from']) - ->emailFormat($options['emailFormat']) - ->subject($options['subject']) - ->template($options['template'], $options['layout']) - ->viewVars(array( - 'model' => $this->modelClass, - 'user' => $this->{$this->modelClass}->data, - 'token' => $this->{$this->modelClass}->data[$this->modelClass]['password_token'])) - ->send(); - - if ($admin) { - $this->Session->setFlash(sprintf( - __d('users', '%s has been sent an email with instruction to reset their password.'), - $user[$this->modelClass]['email'])); - $this->redirect(array('action' => 'index', 'admin' => true)); - } else { - $this->Session->setFlash(__d('users', 'You should receive an email with further instructions shortly')); - $this->redirect(array('action' => 'login')); - } - } else { - $this->Session->setFlash(__d('users', 'No user was found with that email.')); - $this->redirect($this->referer('/')); - } - } - $this->render('request_password_change'); - } - -/** - * Sets the cookie to remember the user - * - * @param array RememberMe (Cookie) component properties as array, like array('domain' => 'yourdomain.com') - * @param string Cookie data keyname for the userdata, its default is "User". This is set to User and NOT using the model alias to make sure it works with different apps with different user models across different (sub)domains. - * @return void - * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html - */ - protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { - $this->RememberMe->settings['cookieKey'] = $cookieKey; - $this->RememberMe->configureCookie($options); - $this->RememberMe->setCookie(); - } - -/** - * This method allows the user to change his password if the reset token is correct - * - * @param string $token Token - * @return void - */ - protected function _resetPassword($token) { - $user = $this->{$this->modelClass}->checkPasswordToken($token); - if (empty($user)) { - $this->Session->setFlash(__d('users', 'Invalid password reset token, try again.')); - $this->redirect(array('action' => 'reset_password')); - return; - } - - if (!empty($this->request->data) && $this->{$this->modelClass}->resetPassword(Hash::merge($user, $this->request->data))) { - if ($this->RememberMe->cookieIsSet()) { - $this->Session->setFlash(__d('users', 'Password changed.')); - $this->_setCookie(); - } else { - $this->Session->setFlash(__d('users', 'Password changed, you can now login with your new password.')); - $this->redirect($this->Auth->loginAction); - } - } - - $this->set('token', $token); - } - -/** - * Returns a CakeEmail object - * - * @return object CakeEmail instance - * @link http://book.cakephp.org/2.0/en/core-utility-libraries/email.html - */ - protected function _getMailInstance() { - return $this->{$this->modelClass}->getMailInstance(); - } - -/** - * Default isAuthorized method - * - * This is called to see if a user (when logged in) is able to access an action - * - * @param array $user - * @return boolean True if allowed - * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#using-controllerauthorize - */ - public function isAuthorized($user = null) { - return parent::isAuthorized($user); - } - -} diff --git a/Docs/Documentation/Auth-in-the-Users-Plugin.md b/Docs/Documentation/Auth-in-the-Users-Plugin.md deleted file mode 100644 index f88afcb23..000000000 --- a/Docs/Documentation/Auth-in-the-Users-Plugin.md +++ /dev/null @@ -1,39 +0,0 @@ -Auth in the Users Plugin -======================== - -The users plugin is made to work out of the box with some default settings. If you want to customize them or user your application level auth settings you'll have to do a few things that are explained in this document. - -Disable The Default Auth Settings ---------------------------------- - -In the case you want to user your customized auth settings of your application, for example declared in the ```AppController::beforeFilter()``` method, you'll have to disable the default auth of the users plugin. - -You can use the configuration settings to disable it, for example in your ```bootstrap.php``` - -```php -Configure::write('Users.disableDefaultAuth'); -``` - -Or when extending the UsersController simply overwrite the ```_setupAuth()``` method. - -```php -protected function _setupAuth() { -} -``` - -Overwriting the default auth settings -------------------------------------- - -If you want to change some of the default auth settings of the users controller overwrite the ```_setupAuth()``` method in the extending controller. - -```php -protected function _setupAuth() { - parent::_setupAuth(); - $this->Auth->loginRedirect = array( - 'plugin' => null, - 'admin' => false, - 'controller' => 'app_users', - 'action' => 'login' - ); -} -``` \ No newline at end of file diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md deleted file mode 100644 index 195238470..000000000 --- a/Docs/Documentation/Configuration.md +++ /dev/null @@ -1,104 +0,0 @@ -Configuration -============= - -Email Templates ---------------- - -To modify the templates as needed copy them to - -``` -/app/View/Plugin/Users/Emails/ -``` - -Note that you will have to overwrite any view that is linking to the plugin like the email verification email. - -Disable Slugs -------------- - -If the Utils plugin is present the users model will auto attach and use the sluggable behavior. - -If you don't want to create slugs for new users put this in your configuration: - -```php -Configure::write('Users.disableSlugs', true); -``` - -Email configuration -------------------- - -The plugin uses the $default email configuration (should be present in your Config/email.php file), but you can override it using - -```php -Configure::write('Users.emailConfig', 'default'); -``` - -To change the plugins default "from" setting for outgoing emails put this into your bootstrap.php - -```php -Configure::write('App.defaultEmail', 'your@email.com'); -``` - -If not configured it will use 'noreply@' . env('HTTP_HOST'); as default from email address. - -Roles Management ----------------- - -You can add `Users.roles` in `app/Config/bootstrap.php` file and these roles will be used on Admin Add / Edit pages. i.e: - -```php -Configure::write('Users.roles', array( - 'admin' => 'Admin', - 'registered' => 'Registered' -)); -``` - -If you don't specify roles it will use 'admin' role (if `is_admin` is checked) or 'registered' role otherwise. You can override 'registered' role setting Users.defaultRole in `app/Config/bootstrap.php`. i.e: - -```php -Configure::write('Users.defaultRole', 'user_registered'); -``` - -Enabling / Disabling Registration ---------------------------------- - -Some application won't need to have registration enable so you can define `Users.allowRegistration` in `app/Config/bootstrap.php` to enable or disable registration. By default registration will be enabled. - -``` -// Disables the registration -Configure::write('Users.allowRegistration', false); -``` - -Configuration options ---------------------- - -The configuration settings can be written by using the Configure class. - -``` -Users.disableDefaultAuth -``` - -Disables/enables the default auth setup that is implemented in the plugins `UsersController::_setupAuth()`. - -``` -Users.allowRegistration -``` - -Disables/enables the user registration. - -``` -Users.roles -``` - -Optional array of user roles if you need it. This is not actively used by the plugin by default. - -``` -Users.sendPassword -``` - -Disables/enables the password reset functionality. - -``` -Users.emailConfig -``` - -Email configuration settings array used by this plugin. diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md deleted file mode 100644 index 5107404ba..000000000 --- a/Docs/Documentation/Events.md +++ /dev/null @@ -1,19 +0,0 @@ -Events -====== - -If you're not familiar with events please look them up in [the official documentation](http://book.cakephp.org/2.0/en/core-libraries/events.html). - -The events in this plugin follow these conventions ...: - -* Users.Controller.Users.someCallBack -* Users.Model.User.someCallBack -* ... - -Events that are triggered in this plugin are: - - * Users.Controller.Users.beforeRegister - * Users.Controller.Users.afterRegister - * Users.Controller.Users.beforeLogin - * Users.Controller.Users.afterLogin - * Users.Model.User.beforeRegister - * Users.Model.User.afterRegister \ No newline at end of file diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md deleted file mode 100644 index ab62128f1..000000000 --- a/Docs/Documentation/Extending-the-Plugin.md +++ /dev/null @@ -1,65 +0,0 @@ -Extending the Plugin -==================== - -Extending the controller ------------------------- - -Declare the controller class. It is important to set the ```$name``` property here to make sure the controller initializes everything correct. If not setting the name the name setting is inherited and won't match the new controllers name. - -```php -App::uses('UsersController', 'Users.Controller'); -class AppUsersController extends UsersController { - public $name = 'AppUsers'; -} -``` - -In the case you want to extend also the user model it's required to set the right user class in the beforeFilter() because the controller will use the inherited model which would be Users.User. - -```php -public function beforeFilter() { - parent::beforeFilter(); - $this->User = ClassRegistry::init('AppUser'); - $this->set('model', 'AppUser'); -} -``` - -You can overwrite the ```Controller::render()``` method to fall back to the plugin views in the case you want to use some of them - -```php -public function render($view = null, $layout = null) { - if (is_null($view)) { - $view = $this->action; - } - $viewPath = substr(get_class($this), 0, strlen(get_class($this)) - 10); - if (!file_exists(APP . 'View' . DS . $viewPath . DS . $view . '.ctp')) { - $this->plugin = 'Users'; - } else { - $this->viewPath = $viewPath; - } - return parent::render($view, $layout); -} -``` - -Note: Depending on the CakePHP version you are using, you might need to bring a copy of the Views used in the plugin to your AppUsers view directory - -Extending the model -------------------- - -Declare the model. Same as in the controller, set the ```$name``` property and set the ```$useTable``` property to ```users```. - -```php -App::uses('User', 'Users.Model'); -class AppUser extends User { - public $name = 'AppUser'; - public $useTable = 'users'; -} -``` - -It's important to override the ```AppUser::$useTable``` property with the ```users``` table. It won't use the correct table otherwise. - -You can override / extend all methods or properties like validation rules to suit your needs. - -Routing to preserve the /users URL when extending the plugin ------------------------------------------------------------- - -See the [Routing](Routing.md) documentation. \ No newline at end of file diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md deleted file mode 100644 index 1c21786ba..000000000 --- a/Docs/Documentation/Installation.md +++ /dev/null @@ -1,52 +0,0 @@ -Installation -============ - -To install the plugin, place the files in a directory labelled "Users/" in your "app/Plugin/" directory. - -Then, include the following line in your `app/Config/bootstrap.php` to load the plugin in your application. - -``` -CakePlugin::load('Users'); -``` - -Git Submodule -------------- - -If you're using git for version control, you may want to add the **Users** plugin as a submodule on your repository. To do so, run the following command from the base of your repository: - -``` -git submodule add git@github.com:CakeDC/users.git app/Plugin/Users -``` - -After doing so, you will see the submodule in your changes pending, plus the file ".gitmodules". Simply commit and push to your repository. - -To initialize the submodule(s) run the following command: - -``` -git submodule update --init --recursive -``` - -To retreive the latest updates to the plugin, assuming you're using the "master" branch, go to "app/Plugin/Users" and run the following command: - -``` -git pull origin master -``` - -If you're using another branch, just change "master" for the branch you are currently using. - -If any updates are added, go back to the base of your own repository, commit and push your changes. This will update your repository to point to the latest updates to the plugin. - -Composer --------- - -The plugin also provides a "composer.json" file, to easily use the plugin through the Composer dependency manager. - -Creating Required Tables ------------------------- -You can create database tables using either the schema shell or the [CakeDC Migrations plugin](http://github.com/CakeDC/migrations): - - ./Console/cake schema create users --plugin Users - -or - - ./Console/cake Migrations.migration run all --plugin Users diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md deleted file mode 100644 index 4b7164bbc..000000000 --- a/Docs/Documentation/Overview.md +++ /dev/null @@ -1,16 +0,0 @@ -Overview -======== - -You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. - -The plugin itself is already capable of: - -* User registration (Enable by default) -* Account verification by a token sent via email -* User login (email / password) -* Password reset based on requesting a token by email and entering a new password -* User search (requires the [CakeDC Search](http://github.com/CakeDC/search) plugin) -* User management using the "admin" section (add / edit / delete) -* Simple roles management - -The default password reset process requires the user to enter his email address, an email is sent to the user with a link and a token. When the user accesses the URL with the token he can enter a new password. diff --git a/Docs/Documentation/Remember-Me-Component.md b/Docs/Documentation/Remember-Me-Component.md deleted file mode 100644 index 5a1352dd9..000000000 --- a/Docs/Documentation/Remember-Me-Component.md +++ /dev/null @@ -1,37 +0,0 @@ -Remember Me Component -===================== - -To use the "remember me" checkbox which sets a cookie on the login page you will need to add the RememberMe component to the AppController or the controllers you want to auto-login the user again based on the cookie. - -```php -public $components = array( - 'Users.RememberMe' -); -``` - -If you are using another user model than ```User``` you'll have to configure it: - -```php - public $components = array( - 'Users.RememberMe' => array( - 'userModel' => 'AppUser' - ) - ); -``` - -And add this line - -```php -$this->RememberMe->restoreLoginFromCookie(); -``` - -to your controllers ```beforeFilter()``` callback - -```php -public function beforeFilter() { - parent::beforeFilter(); - $this->RememberMe->restoreLoginFromCookie(); -} -``` - -The code will read the login credentials from the cookie and log the user in based on that information. Note that you have to use CakePHPs AuthComponent or an aliased Component implementing the same interface as AuthComponent. diff --git a/Docs/Documentation/Routing.md b/Docs/Documentation/Routing.md deleted file mode 100644 index 7782817df..000000000 --- a/Docs/Documentation/Routing.md +++ /dev/null @@ -1,36 +0,0 @@ -Routing -======= - -To remove the second users from ```/users/users``` in the url you can use routes. - -The plugin itself comes with a routes file but you need to explicitly load them. - -```php -CakePlugin::load('Users', array( - 'routes' => true -)); -``` - -List of the used routes: - -```php -Router::connect('/users', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/index/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/users/users/:action/*', array('plugin' => 'users', 'controller' => 'users')); -Router::connect('/login/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); -Router::connect('/logout/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); -Router::connect('/register/*', array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); -``` - -Changing the routes -------------------- - -If you're extending the plugin remove the plugin from the route by setting it to ```null``` and replace the controller with your controller extending the plugins users controller. - -```php -Router::connect('/users', array('plugin' => null, 'controller' => 'app_users')); -/* ... */ -``` - -Feel free to change the routes here or add others as you need for your application. \ No newline at end of file diff --git a/Docs/Documentation/User-Details.md b/Docs/Documentation/User-Details.md deleted file mode 100644 index 117951288..000000000 --- a/Docs/Documentation/User-Details.md +++ /dev/null @@ -1,28 +0,0 @@ -User Details (Legacy) -===================== - -The plugin contains an ```user_details``` table. This table is a key-value store and is not used by the plugin any more but kept for legacy apps. - -If you want to use it you'll have to add the associations by extending the plugin or add your own profiles table which is recommend to use instead of a key-value store. But be aware that this model is very like removed in future versions of the plugin. - -```php -class AppUser extends User { - public $hasMany = array( - 'UserDetail' => array( - 'className' => 'Users.UserDetail' - ) - ); -} -``` - -Or using your custom profiles table. - -```php -class AppUser extends User { - public $hasOne = array( - 'Profile' => array( - 'className' => 'Profile' - ) - ); -} -``` diff --git a/Docs/Home.md b/Docs/Home.md deleted file mode 100644 index ca146c92a..000000000 --- a/Docs/Home.md +++ /dev/null @@ -1,29 +0,0 @@ -Home -==== - -The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. - -The plugin is thought as a base to extend your app specific users controller and model from. - -That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. You will have to extend the plugin on app level to customize it. Read the instructions carefully. - -Requirements ------------- - -* CakePHP 2.5+ -* PHP 5.2.8+ -* [CakeDC Utils plugin](http://github.com/CakeDC/utils) (Optional but recommended) -* [CakeDC Search plugin](http://github.com/CakeDC/search) (Optional but recommended) - -Documentation -------------- - -* [Overview](Documentation/Overview.md) -* [Installation](Documentation/Installation.md) -* [Configuration](Documentation/Configuration.md) -* [Routing](Documentation/Routing.md) -* [Auth in the Users Plugin](Documentation/Auth-in-the-Users-Plugin.md) -* [User Details (Legacy)](Documentation/User-Details.md) -* [Events](Documentation/Events.md) -* [Remember Me Component](Documentation/Remember-Me-Component.md) -* [Extending the Plugin](Documentation/Extending-the-Plugin.md) diff --git a/Locale/deu/LC_MESSAGES/users.mo b/Locale/deu/LC_MESSAGES/users.mo deleted file mode 100644 index 67ba5d6917bde5f70d7433d1f3c2472bf888ab8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9265 zcmb7|TZ|-EdB+dfA+Us-6C48ppT%~(YfralcGuqVtasNlJG0BOGrQ}Z8DBOwq`LZa zcV()phPq69MhQU(5|N8vLL$XVl*BTLqVN(VR=Mm;Xd!_FNghyyA{3;60^$Kd9!Q>0 ze&0E#s=8;#EGf;If1Ok3^4-7h^ncuS=N~GbkoHTo6L%=}DRA`-{Nvevqf&1NKLWlV z{5W_Y_!;n7@XO#YfbV~k!;>IGY85;RZh{YhzX{5`&wxJ*{sSoIeF2oCz6rh={4bCH z4c<-v$KajdI}a(vt9m#1GvNK;JHdzi_>p9Dp}XTV3nD}MZwe*E`9IsZ?=Hu!n41%BK2??ULJ z$3;-&`XNy0{%!Cu_~)R^{{r|B_yh3w!S`_JEcn;pG4S6(k@H&+h6W!7MZT*bs!>mY zBFE=Jp~HZ}$EQKj)63vd@D)(x^c7I{{Q-Cyybs~aJ^?6v#^CRQuYeDLZG`hKa09#- zOhDo5CGaHpH{f~jTi{n;2QMf~^z^?N;V*-4qa*kjxCg!fihX_^6uo}m;~fa|G5Ys_ z!v7Ue=6wtlJ^c|l1HJ+ZzyAWlg8Dj$%GLKkk?a3}!q2-9HYBP0L6OJ2@1Ft1POpKm zsGbLfjue#hJ^{+UFM|u580`0qdR{Uh&o=br?HzcmoisHZ`hKLjsG;N z^xg#T0KW*n5BxGH_WfOtcQg1n{bf+%!AC){*S`RnqW%>WdcO}o3f_aUJq%t3KMU@G zGXFvC?CxpsA^Icmvj1})KM9_t|F_^W z_(M?mehgyIflJ`a;BSHVgNG5m(0v}1^SdA-RKEkB0RIZy0KWmg4wOgyWbzTZ#Mb2z zAHfvtv&4V#U6!gRX|gZsvybq0lD6r(_W#rT7h9Y6V`87r(>_4EN)vwM5j%X2_8{#X zP2~9kO&-FG!j#l1?F}@MEv(v@DgN<6n%Ko7v^UY@IZb=QzA5!9;D`OY*sbVN9`TV= zv~}8tXoyw4o_2{Q_9QZrM|5+ACOX*vEck&H@G?#GC$=ij5eHUR$NamE4Kct^5P$fWpAZv-+vao zKogs}mnOC;Pe>CxR1f63YlbDak}rYi%xX{iTvbY6y`$@5+r$GbXC`+d{ZQF7ZU zX<4X6otcl6CNFf6@|v4Mw$1c*kmsW`>*`U!i6$x9dLz~0AV~UV-;6Mh!Yy44jERg)iqHGA3aaSj4Vdd#r z%FiE+jwxqEt@>dqHW8@O3M;;q|6aC@P`GSGG-pXfJlLU+fK<>rd5-J`y^EI9h+x*TfB)t~2`XjOb8@L4whYoXXwt zR<#LqZhJc0x2$bOay=B`41*#ZD6gAvkfx|e1eplWei))nh72dRb-JuRyw-vPgbo3d zYsFceQiLb=>FQpZP5G)05HDXJjAPv=D!{i}VMX36Gxo@cGWd2GidW?O&ah&c()>Xa zQuI|Zh{=Qj#OSm~$O+3VDt4hM$l2VI!;y*eq)Bn>Vibiqt>@4>BRoY(p9m7=&Gy34 zK@qH4nd9{#oYtCf5r{1$OjIE#O60q`>SBe9#%*=Y46X6&HN*QYVN|W#puKK_481$B zA{QOzYCX-e-5K2}ZJ^MJK_Nsl#|kfmMLfr`6Q?e2w$*ys84__eOg79#X6q)~K@w^M z?QXI!$stFk$jqe-8J|*!?xw~uXX7f`LBzJr@N137F&mNtV=?3l*TC;D06|u9x4*t$B5s758_YG<0Kr# z+hl}tNb(8mrOk|K?k0nh-4Bj_TAG+DX;WM#%kV4sw$_+BvI*bLihb-3TwrW#Z^7Zf zkWiifxacmvT1Tj@5|Gb&XtBr%zi&G$Rn)-+6TiPUJ0|Loj zl7>!`c-L-`t7lA10yOG50-IQ2MUJaOOePtdIDl)pD(SGDY0W$6XT}OtM9sd=tIC|% zBD>i+jjUbiC1r_K%`ILiOT3;k6Pk!R?e;NLR%8XtusU;kbFWolL{a6-77RM%^uly2 z!hA59HJH2Dt!q=7rSn0778XqOJlP7+StkSyJZ9R>tk|-DS zxnRpIpR+MK$LULIr$bk-Y_!gaKAF*4=FkOwY<6z8HT!sL?omDW=)#Hlhi8w?&N8ue z&FpaUjU9sFY9P8G+ZGvC|l5F(StO(Qn^Asrzpy|O+>8D3Og)!F)F)dh6ww; zG$xwJyWE(DCg%3`lc#m+X)94;^kUM>kiRa6oQOePb;V_&_eyLQnvkU)m08yaB_?72 zw%$Bo^7vK0Wr^OBYZ|Uu_P8Zc!-z68i5~Zs{wjC3=GJ!2-P$Ob%cNgj+idKM_WaI4z?#oSsfJR zaAL$40x6=a?WwJoB5X-W;b#O)SIR7K7{rsCH4BJ7SYKQt@Ifqc=?ORS9Q3jHi zk;@)Q-i0$4xEgPD0b71XU>Yus^n?|^i^y*zo}5AAMSIWPlH^RUW46*ETuvTuMZM1u zgIi`0G$sv#Xq@YH8}J4a2>aRirj5qJf)Lh4sam9H!Ld4rFeN7XTk&L!Z7ZnjQ#bVc#CuE#k5kr= zi5o6R`{1B1Ok~t`ViCXo1Vo}LPLQo+FsW|K0W^r_TtKjSH?T1S4Usi1^W2H$H!5-_ z9%WbKlO3Bbi7*$I)G~Wi2Q=xlPVD#scPtyV>+sT~FPBiFpy_R^Z&~a%m&${iBT7RAa&?p}>&}Q#xm=@t z1f3ScJ_gxrLP-9;3~v+HX;LJ=*xy$B<_i-Imy)88nmBrSAGDgFC55%k5^`3hR{6!` z()eb!=Q5v97bbID*}Qvj-az_ysXSGn3X8EJTKei#yBs%Bpj9Q74WCuH?JARM zaa$tePf4-AV!&#(my4Ih_=c^e+j=ERB+oQ9=hG!;Ovl}=@r{HGDRzdGs_iBf+U#+_ zq^=3bu{)w|_jP~lbxbyUU<7hd9dzAye?KY?{KyS>LJxIR7xCH}UL7coiY|oY^G)e9 cj18\n" -"Language-Team: Cake Development Corporation \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-Poedit-Language: German\n" -"X-Poedit-Country: GERMANY\n" -"X-Poedit-SourceCharset: utf-8\n" - -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "Ungültiges Detail" - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "Gespeichert" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "%s Details gespeichert" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "" - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "" - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "" - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "" - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "Profil gespeichert." - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "Dein Profil konnte nicht gespeichert werden." - -#: /controllers/users_controller.php:193 -msgid "Invalid User." -msgstr "Ungültiger Benutzer." - -#: /controllers/users_controller.php:207 -msgid "The User has been saved" -msgstr "Der Benutzer wurde gespeichert" - -#: /controllers/users_controller.php:223 -msgid "User saved" -msgstr "Benutzer gespeichert." - -#: /controllers/users_controller.php:247 -msgid "User deleted" -msgstr "" - -#: /controllers/users_controller.php:249 -#: /models/user.php:703 -msgid "Invalid User" -msgstr "Ungültiger Benutzer" - -#: /controllers/users_controller.php:273 -msgid "You are already registered and logged in!" -msgstr "Du bist bereits registriert und angemeldet!" - -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Dein Account wurde angelegt. Du solltest in Kürze eine Email erhalten um Deinen Account zu bestötigen. Einmal bestätigt wirst Du Dich anmelden können." - -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 -msgid "Your account could not be created. Please, try again." -msgstr "Dein Account konnte nicht angelegt werden. Bitte versuch es erneut." - -#: /controllers/users_controller.php:309 -msgid "%s you have successfully logged in" -msgstr "%s Du hast Dich erfolgreich angemeldet" - -#: /controllers/users_controller.php:383 -msgid "%s you have successfully logged out" -msgstr "%s Du hast Dich erfolgreich abgemeldet" - -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" -msgstr "Die angeforderte URL ist nicht mehr gültig" - -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" -msgstr "Passwort Reset" - -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" -msgstr "Dein Passwort wurde resettet" - -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" -msgstr "Bitte log Dich mit diesem Passwort ein um Dein Passwort zu ändern" - -#: /controllers/users_controller.php:438 -msgid "Your password was sent to your registered email account" -msgstr "Dein Passwort wurde an Deine Email-Adresse versendet" - -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 -msgid "Your e-mail has been validated!" -msgstr "Deine Email-Adresse wurde bestätigt!" - -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "Es trat ein Fehler wärend der Überprüfung Deiner Email-Adresse auf. Bitte prüfe die URL in der Email welche Du zur überprüfung Deiner Email-Adresse benutzen solltest." - -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 -msgid "The url you accessed is not longer valid" -msgstr "Die angeforderte URL ist nicht länger gültig" - -#: /controllers/users_controller.php:467 -msgid "Password changed." -msgstr "Passwort geändert." - -#: /controllers/users_controller.php:521 -msgid "Account verification" -msgstr "Accountverifizierung" - -#: /controllers/users_controller.php:563 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "" - -#: /controllers/users_controller.php:567 -msgid "You should receive an email with further instructions shortly" -msgstr "Du solltest in Kürze eine Email erhalten mit weiteren Instruktionen" - -#: /controllers/users_controller.php:571 -msgid "No user was found with that email." -msgstr "Es wurde kein Benutzer mit Dieser Email gefunden." - -#: /controllers/users_controller.php:588 -msgid "Invalid password reset token, try again." -msgstr "Ungültiger Passwort-Reset-Token, bitte versuche es erneut." - -#: /controllers/users_controller.php:594 -msgid "Password changed, you can now login with your new password." -msgstr "Passwort geändert, Du kannst Dich nun mit Deinem neuen Passwort einloggen." - -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "Bitte gib einen Benutzernamen ein" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "Der Benutzername muß alphanumerisch sein" - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "Der Benutzername ist bereits vergeben" - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "Der Benutzername muß mindestens 3 Zeichen lang sein." - -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "Bitte gib eine gültige Emailadresse ein." - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "Diese Emailadresse wird bereits verwendet." - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "Das Passwort muß mindestens 8 Zeichen haben." - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "Bitte gib ein Passwort ein." - -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." -msgstr "Die Passwort sind nicht gleich, bitte versuche es erneut." - -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "Du mußt den Nutzungsbedingungen zustimmen." - -#: /models/user.php:137;357 -msgid "The passwords are not equal." -msgstr "Die Passwörter sind nicht gleich." - -#: /models/user.php:139 -msgid "Invalid password." -msgstr "Ungültiges Passwort." - -#: /models/user.php:150 -msgid "Invalid date" -msgstr "Ungültiges Datum" - -#: /models/user.php:315 -msgid "This Email Address exists but was never validated." -msgstr "Diese Email-Adresse existiert wude aber nie bestätigt." - -#: /models/user.php:317 -msgid "This Email Address does not exist in the system." -msgstr "Diese Email-Adresse existiert nicht im System." - -#: /models/user.php:406 -msgid "$this->data['" -msgstr "" - -#: /models/user.php:460 -msgid "The user does not exist." -msgstr "Der Benutzer existiert nicht." - -#: /models/user.php:505 -msgid "Please enter your email address." -msgstr "Bitte gib Deine Email-Adresse an." - -#: /models/user.php:515 -msgid "The email address does not exist in the system" -msgstr "Diese Email-Adresse existiert nicht im System" - -#: /models/user.php:520 -msgid "Your account is already authenticated." -msgstr "Dein Account ist bereits bestätigt." - -#: /models/user.php:525 -msgid "Your account is disabled." -msgstr "Dein Account ist deaktiviert." - -#: /tests/cases/controllers/users_controller.test.php:34 -msgid "Sorry, but you need to login to access this location." -msgstr "Sorry, aber Du mußt Dich anmelden um diese Seite zu besuchen." - -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Ungültige Email oder Passwort. Bitte versuch es noch mal." - -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" -msgstr "" - -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" -msgstr "" - -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" -msgstr "" - -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" -msgstr "" - -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 -msgid "List Users" -msgstr "" - -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" -msgstr "Löschen" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" -msgstr "Bist Du Dir sicher das Du %s löschen möchtest?" - -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" -msgstr "" - -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "" - -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" -msgstr "" - -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" -msgstr "" - -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" -msgstr "Bearbeiten" - -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 -msgid "previous" -msgstr "" - -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 -msgid "next" -msgstr "" - -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" -msgstr "" - -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" -msgstr "" - -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" -msgstr "" - -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" -msgstr "Benutzer" - -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" -msgstr "" - -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" -msgstr "" - -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" -msgstr "" - -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" -msgstr "" - -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" -msgstr "" - -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" -msgstr "" - -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" -msgstr "" - -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" -msgstr "" - -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" -msgstr "" - -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" -msgstr "Name" - -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" -msgstr "Beschreibung" - -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" -msgstr "Absenden" - -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" -msgstr "Email" - -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 -msgid "Password" -msgstr "Passwort" - -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 -msgid "Login" -msgstr "Anmeldung" - -#: /views/elements/email/text/account_verification.ctp:2 -msgid "Hello %s," -msgstr "Hallo %s," - -#: /views/elements/email/text/account_verification.ctp:4 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "um Deinen Account zu aktivieren mußt Du diese URL innerhalb von 24 Stunden aufrufen" - -#: /views/elements/email/text/password_reset_request.ctp:2 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "Eine Anfrage um Dein Passwort zu resetten wurde gesendet. Um Dein Passwort zu ändern klicke auf den unten stehenden Link." - -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 -msgid "Add User" -msgstr "Benutzer hinzufügen" - -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 -msgid "Edit User" -msgstr "Benutzer bearbeiten" - -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 -msgid "Users" -msgstr "Benutzer" - -#: /views/users/admin_index.ctp:4 -msgid "Filter" -msgstr "" - -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" -msgstr "Benutzername" - -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 -msgid "Search" -msgstr "Suche" - -#: /views/users/admin_view.ctp:24 -msgid "Delete User" -msgstr "Benutzer löschen" - -#: /views/users/change_password.ctp:1 -msgid "Change your password" -msgstr "Ändere Dein Kennwort" - -#: /views/users/change_password.ctp:3 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "Bitte gib Dein altes Passwort aus Sicherheitsgründen ein und dann gib Dein neues Kenntwort zweimal ein." - -#: /views/users/change_password.ctp:8 -msgid "Old Password" -msgstr "Altes Passwort" - -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 -msgid "New Password" -msgstr "Neues Passwort" - -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 -msgid "Confirm" -msgstr "Bestätigen" - -#: /views/users/dashboard.ctp:2 -msgid "Welcome" -msgstr "Willkommen" - -#: /views/users/dashboard.ctp:3 -msgid "Recent broadcasts" -msgstr "" - -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "Meine Gruppen" - -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "" - -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "Lade einen Benutzer ein" - -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "" - -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "" - -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "Mitglieder" - -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "Benutzer einladen" - -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "" - -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "" - -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "" - -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "" - -#: /views/users/groups.ctp:68 -msgid "Leave group" -msgstr "" - -#: /views/users/login.ctp:11 -msgid "Remember Me" -msgstr "eingeloggt bleiben" - -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "Account Registrierung" - -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" -msgstr "Bitte wähle einen Benutzernamen der nicht bereits verwendet wird" - -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "Es müssen mindestens 3 Zeichen eingegeben werden" - -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "Der Benutzername darf nur Zahlen und Buchstaben enthalten" - -#: /views/users/register.ctp:13 -msgid "Please choose username" -msgstr "Bitte wähle einen Benutzernamen" - -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" -msgstr "E-Mail (wird als Login verwendet)" - -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" -msgstr "Es mußt eine gültige Email-Adresse sein" - -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" -msgstr "Ein Account mit dieser Email-Adresse existiert bereits" - -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" -msgstr "" - -#: /views/users/register.ctp:23 -msgid "Password (confirm)" -msgstr "Passwort (bestätigen)" - -#: /views/users/register.ctp:25 -msgid "Passwords must match" -msgstr "Die Passwörter müssen gleich sein" - -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " -msgstr "" - -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" -msgstr "AGB" - -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" -msgstr "Du must bestätigen das Du die Nutzungsbedingungen gelesen hast" - -#: /views/users/register.ctp:46 -msgid "Openid Identifier" -msgstr "OpenID Identifikation" - -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" -msgstr "Passwort vergessen?" - -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Bitte gib die Email ein welche Du zur Registierung verwendet hast und Du wirst eine Email mit weiteren Instruktionen bekommen." - -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" -msgstr "Deine Email" - -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" -msgstr "Resette Dein Passwort" - -#: /views/users/search.ctp:1 -msgid "Search for users" -msgstr "Nach Benutzern suchen" - -#: View/Users/login.ctp:26 -msgid "I forgot my password" -msgstr "Ich habe mein Passwort vergessen" \ No newline at end of file diff --git a/Locale/fra/LC_MESSAGES/users.po b/Locale/fra/LC_MESSAGES/users.po deleted file mode 100644 index 68c87262c..000000000 --- a/Locale/fra/LC_MESSAGES/users.po +++ /dev/null @@ -1,713 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: CakePHP Users Plugin\n" -"POT-Creation-Date: 2010-09-15 15:48+0200\n" -"PO-Revision-Date: \n" -"Last-Translator: Pierre MARTIN \n" -"Language-Team: CakeDC \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: French\n" - -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "Détail invalide." - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "Sauvegardé" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "%s détails sauvegardés" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "Id invalide pour le Détail" - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "Détail supprimé" - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "Le Détail a été sauvegardé" - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "Le Détail ne peut pas être sauvegardé. Merci de réessayer." - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "Détail Invalide" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "Profil sauvegardé" - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "Le profil n'a pas pu être sauvegardé" - -#: /controllers/users_controller.php:193 -msgid "Invalid User." -msgstr "Utilisateur invalide." - -#: /controllers/users_controller.php:207 -msgid "The User has been saved" -msgstr "L'utilisateur a été sauvegardé" - -#: /controllers/users_controller.php:223 -msgid "User saved" -msgstr "Utilisateur sauvegardé" - -#: /controllers/users_controller.php:247 -msgid "User deleted" -msgstr "Utilisateur supprimé" - -#: /controllers/users_controller.php:249 -#: /models/user.php:703 -msgid "Invalid User" -msgstr "Utilisateur invalide" - -#: /controllers/users_controller.php:273 -msgid "You are already registered and logged in!" -msgstr "Vous êtes déjà enregistré et connecté !" - -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Votre compte a été créé. Vous devriez recevoir un email sous peu pour authentifier votre compte. Une fois le compte validé vous pourrez vous connecter." - -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 -msgid "Your account could not be created. Please, try again." -msgstr "Votre compte n'a pas pu être créé. Merci de réessayer." - -#: /controllers/users_controller.php:309 -msgid "%s you have successfully logged in" -msgstr "%s vous êtes désormais connecté" - -#: /controllers/users_controller.php:383 -msgid "%s you have successfully logged out" -msgstr "%s vous avez été déconnecté avec succès" - -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" -msgstr "L'url à laquelle vous essayez d'accéder n'est plus valide" - -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" -msgstr "Réinitialisation du Mot de passe" - -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" -msgstr "Votre mot de passe a été réinitialisé" - -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" -msgstr "Merci de vous connecter en utilisant ce mot de passe et de le modifier ensuite" - -#: /controllers/users_controller.php:438 -msgid "Your password was sent to your registered email account" -msgstr "Votre mot de passe a été envoyé à l'adresse email associée à votre compte" - -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 -msgid "Your e-mail has been validated!" -msgstr "Votre e-mail a été validé !" - -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "Il y a eu une erreur lors de la validation de votre adresse email. Veuillez vérifier dans vos email que l'URL à utiliser pour valider votre adresse est correcte." - -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 -msgid "The url you accessed is not longer valid" -msgstr "L'url à laquelle vous essayez d'accéder n'est plus valide" - -#: /controllers/users_controller.php:467 -msgid "Password changed." -msgstr "Mot de passe modifé." - -#: /controllers/users_controller.php:521 -msgid "Account verification" -msgstr "Vérification de compte" - -#: /controllers/users_controller.php:563 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "Un email a été envoyé à %s avec les instructions pour mettre à jour le mot de passe." - -#: /controllers/users_controller.php:567 -msgid "You should receive an email with further instructions shortly" -msgstr "Vous devriez recevoir un email sous peu avec de plus amples instructions" - -#: /controllers/users_controller.php:571 -msgid "No user was found with that email." -msgstr "Aucun utilisateur ayant cet adresse email n'a été trouvé." - -#: /controllers/users_controller.php:588 -msgid "Invalid password reset token, try again." -msgstr "Jeton de réinitialisation de mot de passe invalide. merci de réessayer." - -#: /controllers/users_controller.php:594 -msgid "Password changed, you can now login with your new password." -msgstr "Mot de passe changé, vous pouvez désormais vous connecter avec votre nouveau mot de passe." - -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "Veuillez saisir un nom d'utilisateur" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "Le nom d'utilisateur doit être alphanumérique" - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "Ce nom d'utilisateur est déjà utilisé." - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "Le nom d'utilisateur doit avoir au moins 3 caractères." - -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "Merci de saisir une adresse email valide." - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "Cet email est déjà utilisé." - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "Le mot de passe doit contenir au moins 8 caractères." - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "Veuillez entrer un mot de passe." - -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." -msgstr "Les mots de passe ne correspondent pas, merci de réessayer." - -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "Vous devez accepter les conditions d'utilisation." - -#: /models/user.php:137;357 -msgid "The passwords are not equal." -msgstr "Les mots de passe ne sont pas égaux." - -#: /models/user.php:139 -msgid "Invalid password." -msgstr "Mot de passe invalide." - -#: /models/user.php:150 -msgid "Invalid date" -msgstr "Date invalide" - -#: /models/user.php:315 -msgid "This Email Address exists but was never validated." -msgstr "Cette adresse email existe mais n'a jamais été validée." - -#: /models/user.php:317 -msgid "This Email Address does not exist in the system." -msgstr "Cette adresse email n'existe pas dans le système." - -#: /models/user.php:406 -msgid "$this->data['" -msgstr "$this->data['" - -#: /models/user.php:460 -msgid "The user does not exist." -msgstr "L'utilisateur n'existe pas." - -#: /models/user.php:505 -msgid "Please enter your email address." -msgstr "Veuillez entrer votre adresse email." - -#: /models/user.php:515 -msgid "The email address does not exist in the system" -msgstr "Cette adresse email n'existe pas dans le système." - -#: /models/user.php:520 -msgid "Your account is already authenticated." -msgstr "Votre compte est déjà authentifié." - -#: /models/user.php:525 -msgid "Your account is disabled." -msgstr "Votre compte est désactivé." - -#: /tests/cases/controllers/users_controller.test.php:34 -msgid "Sorry, but you need to login to access this location." -msgstr "Désole, mais vous devez vous connecter pour accéder à cette page." - -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Combinaison e-mail / mot de passe incorrecte. Veuillez réessayer." - -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" -msgstr "testuser you have successfully logged in" - -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" -msgstr "floriank you have successfully logged out" - -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" -msgstr "Ajouter un Détail" - -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" -msgstr "Lister les Détails" - -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 -msgid "List Users" -msgstr "Lister les Utilisateurs" - -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "Nouvel Utilisateur" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "Lister les Groupes" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "Nouveau Groupe" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "Modifier le Détail" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" -msgstr "Effacer" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" -msgstr "Etes-vous sûr de vouloir supprimer # %s ?" - -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" -msgstr "Détails" - -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "Page %page% sur %pages%, affiche %current% enregistrements sur un total de %count%, commençant à l'enregistrement %start%, s'arrêtant au %end%" - -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" -msgstr "Actions" - -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" -msgstr "Voir" - -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" -msgstr "Modifier" - -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 -msgid "previous" -msgstr "précédent" - -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 -msgid "next" -msgstr "suivant" - -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" -msgstr "Nouveau Détail" - -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" -msgstr "Détail" - -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" -msgstr "Id" - -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" -msgstr "Utilisateur" - -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" -msgstr "Position" - -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" -msgstr "Champ" - -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" -msgstr "Valeur" - -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" -msgstr "Créé" - -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" -msgstr "Modifié" - -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" -msgstr "Supprimer le Détail" - -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" -msgstr "Groupes liés" - -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" -msgstr "Id d'Utilisateur" - -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" -msgstr "Est Public" - -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" -msgstr "Nom" - -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" -msgstr "Description" - -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" -msgstr "Envoyer" - -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" -msgstr "Email" - -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 -msgid "Password" -msgstr "Mot de passe" - -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 -msgid "Login" -msgstr "Identifiant" - -#: /views/elements/email/text/account_verification.ctp:2 -msgid "Hello %s," -msgstr "Bonjour %s," - -#: /views/elements/email/text/account_verification.ctp:4 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "pour valider votre compte, vous devez visiter l'URL ci-dessous sous 24 heures" - -#: /views/elements/email/text/password_reset_request.ctp:2 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "Une requête de réinitialisation de mot de passe a été envoyée. Pour modifier votre mot de passe cliquez sur le lien ci-dessous." - -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 -msgid "Add User" -msgstr "Ajouter un Utilisateur" - -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 -msgid "Edit User" -msgstr "Modifier un Utilisateur" - -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 -msgid "Users" -msgstr "Utilisateurs" - -#: /views/users/admin_index.ctp:4 -msgid "Filter" -msgstr "Filtre" - -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" -msgstr "Nom d'utilisateur" - -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 -msgid "Search" -msgstr "Recherche" - -#: /views/users/admin_view.ctp:24 -msgid "Delete User" -msgstr "Supprimer l'utilisateur" - -#: /views/users/change_password.ctp:1 -msgid "Change your password" -msgstr "Modifier votre mot de passe" - -#: /views/users/change_password.ctp:3 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "Merci de saisir votre ancien mot de passe pour des raisons de sécurité et ensuite votre nouveau mot de passe deux fois." - -#: /views/users/change_password.ctp:8 -msgid "Old Password" -msgstr "Ancien mot de passe" - -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 -msgid "New Password" -msgstr "Nouveau mot de passe" - -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 -msgid "Confirm" -msgstr "Confirmer" - -#: /views/users/dashboard.ctp:2 -msgid "Welcome" -msgstr "Bienvenue" - -#: /views/users/dashboard.ctp:3 -msgid "Recent broadcasts" -msgstr "Récents broadcasts" - -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "Mes Groupes" - -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "Créer un nouveau groupe" - -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "Inviter un utilisateur" - -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "Requêtes pour joindre" - -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "Mes propres groupes" - -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "Membres" - -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "Inviter l'utilisateur" - -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "Gérer l'étendue du Broadcast" - -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "Accéder" - -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "Addons" - -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "Groupes dont je suis membre" - -#: /views/users/groups.ctp:68 -msgid "Leave group" -msgstr "Quitter le Groupe" - -#: /views/users/login.ctp:11 -msgid "Remember Me" -msgstr "Se rappeler de moi" - -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "Création de compte" - -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" -msgstr "Veuillez sélectionner un nom d'utilisateur qui n'est pas déjà utilisé" - -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "Doit avoir au moins 3 caractères" - -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "Le nom d'utilisateur ne doit contenir que des nombres et lettres" - -#: /views/users/register.ctp:13 -msgid "Please choose username" -msgstr "Veuillez choisir un nom d'utilisateur" - -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" -msgstr "Email (utilisé comme identifiant)" - -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" -msgstr "Doit être une adresse email valide" - -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" -msgstr "Un compte avec cette adresse email existe déjà" - -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" -msgstr "Doit avoir au moins 5 caractères" - -#: /views/users/register.ctp:23 -msgid "Password (confirm)" -msgstr "Mot de passe (confirmation)" - -#: /views/users/register.ctp:25 -msgid "Passwords must match" -msgstr "Les mots de passe doivent correspondre" - -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " -msgstr "J'ai lu et accepte les " - -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" -msgstr "Conditions d'utilisation" - -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" -msgstr "Vous devez vérifier que vous ayez lu les Conditions d'utilisation" - -#: /views/users/register.ctp:46 -msgid "Openid Identifier" -msgstr "Identifiant Openid" - -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" -msgstr "Mot de passe oublié ?" - -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Veuillez saisir l'adresse email utilisée lors de l'inscription afin de recevoir un email contenant les instructions." - -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" -msgstr "Votre email" - -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" -msgstr "Réinitialiser votre mot de passe" - -#: /views/users/search.ctp:1 -msgid "Search for users" -msgstr "Rechercher des utilisateurs" - -#: View/Users/login.ctp:26 -msgid "I forgot my password" -msgstr "Mot de passe oublié" \ No newline at end of file diff --git a/Locale/nld/LC_MESSAGES/users.mo b/Locale/nld/LC_MESSAGES/users.mo deleted file mode 100644 index 6445b1044ba4b9d4b50d4d74124f666315d72555..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9670 zcmbW6ZHyh)S;tS)1QOHG(uO7tc{!%t#3sAfyK&;icAWTa?QCm%-Sw^=CnaU>y=U*v z-nlcInYnwt29W@Q3Xo7gqynLWKoy8L2~@QbQh};!g-Qf`D565D2xiCc1m6ul1l|fB1GV2t@HX%qsCg^k4}w=gotuH0cMa73KMmds{xYcjJ_WuF z{0mTgeg%92{73Me;Qb8l1LwgX0Iz~;U>DT>p9dk?yb6krzXe6dSF7=_gZK0PFQDe# z!6BmmE|4zs9`F|MAy9JNU-h2@3*N7SI_IxI(eoAX`@w$(kAkm*qU$j_?*Y$L_z_V0 zxdyhtPkkAwTF_ZL9^ z8ONWy!ELYs{t~zV{%Q68EpU$a2RKyY=Rn!rkAu?3uYi*GAA;iN??B1r-$1Rq3n9D+ zo&@K?PlJzw{{)KOdtl;0@DOOh%b?^v0449A0HueY2PM~6Kz@U7q< zfwI?6gOcZK;4$zPj7j?(2PKCOg1-p<6ezpC6C->Ncn}ml=Rxt)1I6#pf$s-D32OhZ zR(KmiIK%q^aPuw55k$r2YY6oU_$^TD&$8JAU>hvKp8+Awybek~Z{u*`yFf%^?yYbR z{1M)dgF3ehLbCaIg}(<%E}sL%-E-W{4?NFyuVt#-|<7(8t)H)+V?o9@ikEAzXD>S=C?qd z_Zd*<{aJ-y0xj=f2BrUh2c>5TQR{C5rRR5p`@nla?RN_7ftNtZ;qxFWGJgq*-milv z!T+rK4`Y0?-(?Vyn01hU=4JkDg1-)G{T(Q6349QI5{yCd_1mDnkh2ESPaCEt&NTK~J? zVeoSxDlq>Aiq5;3^aS`JumFDn)c)TFwf}yc)PgTm_!208`3+F|_#!B}{<^|%fP^IT zZBX*PlgZ-io(dlXZ{htRQ1-GPlsqngN5BE7eLn@hAN&*WCGbB$STrSzblxkV^zjFv z`1$h+zXl%X{eM7~m}5AtFap*8v*266by`fTAIbV7)r<5i-+~3N8+AWLlU(ZOA%2L? z4((x@XsMr5)sF5?{ zTcIt|WV_2W#a=y%_2+48df`cFAEse;<{VAWChZ{YI8Dz1+O4!JG}&tXNZyFeoTWvy z57AE3^!zC8dD<3jmG)z_Gqk5^_t6ON-rqLBL$nr6k97M%nru>jq9+UB|Drzc2YUGc zO}dwTv}q@3^&{K4T)oKNZlTGZWxMhV*@m8HXoOJj3-S|7+x+jK6qg-c5trPlSLII)Ac+^}(4 zlzG2Z##w61%;v6er7bsHoZGFaC%-c%%j5O96^R=<1%=0LXHK-+cCB#v@CPHQjjEMi7Uf1%R#oH`$;{jn z0`t|6LBw%z(RPU|oqeyJDV{c`0>!o5>h}o_%&9D0kMo{6#Q~*jo6~*=vpDB1n-GkV3*n-zXVa`cC`YXFWpS3YNba}qdgr>8R z4FU}3RRT2UcWh;-=0enS=7Jm8i_3*2hnYG16Hi*-XooV&+92RGgU<*GkEX4Ym-dkqSbr~hhFQdHF0zyETi5k?$ zUKmm}GQ-aqGo-ivVfVFyLGK@q*%bwm(Q9zz_N>w2SMbz z;Ddycj2k%*!7WUbgeL`9?NGU)^(-kQCR^N&{T>$4nl@#U>w~+whEs`C{w6txFufyd z_QI^L@m+G3AqG{*px#W#UzLjl8zyf+iN!81C(T3*-LN2}4&I(cdg{1Zg6MSbS4#qU ztgRCc%nxV(PNU&=8m?xh4|dYe?hR!8#(O}>QQG09@Lr&PMM>XRn9H#nm@6*fvUcXG zE6i2oCF`m;4Ka{AGvo^RWJvq=`k7wGK7Ua9AgN=m!5yKn;pcEE$$z+CTuc^u^T4TV zEH9HCt|fh!9^1CCb z4y|rEZIL-BXOe2Y>kMM92-$rzK^$4Q@4P4opH!kJz)A09VVExFjFvitN}Yw=zdUf4t*Is5z>E z29Ea>8>F2++1%W!i+V@wp7TrR7e~Y|H0JkEJFtRNcD5k5bl1uQTM23OQ6DbRuf?&Y3#*G~7gvsQlW6?d z;eJ_(Q9k*W->$8`e%t%@FJ@?|9a-SI<1enOg%=F59w^!d5!qBI zO{W#56rt3lgjWyi=5ppbq>;_MA9wMgGIP_qM0_1FBsvVph6oVpX5w_6OD>ua!Wr+| z>rUGdi}|!bRrCI-v)(l6|Raa$TzyN;VE&-mz)V9bgz2>Bv42Z1q{Bw#}ugqz#2lmYda# z;%}%U72*DlPt96fR=>_VbdEPt=H5)A=Mn2ztsC{s1&LrxQWU?=Ec#H<3A(Ahz^kqP z4&!Bvkos^jk{YEY)pu0azS|@dz6@6JJ1Tm8cU9?TOAH!!cbvJnjgwuEEw63 z#~W^0VyKi>S(-FPtd_OWIUd>R<;Fr03gMm*+2@S}a0sOiW7(vl#hG1931t!KDkZIB zag=E06nUM~HyJNag~&1aKyI}I3&;A$E*NT8RlAfvaY-oAU5OGy!OM5C-1A$fJy7QT>@R+BGrgeB6HbY^&p#ET*1OI2`GqzCIABFMcIEU;I-2 zo^>6JJhfedgCE!DVBSZ&O$l?0A#>)?p+pEk;qGtPQ~qNddZ_AO-ELzl@ghJ6h?Wo2 z4of^_yVSp3)xXtM2j{29J%t?<#{-3ga-=hbteY;;rlB4VSwNC)Nyzk)WzKT#VjQ-L z&feggP6>rRN{UyBFOj9^)kUL~LvI}3(wf&W;(9n%cu(!>qY4QlBjTUW%ARFjTk$42 z+>rZ;eZ$%trFL+d)QGnm&aIb-tF;k4I26-Z4fPzRi1iZy_#@itL*M(J@bKx06-$CJPzW=qOa1LIwS|4s zvNr4mzN(KUGG11?M??0D%2^QZ)W$g7L7BU(W|BVqtwWH-FX{KjDvzF6qLHyM<%jEZ z=*\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -"X-Generator: Poedit 1.5.5\n" - -#: Controller/UsersController.php:310 -msgid "Invalid User." -msgstr "Ongeldige gebruiker." - -#: Controller/UsersController.php:328 -msgid "The User has been saved" -msgstr "Gebruiker is opgeslagen" - -#: Controller/UsersController.php:345 -msgid "User saved" -msgstr "Gebruiker is opgeslagen" - -#: Controller/UsersController.php:369 -msgid "User deleted" -msgstr "Gebruiker is verwijderd" - -#: Controller/UsersController.php:371 Model/User.php:821 -msgid "Invalid User" -msgstr "Ongeldige gebruiker" - -#: Controller/UsersController.php:393 -msgid "You are already registered and logged in!" -msgstr "U bent al geregistreerd en ingelogd!" - -#: Controller/UsersController.php:401 -#: Test/Case/Controller/UsersControllerTest.php:342 -msgid "" -"Your account has been created. You should receive an e-mail shortly to " -"authenticate your account. Once validated you will be able to login." -msgstr "" -"Uw account is gecreëerd. U heeft een email ontvangen om uw account te " -"verifiëren. Na verificatie bent u instaat in te loggen." - -#: Controller/UsersController.php:406 -#: Test/Case/Controller/UsersControllerTest.php:357 -msgid "Your account could not be created. Please, try again." -msgstr "Uw account kon niet worden gecreëerd. Probeer opnieuw." - -#: Controller/UsersController.php:428 -msgid "%s you have successfully logged in" -msgstr "%s, u ben succesvol ingelogd" - -#: Controller/UsersController.php:444 -#: Test/Case/Controller/UsersControllerTest.php:316 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Ongeldig emailadress / wachtwoord combinatie. Probeer opnieuw." - -#: Controller/UsersController.php:510 -msgid "%s you have successfully logged out" -msgstr "%s, u bent succesvol uitgelogd" - -#: Controller/UsersController.php:524 -msgid "The email was resent. Please check your inbox." -msgstr "E-mail is nogmaals verstuurd. Check uw inbox." - -#: Controller/UsersController.php:527 -msgid "The email could not be sent. Please check errors." -msgstr "Gegeven kon niet worden opgeslagen. Probeer opnieuw." - -#: Controller/UsersController.php:550 -#: Test/Case/Controller/UsersControllerTest.php:374 -msgid "Your e-mail has been validated!" -msgstr "Uw email is geverifiëerd" - -#: Controller/UsersController.php:573 -msgid "The url you accessed is not longer valid" -msgstr "De URL, die u probeert te bezoeken, is niet langer geldig" - -#: Controller/UsersController.php:579 -msgid "Your password was sent to your registered email account" -msgstr "Uw wachtwoord is naar uw, bij ons geregistreerde, email gestuurd" - -#: Controller/UsersController.php:583 -msgid "" -"There was an error verifying your account. Please check the email you were " -"sent, and retry the verification link." -msgstr "" -"Er heeft zich een error voorgedaan bij de verificatie van uw account. Bekijk " -"uw e-mail en volg de verificatie link." - -#: Controller/UsersController.php:599;709 -msgid "Password Reset" -msgstr "Wachtwoord wijzigen" - -#: Controller/UsersController.php:616;780 -msgid "Password changed." -msgstr "Wachtwoord gewijzigd." - -#: Controller/UsersController.php:677 -msgid "Account verification" -msgstr "Account verificatie" - -#: Controller/UsersController.php:736 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "" -"Er is een email naar %s verstuurd met instructies om zijn/haar wachtwoord te " -"wijzigen. " - -#: Controller/UsersController.php:740 -msgid "You should receive an email with further instructions shortly" -msgstr "Er is een email verstuurd met verder te volgen instructies" - -#: Controller/UsersController.php:744 -msgid "No user was found with that email." -msgstr "Er is geen gebruiker met dat emailadres." - -#: Controller/UsersController.php:774 -msgid "Invalid password reset token, try again." -msgstr "Ongeldige token, probeer opnieuw." - -#: Controller/UsersController.php:783 -msgid "Password changed, you can now login with your new password." -msgstr "Wachtwoord gewijzigd. U kunt nu inloggen met uw nieuwe wachtwoord." - -#: Controller/Component/RememberMeComponent.php:230 -msgid "Invalid options %s" -msgstr "Ongeldig wachtwoord." - -#: Model/User.php:158;339 -msgid "The passwords are not equal." -msgstr "De wachtwoorden zijn niet gelijk." - -#: Model/User.php:160 -msgid "Invalid password." -msgstr "Ongeldig wachtwoord." - -#: Model/User.php:242 Test/Case/Controller/UsersControllerTest.php:382 -msgid "" -"Invalid token, please check the email you were sent, and retry the " -"verification link." -msgstr "Ongeldige token. Bekijk uw e-mail en volg de verificatie link." - -#: Model/User.php:247 -msgid "The token has expired." -msgstr "De token is verlopen." - -#: Model/User.php:301 -msgid "This Email Address exists but was never validated." -msgstr "Dit emailadres bestaat, maar is nooit geverifiëerd." - -#: Model/User.php:303 -msgid "This Email Address does not exist in the system." -msgstr "Dit emailadres bestaat niet in dit systeem" - -#: Model/User.php:397 -msgid "$this->data['" -msgstr "$this->data['" - -#: Model/User.php:443 -msgid "The user does not exist." -msgstr "De gebruiker bestaat niet." - -#: Model/User.php:481 -msgid "Invalid Email address." -msgstr "Moet een geldig e-mailadres zijn" - -#: Model/User.php:486 -msgid "This email is already verified." -msgstr "Het emailadres is al in gebruik." - -#: Model/User.php:554 -msgid "Please enter your email address." -msgstr "Vul uw emailadres in." - -#: Model/User.php:561 -msgid "The email address does not exist in the system" -msgstr "Het emailadres bestaat niet in dit systeem" - -#: Model/User.php:566 -msgid "Your account is already authenticated." -msgstr "Uw account is al geverifiëerd." - -#: Model/User.php:571 -msgid "Your account is disabled." -msgstr "Uw account is uitgezet." - -#: Test/Case/Controller/UsersControllerTest.php:55 -msgid "Sorry, but you need to login to access this location." -msgstr "U moet ingelogd zijn om deze locatie te bekijken." - -#: Test/Case/Controller/UsersControllerTest.php:275 -msgid "adminuser you have successfully logged in" -msgstr "testuser, u bent succesvol ingelogd" - -#: Test/Case/Controller/UsersControllerTest.php:401 -msgid "testuser you have successfully logged out" -msgstr "testuser, u bent succesvol ingelogd" - -#: View/Elements/Users/admin_sidebar.ctp:3 View/Elements/Users/sidebar.ctp:9 -msgid "Logout" -msgstr "Uitloggen" - -#: View/Elements/Users/admin_sidebar.ctp:4 View/Elements/Users/sidebar.ctp:10 -msgid "My Account" -msgstr "Mijn Account" - -#: View/Elements/Users/admin_sidebar.ctp:6 -msgid "Add Users" -msgstr "Voeg gebruiker toe" - -#: View/Elements/Users/admin_sidebar.ctp:7 View/Elements/Users/sidebar.ctp:15 -msgid "List Users" -msgstr "Toon gebruikers" - -#: View/Elements/Users/admin_sidebar.ctp:9 -msgid "Frontend" -msgstr "Frontend" - -#: View/Elements/Users/sidebar.ctp:4 View/Users/login.ctp:13 -msgid "Login" -msgstr "Inloggen" - -#: View/Elements/Users/sidebar.ctp:6 -msgid "Register an account" -msgstr "Registreer een account" - -#: View/Elements/Users/sidebar.ctp:11 -msgid "Change password" -msgstr "Wijzig uw wachtwoord" - -#: View/Emails/text/account_verification.ctp:12 -msgid "Hello %s," -msgstr "Hallo %s," - -#: View/Emails/text/account_verification.ctp:14 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "Om uw account te verifiëren, volg binnen 24 uur de volgende URL" - -#: View/Emails/text/new_password.ctp:12 -msgid "Your password has been reset" -msgstr "Uw wachtwoord is gewijzigd" - -#: View/Emails/text/new_password.ctp:13 -msgid "Please login using this password and change your password" -msgstr "Login met dit wachtwoord om daarna uw wachtwoord te wijzigen" - -#: View/Emails/text/new_password.ctp:15 -msgid "Your new password is: %s" -msgstr "Uw wachtwoord is gewijzigd" - -#: View/Emails/text/password_reset_request.ctp:12 -msgid "" -"A request to reset your password was sent. To change your password click the " -"link below." -msgstr "" -"Een verzoek om uw wachtwoord te wijzigen is verstuurd. Om uw wachtwoord te " -"wijzigen klik op de beneden staande link." - -#: View/Users/add.ctp:13 View/Users/admin_add.ctp:15 -msgid "Add User" -msgstr "Voeg gebruiker toe" - -#: View/Users/add.ctp:18 View/Users/admin_add.ctp:18 -#: View/Users/admin_edit.ctp:19 View/Users/admin_index.ctp:18 -#: View/Users/admin_view.ctp:15 View/Users/search.ctp:18 -#: View/Users/view.ctp:15 -msgid "Username" -msgstr "Gebruikersnaam" - -#: View/Users/add.ctp:20 View/Users/admin_add.ctp:20 -msgid "E-mail (used as login)" -msgstr "E-mail (gebruik als login)" - -#: View/Users/add.ctp:21 View/Users/admin_add.ctp:21 -msgid "Must be a valid email address" -msgstr "Moet een geldig e-mailadres zijn" - -#: View/Users/add.ctp:22 View/Users/admin_add.ctp:22 -msgid "An account with that email already exists" -msgstr "Een account met dit e-mailadres bestaat al" - -#: View/Users/add.ctp:24 View/Users/admin_add.ctp:24 View/Users/login.ctp:23 -msgid "Password" -msgstr "Wachtwoord" - -#: View/Users/add.ctp:27 View/Users/admin_add.ctp:27 -msgid "Password (confirm)" -msgstr "Wachtwoord (bevestig)" - -#: View/Users/add.ctp:29 -msgid "Terms of Service" -msgstr "Gebruikersvoorwaarden" - -#: View/Users/add.ctp:31 -msgid "I have read and agreed to " -msgstr "Ik heb gelezen en ga akkoord met de " - -#: View/Users/add.ctp:32 View/Users/change_password.ctp:26 -#: View/Users/edit.ctp:25 View/Users/login.ctp:30 -#: View/Users/request_password_change.ctp:22 -#: View/Users/resend_verification.ctp:22 View/Users/reset_password.ctp:14 -msgid "Submit" -msgstr "Opslaan" - -#: View/Users/admin_add.ctp:31 View/Users/admin_edit.ctp:24 -msgid "Role" -msgstr "Rol" - -#: View/Users/admin_add.ctp:34 View/Users/admin_edit.ctp:27 -msgid "Is Admin" -msgstr "Is Administrator" - -#: View/Users/admin_add.ctp:36 View/Users/admin_edit.ctp:29 -msgid "Active" -msgstr "Actief" - -#: View/Users/admin_edit.ctp:15 View/Users/edit.ctp:15 -msgid "Edit User" -msgstr "Wijzig gebruiker" - -#: View/Users/admin_edit.ctp:21 View/Users/admin_index.ctp:19 -#: View/Users/login.ctp:21 View/Users/search.ctp:20 -msgid "Email" -msgstr "E-mail" - -#: View/Users/admin_index.ctp:13 View/Users/index.ctp:13 -#: View/Users/search.ctp:13 -msgid "Users" -msgstr "Gebruikers" - -#: View/Users/admin_index.ctp:15 -msgid "Filter" -msgstr "Filter" - -#: View/Users/admin_index.ctp:20 View/Users/search.ctp:23 -msgid "Search" -msgstr "Zoeken" - -#: View/Users/admin_index.ctp:32 View/Users/index.ctp:25 -#: View/Users/search.ctp:35 -msgid "Actions" -msgstr "Acties" - -#: View/Users/admin_index.ctp:50;53 -msgid "Yes" -msgstr "Ja" - -#: View/Users/admin_index.ctp:50;53 -msgid "No" -msgstr "Nee" - -#: View/Users/admin_index.ctp:59 View/Users/index.ctp:39 -#: View/Users/search.ctp:49 -msgid "View" -msgstr "Bekijk" - -#: View/Users/admin_index.ctp:60 View/Users/search.ctp:50 -msgid "Edit" -msgstr "Wijzig" - -#: View/Users/admin_index.ctp:61 View/Users/search.ctp:52 -msgid "Delete" -msgstr "Verwijder" - -#: View/Users/admin_index.ctp:61 View/Users/search.ctp:55 -msgid "Are you sure you want to delete # %s?" -msgstr "Weet u zeker dat u # %s wilt verwijderen?" - -#: View/Users/admin_view.ctp:13 View/Users/view.ctp:13 -msgid "User" -msgstr "Gebruiker" - -#: View/Users/admin_view.ctp:20 View/Users/view.ctp:20 -msgid "Created" -msgstr "Gecreëerd" - -#: View/Users/admin_view.ctp:25 -msgid "Modified" -msgstr "Gewijzigd" - -#: View/Users/change_password.ctp:13 View/Users/edit.ctp:22 -msgid "Change your password" -msgstr "Wijzig uw wachtwoord" - -#: View/Users/change_password.ctp:14 -msgid "" -"Please enter your old password because of security reasons and then your new " -"password twice." -msgstr "" -"Vul eerst uw oude wachtwoord in. En daarna tweemaal uw nieuwe wachtwoord." - -#: View/Users/change_password.ctp:18 -msgid "Old Password" -msgstr "Oude wachtwoord" - -#: View/Users/change_password.ctp:21 View/Users/reset_password.ctp:9 -msgid "New Password" -msgstr "Nieuw wachtwoord" - -#: View/Users/change_password.ctp:24 View/Users/reset_password.ctp:12 -msgid "Confirm" -msgstr "Bevestig" - -#: View/Users/dashboard.ctp:13 -msgid "Welcome" -msgstr "Welkom" - -#: View/Users/dashboard.ctp:14 -msgid "Recent broadcasts" -msgstr "Recente uitzendingen" - -#: View/Users/index.ctp:17 View/Users/search.ctp:27 -msgid "" -"Page %page% of %pages%, showing %current% records out of %count% total, " -"starting on record %start%, ending on %end%" -msgstr "" -"Pagina %page% van %pages%, %current% van %count% objecten getoond, beginnend " -"bij %start%, eindigend bij %end%" - -#: View/Users/login.ctp:25 -msgid "Remember Me" -msgstr "Herinner mij" - -#: View/Users/login.ctp:26 -msgid "I forgot my password" -msgstr "Wachtwoord vergeten?" - -#: View/Users/request_password_change.ctp:13 -msgid "Forgot your password?" -msgstr "Wachtwoord vergeten?" - -#: View/Users/request_password_change.ctp:14 -#: View/Users/resend_verification.ctp:14 -msgid "" -"Please enter the email you used for registration and you'll get an email " -"with further instructions." -msgstr "" -"Vul het door u bij ons geregistreerde e-mailadres in om een e-mail met te " -"volgen instructies te ontvangen." - -#: View/Users/request_password_change.ctp:21 -#: View/Users/resend_verification.ctp:21 -msgid "Your Email" -msgstr "Uw E-mail" - -#: View/Users/resend_verification.ctp:13 -msgid "Resend the Email Verification" -msgstr "Verstuur nogmaals de e-mail verificatie." - -#: View/Users/reset_password.ctp:2 -msgid "Reset your password" -msgstr "Wijzig uw wachtwoord" - -#: View/Users/search.ctp:22 -msgid "Name" -msgstr "Naam" - -#: Model/User.php:validation for field username -msgid "Please enter a username." -msgstr "Vul een gebruikersnaam in" - -#: Model/User.php:validation for field username -msgid "The username must be alphanumeric." -msgstr "Een gebruikersnaam kan alleen uit letters en cijfers bestaan" - -#: Model/User.php:validation for field username -msgid "This username is already in use." -msgstr "De gebruikersnaam is al in gebruik." - -#: Model/User.php:validation for field username -msgid "The username must have at least 3 characters." -msgstr "De gebruikersnaam moet uit minstens 3 karakters bestaan." - -#: Model/User.php:validation for field email -msgid "Please enter a valid email address." -msgstr "Vul een geldig emailadres in." - -#: Model/User.php:validation for field email -msgid "This email is already in use." -msgstr "Het emailadres is al in gebruik." - -#: Model/User.php:validation for field password -msgid "The password must have at least 6 characters." -msgstr "Een wachtwoord moet uit minstens 6 karakters bestaan." - -#: Model/User.php:validation for field password -msgid "Please enter a password." -msgstr "Vul een wachtwoord in." - -#: Model/User.php:validation for field temppassword -msgid "The passwords are not equal, please try again." -msgstr "De wachtwoorden zijn niet gelijk. Probeer opnieuw." - -#: Model/User.php:validation for field tos -msgid "You must agree to the terms of use." -msgstr "Ga akkoord met de gebruikersvoorwaarden." - -#~ msgid "Invalid Detail." -#~ msgstr "Ongeldige gegevens." - -#~ msgid "Saved" -#~ msgstr "Opgeslagen" - -#~ msgid "%s details saved" -#~ msgstr "%s gegevens opgeslagen" - -#~ msgid "Invalid id for Detail" -#~ msgstr "Ongeldige id voor Gegeven" - -#~ msgid "User Detail deleted" -#~ msgstr "Gegeven verwijderd" - -#~ msgid "The Detail has been saved" -#~ msgstr "Gegeven is opgeslagen" - -#~ msgid "The Detail could not be saved. Please, try again." -#~ msgstr "Gegeven kon niet worden opgeslagen. Probeer opnieuw." - -#~ msgid "Invalid Detail" -#~ msgstr "Ongeldig gegeven" - -#~ msgid "Profile saved." -#~ msgstr "Profiel opgeslagen." - -#~ msgid "Could not save your profile." -#~ msgstr "Profiel kon niet worden opgeslagen." - -#~ msgid "Invalid date" -#~ msgstr "Ongeldige datum" - -#~ msgid "Add User Detail" -#~ msgstr "Voeg gegeven toe" - -#~ msgid "List Details" -#~ msgstr "Toon gegevens" - -#~ msgid "New User" -#~ msgstr "Nieuwe gebruiker" - -#~ msgid "Edit User Detail" -#~ msgstr "Wijzig gegeven" - -#~ msgid "User Details" -#~ msgstr "Toon gegevens" - -#~ msgid "New User Detail" -#~ msgstr "Voeg gegeven toe" - -#~ msgid "User Detail" -#~ msgstr "Voeg gegeven toe" - -#~ msgid "Id" -#~ msgstr "Id" - -#~ msgid "Position" -#~ msgstr "Positie" - -#~ msgid "Field" -#~ msgstr "Veld" - -#~ msgid "Value" -#~ msgstr "Waarde" - -#~ msgid "Edit Detail" -#~ msgstr "Wijzig gegeven" - -#~ msgid "Delete Detail" -#~ msgstr "Verwijder gegeven" - -#~ msgid "New Detail" -#~ msgstr "Voeg gegeven toe" - -#~ msgid "There url you accessed is not longer valid" -#~ msgstr "De URL, die u probeert te bezoeken, is niet langer geldig" - -#~ msgid "" -#~ "There was an error trying to validate your e-mail address. Please check " -#~ "your e-mail for the URL you should use to verify your e-mail address." -#~ msgstr "" -#~ "Er is een error opgetreden bij het verifiëren van uw email. Controleer de " -#~ "email voor de URL die moet worden gevolgt om uw emailadres te verifiëren." - -#~ msgid "floriank you have successfully logged out" -#~ msgstr "floriank, u bent succesvol ingelogd" - -#~ msgid "List Groups" -#~ msgstr "Toon groepen" - -#~ msgid "New Group" -#~ msgstr "Nieuwe groep" - -#~ msgid "Details" -#~ msgstr "Gegevens" - -#~ msgid "previous" -#~ msgstr "vorige" - -#~ msgid "next" -#~ msgstr "volgende" - -#~ msgid "Detail" -#~ msgstr "Gegeven" - -#~ msgid "Related Groups" -#~ msgstr "Gerelateerde Groepen" - -#~ msgid "User Id" -#~ msgstr "Gebruiker Id" - -#~ msgid "Is Public" -#~ msgstr "Publiekelijk" - -#~ msgid "Description" -#~ msgstr "Omschrijving" - -#~ msgid "Delete User" -#~ msgstr "Verwijder Gebruiker" - -#~ msgid "My Groups" -#~ msgstr "Mijn Groepen" - -#~ msgid "Create a new group" -#~ msgstr "Creëer een nieuwe groep" - -#~ msgid "Invite a user" -#~ msgstr "Nodig een gebruiker uit" - -#~ msgid "Requests to join" -#~ msgstr "Uitnodigen" - -#~ msgid "My own groups" -#~ msgstr "Mijn eigen groepen" - -#~ msgid "Members" -#~ msgstr "Leden" - -#~ msgid "Invite user" -#~ msgstr "Nodig gebruiker uit" - -#~ msgid "Manage Broadcast Scope" -#~ msgstr "Beheer uitzending bereik" - -#~ msgid "Access" -#~ msgstr "Toegang" - -#~ msgid "Addons" -#~ msgstr "Toevoegingen" - -#~ msgid "Groups im a member in" -#~ msgstr "Groepen waartoe ik behoor" - -#~ msgid "Leave group" -#~ msgstr "Verlaat groep" - -#~ msgid "Account registration" -#~ msgstr "Account registratie" - -#~ msgid "Please select a username that is not already in use" -#~ msgstr "Vul een gebruikersnaam in die nog niet in gebruik is" - -#~ msgid "Must be at least 3 characters" -#~ msgstr "Moet minstens 3 karakters bevatten" - -#~ msgid "Username must contain numbers and letters only" -#~ msgstr "Gebruikers naam kan alleen letters en cijfers bevatten" - -#~ msgid "Please choose username" -#~ msgstr "Kies een gebruikersnaam" - -#~ msgid "Must be at least 5 characters long" -#~ msgstr "Moet minstens 5 karakters bevatten" - -#~ msgid "Passwords must match" -#~ msgstr "Wachtwoorden moeten gelijk zijn" - -#~ msgid "You must verify you have read the Terms of Service" -#~ msgstr "U moet akkoord gaan met de gebruikersvoorwaarden" - -#~ msgid "Openid Identifier" -#~ msgstr "Openid identificatie" - -#~ msgid "Search for users" -#~ msgstr "Zoek gebruikers" diff --git a/Locale/pt_BR/LC_MESSAGES/users.po b/Locale/pt_BR/LC_MESSAGES/users.po deleted file mode 100644 index ffb50702b..000000000 --- a/Locale/pt_BR/LC_MESSAGES/users.po +++ /dev/null @@ -1,722 +0,0 @@ -# LANGUAGE translation of the CakePHP Users plugin -# -# Copyright 2010, Cake Development Corporation (http://cakedc.com) -# -# Licensed under The MIT License -# Redistributions of files must retain the above copyright notice. -# -# @copyright Copyright 2010, Cake Development Corporation (http://cakedc.com) -# @license MIT License (http://www.opensource.org/licenses/mit-license.php) -# -msgid "" -msgstr "" -"Project-Id-Version: CakePHP Users Plugin\n" -"POT-Creation-Date: 2010-09-15 15:48+0200\n" -"PO-Revision-Date: 2014-01-25 14:40-0300\n" -"Last-Translator: Renan Gonçalves \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=2;plural=n>1;\n" -"X-Poedit-Language: Portuguese\n" -"X-Poedit-Country: BRAZIL\n" - -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "Detalhe inválido." - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "Salvo" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "%s detalhe salvo" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "ID inválido para Detalhe" - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "Detalhe removido" - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "O Detalhe foi salvo" - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "O Detalhe não pode ser salvo. Por favor, tente novamente." - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "Detalhe inválido" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "Perfil salvo." - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "Não foi possível salvar o perfil." - -#: /controllers/users_controller.php:193 -msgid "Invalid User." -msgstr "Usuário inválido." - -#: /controllers/users_controller.php:207 -msgid "The User has been saved" -msgstr "O Usuário foi salvo" - -#: /controllers/users_controller.php:223 -msgid "User saved" -msgstr "Usuário salvo" - -#: /controllers/users_controller.php:247 -msgid "User deleted" -msgstr "Usuário removido" - -#: /controllers/users_controller.php:249 -#: /models/user.php:703 -msgid "Invalid User" -msgstr "Usuário inválido" - -#: /controllers/users_controller.php:273 -msgid "You are already registered and logged in!" -msgstr "Você já está registrado e logado!" - -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Sua conta foi salva. Logo você receberá um e-mail para confirmar sua conta. Uma vez validada você poderá logar." - -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 -msgid "Your account could not be created. Please, try again." -msgstr "Sua conta não pôde ser criada. Por favor, tente novamente." - -#: /controllers/users_controller.php:309 -msgid "%s you have successfully logged in" -msgstr "%s você se logou com sucesso" - -#: /controllers/users_controller.php:383 -msgid "%s you have successfully logged out" -msgstr "%s você saiu com sucesso" - -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" -msgstr "Essa url que você acessou não é mais válida" - -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" -msgstr "Resetar senha" - -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" -msgstr "Sua senha foi resetada" - -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" -msgstr "Por favor faça o login usando esta senha e então mude-a o mais breve possível" - -#: /controllers/users_controller.php:438 -msgid "Your password was sent to your registered email account" -msgstr "Sua senha foi enviada para seu e-mail registrado em sua conta" - -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 -msgid "Your e-mail has been validated!" -msgstr "Seu e-mail foi validado!" - -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "Houve um erro ao tentar validar o seu endereço de e-mail. Por favor, verifique seu e-mail pela URL que você deve usar para verificar o seu endereço de e-mail." - -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 -msgid "The url you accessed is not longer valid" -msgstr "A url que você acessou não é mais válida" - -#: /controllers/users_controller.php:467 -msgid "Password changed." -msgstr "Senha alterada." - -#: /controllers/users_controller.php:521 -msgid "Account verification" -msgstr "Verificação de conta" - -#: /controllers/users_controller.php:563 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "%s foi enviado um email com instruções para redefinir sua senha." - -#: /controllers/users_controller.php:567 -msgid "You should receive an email with further instructions shortly" -msgstr "Você deverá receber um email com mais instruções em breve" - -#: /controllers/users_controller.php:571 -msgid "No user was found with that email." -msgstr "Não foi localizado nenhum usuário com esse e-mail." - -#: /controllers/users_controller.php:588 -msgid "Invalid password reset token, try again." -msgstr "Token para redefinição de senha inválido, tente novamente." - -#: /controllers/users_controller.php:594 -msgid "Password changed, you can now login with your new password." -msgstr "Senha alterada, você pode logar agora com sua nova senha." - -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "Por favor informe o nome de usuário" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "O nome de usuário deve ser alfanumérico" - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "Esse nome de usuário já está em uso." - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "O nome de usuário deve ter no mínimo 3 caracteres." - -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "Por favor informe um endereço de e-mail válido." - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "Esse e-mail já está em uso." - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "A senha deve ter no mínimo 8 caracteres." - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "Por favor informe a sua senha." - -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." -msgstr "As senhas devem ser idênticas, por favor verifique." - -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "Você deve aceitar os termos de uso." - -#: /models/user.php:137;357 -msgid "The passwords are not equal." -msgstr "As senhas não são iguais." - -#: /models/user.php:139 -msgid "Invalid password." -msgstr "Senha inválida." - -#: /models/user.php:150 -msgid "Invalid date" -msgstr "Data inválida" - -#: /models/user.php:315 -msgid "This Email Address exists but was never validated." -msgstr "Esse endereço de e-mail existe mas nunca foi validado." - -#: /models/user.php:317 -msgid "This Email Address does not exist in the system." -msgstr "Esse endereço de e-mail não existe no sistema." - -#: /models/user.php:406 -msgid "$this->data['" -msgstr "$this->data['" - -#: /models/user.php:460 -msgid "The user does not exist." -msgstr "O usuário não existe." - -#: /models/user.php:505 -msgid "Please enter your email address." -msgstr "Por favor informe seu endereço de e-mail." - -#: /models/user.php:515 -msgid "The email address does not exist in the system" -msgstr "O endereço de e-mail não existe no sistema" - -#: /models/user.php:520 -msgid "Your account is already authenticated." -msgstr "Sua conta já está autenticada." - -#: /models/user.php:525 -msgid "Your account is disabled." -msgstr "Sua conta foi desativada." - -#: /tests/cases/controllers/users_controller.test.php:34 -msgid "Sorry, but you need to login to access this location." -msgstr "Desculpe, mas você precisa logar para acessar esse local." - -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Combinação de e-mail/senha inválida. Por favor tente novamente." - -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" -msgstr "Usuário de teste você logou corretamente" - -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" -msgstr "Você realizou o logout com sucesso" - -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" -msgstr "Adicionar Detalhe" - -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" -msgstr "Listar Detalhes" - -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 -msgid "List Users" -msgstr "Listar Usuários" - -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "Novo Usuário" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "Listar Grupos" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "Novo Grupo" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "Editar Detalhe" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" -msgstr "Remover" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" -msgstr "Você tem certeza que deseja remover # %s?" - -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" -msgstr "Detalhes" - -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "Página %page% de %pages%, exibindo %current% resultados de um total de %count%, iniciando em %start%, terminando em %end%" - -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" -msgstr "Ações" - -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" -msgstr "Visualizar" - -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" -msgstr "Editar" - -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 -msgid "previous" -msgstr "anterior" - -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 -msgid "next" -msgstr "próximo" - -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" -msgstr "Novo Detalhe" - -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" -msgstr "Detalhe" - -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" -msgstr "Id" - -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" -msgstr "Usuário" - -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" -msgstr "Posição" - -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" -msgstr "Campo" - -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" -msgstr "Valor" - -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" -msgstr "Criação" - -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" -msgstr "Atualização" - -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" -msgstr "Remover Detalhe" - -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" -msgstr "Grupos relacionados" - -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" -msgstr "Id de Usuário" - -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" -msgstr "Público" - -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" -msgstr "Nome" - -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" -msgstr "Descrição" - -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" -msgstr "Enviar" - -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" -msgstr "E-mail" - -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 -msgid "Password" -msgstr "Senha" - -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 -msgid "Login" -msgstr "Login" - -#: /views/elements/email/text/account_verification.ctp:2 -msgid "Hello %s," -msgstr "Olá %s," - -#: /views/elements/email/text/account_verification.ctp:4 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "para validar a sua conta, você deve visitar a URL abaixo no prazo de 24 horas" - -#: /views/elements/email/text/password_reset_request.ctp:2 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "Uma solicitação para redefinir sua senha foi enviada. Para alterar sua senha, clique no link abaixo." - -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 -msgid "Add User" -msgstr "Adicionar Usuário" - -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 -msgid "Edit User" -msgstr "Editar Usuário" - -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 -msgid "Users" -msgstr "Usuários" - -#: /views/users/admin_index.ctp:4 -msgid "Filter" -msgstr "Filtro" - -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" -msgstr "Nome de usuário" - -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 -msgid "Search" -msgstr "Buscar" - -#: /views/users/admin_view.ctp:24 -msgid "Delete User" -msgstr "Remover Usuário" - -#: /views/users/change_password.ctp:1 -msgid "Change your password" -msgstr "Altera sua senha" - -#: /views/users/change_password.ctp:3 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "Por favor digite sua senha antiga por razões de segurança e depois sua nova senha duas vezes." - -#: /views/users/change_password.ctp:8 -msgid "Old Password" -msgstr "Senha antiga" - -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 -msgid "New Password" -msgstr "Nova senha" - -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 -msgid "Confirm" -msgstr "Confirmar" - -#: /views/users/dashboard.ctp:2 -msgid "Welcome" -msgstr "Bem-vindo(a)" - -#: /views/users/dashboard.ctp:3 -msgid "Recent broadcasts" -msgstr "Atualizações recentes" - -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "Meus Grupos" - -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "Criar um novo grupo" - -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "Convide um usuário" - -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "Convites para participar" - -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "Meus próprios grupos" - -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "Membros" - -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "Convite um usuário" - -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "Gerenciar escopo atualizações" - -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "Acesso" - -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "Módulos" - -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "Grupos em que sou membro" - -#: /views/users/groups.ctp:68 -msgid "Leave group" -msgstr "Deixar grupo" - -#: /views/users/login.ctp:11 -msgid "Remember Me" -msgstr "Lembrar-me" - -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "Registro de conta" - -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" -msgstr "Por favor selecione um nome de usuário que não esteja em uso" - -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "Tem que ter no mínimo 3 caracteres" - -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "Nome de usuário devem conter apenas números e letras" - -#: /views/users/register.ctp:13 -msgid "Please choose username" -msgstr "Por favor escolha o nome de usuário" - -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" -msgstr "E-mail (usado para logar)" - -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" -msgstr "O e-mail deve ser um endereço válido" - -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" -msgstr "Já existe uma conta com esse e-mail" - -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" -msgstr "Deve ter pelo menos 5 caracteres" - -#: /views/users/register.ctp:23 -msgid "Password (confirm)" -msgstr "Confirme sua senha" - -#: /views/users/register.ctp:25 -msgid "Passwords must match" -msgstr "As senhas devem ser idênticas" - -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " -msgstr "Eu li e concordo com " - -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" -msgstr "Termos de Serviço" - -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" -msgstr "Você deve verificar se leu os Termos de Serviços" - -#: /views/users/register.ctp:46 -msgid "Openid Identifier" -msgstr "Identificador OpenId" - -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" -msgstr "Esqueceu sua senha?" - -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Por favor entre com o e-mail usado no registro e você irá receber um e-mail com mais instruções." - -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" -msgstr "Seu E-mail" - -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" -msgstr "Redefinir sua senha" - -#: /views/users/search.ctp:1 -msgid "Search for users" -msgstr "Procurar por usuários" - diff --git a/Locale/rus/LC_MESSAGES/users.po b/Locale/rus/LC_MESSAGES/users.po deleted file mode 100644 index 3c02b5e58..000000000 --- a/Locale/rus/LC_MESSAGES/users.po +++ /dev/null @@ -1,711 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: CakePHP Users Plugin\n" -"POT-Creation-Date: 2010-09-16 16:33+0200\n" -"PO-Revision-Date: \n" -"Last-Translator: Evgeny Tomenko \n" -"Language-Team: CakeDC\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: Russian\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "Неверные данные." - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "Сохренено" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "%s параметр соханен" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "Неверные данные." - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "Данные удалены." - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "Данные сохранены." - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "Данные не удалось сохранить." - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "Неверные данные" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "Профиль обновлен" - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "Профиль сохранить не удалось." - -#: /controllers/users_controller.php:193 -msgid "Invalid User." -msgstr "Неуществующий пользователь." - -#: /controllers/users_controller.php:207 -msgid "The User has been saved" -msgstr "Пользователь был" - -#: /controllers/users_controller.php:223 -msgid "User saved" -msgstr "Данные пользователя сохранены" - -#: /controllers/users_controller.php:247 -msgid "User deleted" -msgstr "Данные о пользователе удалены" - -#: /controllers/users_controller.php:249 -#: /models/user.php:703 -msgid "Invalid User" -msgstr "Неуществующий пользователь" - -#: /controllers/users_controller.php:273 -msgid "You are already registered and logged in!" -msgstr "Вы уже зарегистрированы и авторизованы!" - -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Учетная запись успешно создана. Скоро вы получите e-mail, с помощью которого можно подтвердить аккаунт." - -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 -msgid "Your account could not be created. Please, try again." -msgstr "Учетную запись создать не удалось. Попробуйте позднее." - -#: /controllers/users_controller.php:309 -msgid "%s you have successfully logged in" -msgstr "%s, вы успешно авторизовались." - -#: /controllers/users_controller.php:383 -msgid "%s you have successfully logged out" -msgstr "%s, вы успешно покинули систему." - -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" -msgstr "Данная ссылка не доступна." - -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" -msgstr "Сбросить пароль" - -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" -msgstr "Ваш пароль был сброшен" - -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" -msgstr "Пожалуйста авторизуйтесь и измените пароль" - -#: /controllers/users_controller.php:438 -msgid "Your password was sent to your registered email account" -msgstr "Ваш пароль был отправлен на ваш почтовый адрес." - -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 -msgid "Your e-mail has been validated!" -msgstr "Ваш e-mail был подтвержен!" - -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "При попытке подтвердить ваш электронный адрес произошла ошибка. Убедитесь что вы используете правильную ссылку для подтверждения своего почтового адреса." - -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 -msgid "The url you accessed is not longer valid" -msgstr "Данный адрес более не доступен." - -#: /controllers/users_controller.php:467 -msgid "Password changed." -msgstr "Пароль изменен." - -#: /controllers/users_controller.php:521 -msgid "Account verification" -msgstr "Проверка учетной записи" - -#: /controllers/users_controller.php:563 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "%s. Вам была отправлена инструкция для сброса пароля." - -#: /controllers/users_controller.php:567 -msgid "You should receive an email with further instructions shortly" -msgstr "Вскоре вы получите письмо с дальнейшими инстукциями." - -#: /controllers/users_controller.php:571 -msgid "No user was found with that email." -msgstr "С данным почтовым адресом не зарегистрирован ни один пользователь." - -#: /controllers/users_controller.php:588 -msgid "Invalid password reset token, try again." -msgstr "Неверный код сброса пароля, попробуйте еще раз." - -#: /controllers/users_controller.php:594 -msgid "Password changed, you can now login with your new password." -msgstr "Пароль изменен, вы можете авторизоваться с вашим новым паролем." - -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "Задайте имя пользователя" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "Имя пользователя должно snm буквенно-цифровым." - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "Данное имя пользователя уже используется." - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "Имя пользователя должено содержать как минимум 3 символа." - -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "Введите допустимый почтовый адрес." - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "Данный почтовый адрес занят." - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "Длина пароль должена быть не менее 8 символов." - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "Введите пароль." - -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." -msgstr "Пароли не совпадают, попробуйте еще раз." - -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "Вы должны подтвердить согласие с правилами пользования сервисом." - -#: /models/user.php:137;357 -msgid "The passwords are not equal." -msgstr "Пароли не совпадают." - -#: /models/user.php:139 -msgid "Invalid password." -msgstr "Неверный пароль." - -#: /models/user.php:150 -msgid "Invalid date" -msgstr "Неверная дата" - -#: /models/user.php:315 -msgid "This Email Address exists but was never validated." -msgstr "Почтовый адрес существует, но не подтвержден." - -#: /models/user.php:317 -msgid "This Email Address does not exist in the system." -msgstr "Почтовый адрес системе не известен." - -#: /models/user.php:406 -msgid "$this->data['" -msgstr "" - -#: /models/user.php:460 -msgid "The user does not exist." -msgstr "Пользователь не существует." - -#: /models/user.php:505 -msgid "Please enter your email address." -msgstr "Пожалуйста, заполните почтовый адрес" - -#: /models/user.php:515 -msgid "The email address does not exist in the system" -msgstr "Данный почтовый адрес системе не известен." - -#: /models/user.php:520 -msgid "Your account is already authenticaed." -msgstr "Ваша учетная запись уже подтверждена." - -#: /models/user.php:525 -msgid "Your account is disabled." -msgstr "Ваша учетная запись заблокирована." - -#: /tests/cases/controllers/users_controller.test.php:34 -msgid "Sorry, but you need to login to access this location." -msgstr "Вы должны авторизоваться, чтобы получить доступ к данной странице." - -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Неверный комбинация email и пароля, попробуйте еще раз." - -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" -msgstr "testuser вы успешно авторизовались" - -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" -msgstr "floriank вы успешно завершили сессию" - -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" -msgstr "Добавить данные" - -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" -msgstr "Список данных" - -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 -msgid "List Users" -msgstr "Список пользователей" - -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "Новый пользователь" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "Список групп" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "Новая группа" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "Редактировать данные" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" -msgstr "Удалить" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" -msgstr "Вы действительно хотите удалить %s?" - -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" -msgstr "Данные" - -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "Страница %page% из %pages%, показано %current% записей из %count%, начиная с %start%,и заканчивая %end%" - -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" -msgstr "Действия" - -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" -msgstr "Просмотр" - -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" -msgstr "Редактировать" - -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 -msgid "previous" -msgstr "назад" - -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 -msgid "next" -msgstr "вперед" - -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" -msgstr "Новые данные" - -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" -msgstr "Данные" - -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" -msgstr "Id" - -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" -msgstr "Пользователь" - -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" -msgstr "Позиция" - -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" -msgstr "Поле" - -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" -msgstr "Значение" - -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" -msgstr "Дата создания" - -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" -msgstr "Дата изменения" - -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" -msgstr "Удалить данные" - -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" -msgstr "Связанные группы" - -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" -msgstr "Идентификатор пользователя" - -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" -msgstr "Публичное?" - -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" -msgstr "Название" - -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" -msgstr "Описание" - -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" -msgstr "Сохранить" - -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" -msgstr "Email" - -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 -msgid "Password" -msgstr "Пароль" - -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 -msgid "Login" -msgstr "Войти" - -#: /views/elements/email/text/account_verification.ctp:2 -msgid "Hello %s," -msgstr "Здравствуйте %s," - -#: /views/elements/email/text/account_verification.ctp:4 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "чтобы подтвердить вашу учетную запись, необходимо посетить слеждующую ссылку в течении 24 часов." - -#: /views/elements/email/text/password_reset_request.ctp:2 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "Запрос на сброс пароля отправлен. Чтобы сменить пароль воспользуйтесь следующей ссылкой:" - -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 -msgid "Add User" -msgstr "Добавить пользователя" - -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 -msgid "Edit User" -msgstr "Редактировать пользователя" - -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 -msgid "Users" -msgstr "Пользователи" - -#: /views/users/admin_index.ctp:4 -msgid "Filter" -msgstr "Фильтр" - -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" -msgstr "Имя пользователя" - -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 -msgid "Search" -msgstr "Поиск" - -#: /views/users/admin_view.ctp:24 -msgid "Delete User" -msgstr "Удалить пользователя" - -#: /views/users/change_password.ctp:1 -msgid "Change your password" -msgstr "Сменить ваш пароль" - -#: /views/users/change_password.ctp:3 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "По правилам безопасности необходимо указать ваш старый пароль, а затем дважды новый пароль." - -#: /views/users/change_password.ctp:8 -msgid "Old Password" -msgstr "Старый пароль" - -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 -msgid "New Password" -msgstr "Новый пароль" - -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 -msgid "Confirm" -msgstr "Подтвердить" - -#: /views/users/dashboard.ctp:2 -msgid "Welcome" -msgstr "Добро пожаловать" - -#: /views/users/dashboard.ctp:3 -msgid "Recent broadcasts" -msgstr "Свежие рассылки" - -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "Мои группы" - -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "Создать новую группу" - -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "Пригласить пользователя" - -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "Запрос на присоединение" - -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "Мои группы" - -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "Участники" - -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "Пригласить пользователя" - -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "Управление массовыми рассылками" - -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "Доступ" - -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "Плагины" - -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "Группы, в которых я состою" - -#: /views/users/groups.ctp:68 -msgid "Leave group" -msgstr "Покинуть группу" - -#: /views/users/login.ctp:11 -msgid "Remember Me" -msgstr "Запомнить меня" - -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "Регистрация учетной записи" - -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" -msgstr "Выберете не используемое имя пользователя" - -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "Как минимум 3 символа" - -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "Имя пользователя должно содержать только буквы и цифры" - -#: /views/users/register.ctp:13 -msgid "Please choose username" -msgstr "Выберете имя пользователя" - -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" -msgstr "Email (используется для входа)" - -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" -msgstr "Укажите верный адрес email" - -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" -msgstr "Учетная запись с данным email уже существует" - -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" -msgstr "Должно быть как минимум 5 символов" - -#: /views/users/register.ctp:23 -msgid "Password (confirm)" -msgstr "Пароль (подтверждение)" - -#: /views/users/register.ctp:25 -msgid "Passwords must match" -msgstr "Пароли должны совпадать" - -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " -msgstr "Я прочитал и согласен с" - -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" -msgstr "правилами пользования сервисом" - -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" -msgstr "Необходимо подтвердить, что вы прочитали правила пользования сервисом." - -#: /views/users/register.ctp:46 -msgid "Openid Identifier" -msgstr "Идентификация Openid" - -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" -msgstr "Забыли пароль?" - -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Укажите email который использовался при регистрации и вы получите дальнейшие инструкции." - -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" -msgstr "Ваш почтовый адрес" - -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" -msgstr "Сбросить ваш пароль" - -#: /views/users/search.ctp:1 -msgid "Search for users" -msgstr "Поиск пользователей" - diff --git a/Locale/spa/LC_MESSAGES/users.po b/Locale/spa/LC_MESSAGES/users.po deleted file mode 100644 index 40898c3d6..000000000 --- a/Locale/spa/LC_MESSAGES/users.po +++ /dev/null @@ -1,716 +0,0 @@ -# LANGUAGE translation of the CakePHP Users plugin -# -# Copyright 2010, Cake Development Corporation (http://cakedc.com) -# -# Licensed under The MIT License -# Redistributions of files must retain the above copyright notice. -# -# @copyright Copyright 2010, Cake Development Corporation (http://cakedc.com) -# @license MIT License (http://www.opensource.org/licenses/mit-license.php) -# -msgid "" -msgstr "" -"Project-Id-Version: Users CakePHP plugin\n" -"POT-Creation-Date: 2013-09-18 23:20+0200\n" -"PO-Revision-Date: 2013-09-18 22:52-0000\n" -"Last-Translator: Jorge González \n" -"Language-Team: CakeDC \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: Controller/UsersController.php:310 -msgid "Invalid User." -msgstr "Usuario no válido" - -#: Controller/UsersController.php:328 -msgid "The User has been saved" -msgstr "El usuario ha sido guardado" - -#: Controller/UsersController.php:345 -msgid "User saved" -msgstr "Usuario guardado" - -#: Controller/UsersController.php:369 -msgid "User deleted" -msgstr "Usuario elimianado" - -#: Controller/UsersController.php:371 -#: Model/User.php:829;858 -msgid "Invalid User" -msgstr "Usuario no válido" - -#: Controller/UsersController.php:393 -msgid "You are already registered and logged in!" -msgstr "¡Ya estás registrado y has iniciado la sesión!" - -#: Controller/UsersController.php:413 -#: Test/Case/Controller/UsersControllerTest.php:342 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Su cuenta ha sido creada. Debería recibir un correo con un enlace para verificar su cuenta de correo. Una vez validado, podrá iniciar sesión." - -#: Controller/UsersController.php:418 -#: Test/Case/Controller/UsersControllerTest.php:357 -msgid "Your account could not be created. Please, try again." -msgstr "Su cuenta no pudo ser creada, por favor inténtelo de nuevo." - -#: Controller/UsersController.php:462 -msgid "%s you have successfully logged in" -msgstr "%s ha iniciado sesión" - -#: Controller/UsersController.php:483 -#: Test/Case/Controller/UsersControllerTest.php:316 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Combinación de email / contraseña no válida. Por favor, inténtelo de nuevo" - -#: Controller/UsersController.php:549 -msgid "%s you have successfully logged out" -msgstr "%s ha cerrado la sesión" - -#: Controller/UsersController.php:563 -msgid "The email was resent. Please check your inbox." -msgstr "Se ha reenviado el correo, por favor compruebe que le ha llegado a su bandeja de entrada." - -#: Controller/UsersController.php:566 -msgid "The email could not be sent. Please check errors." -msgstr "El email no se pudo enviar. Por favor compruebe los errores y/o la configuración de envío de emails." - -#: Controller/UsersController.php:589 -#: Test/Case/Controller/UsersControllerTest.php:374 -msgid "Your e-mail has been validated!" -msgstr "¡Su correo ha sido validado!" - -#: Controller/UsersController.php:612 -msgid "The url you accessed is not longer valid" -msgstr "El URL que accedió no es válido" - -#: Controller/UsersController.php:618 -msgid "Your password was sent to your registered email account" -msgstr "Su contraseña fue enviada a la cuenta de correo que utilizó al registrarse" - -#: Controller/UsersController.php:622 -msgid "There was an error verifying your account. Please check the email you were sent, and retry the verification link." -msgstr "Hubo un error al verificar su cuenta. Por favor utilice el enlace de verificación que le enviamos a su cuenta de correo." - -#: Controller/UsersController.php:638;748 -msgid "Password Reset" -msgstr "Contraseña reiniciada" - -#: Controller/UsersController.php:655;819 -msgid "Password changed." -msgstr "Contraseña modificada" - -#: Controller/UsersController.php:716 -msgid "Account verification" -msgstr "Verificación de cuenta" - -#: Controller/UsersController.php:775 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "%s, le hemos enviado un correo con instrucciones para reiniciar su contraseña." - -#: Controller/UsersController.php:779 -msgid "You should receive an email with further instructions shortly" -msgstr "Recibirá un correo con más instrucciones en breve" - -#: Controller/UsersController.php:783 -msgid "No user was found with that email." -msgstr "Ningún usuario fue encontrado con dicho correo." - -#: Controller/UsersController.php:813 -msgid "Invalid password reset token, try again." -msgstr "Contraseña no válida, por favor inténtelo de nuevo." - -#: Controller/UsersController.php:822 -msgid "Password changed, you can now login with your new password." -msgstr "Contraseña modificada, ahora puede acceder nuevamente." - -#: Controller/Component/RememberMeComponent.php:230 -msgid "Invalid options %s" -msgstr "Opciones no válidas %s" - -#: Controller/Component/Auth/TokenAuthenticate.php:67 -msgid "You need to specify token parameter and/or header" -msgstr "Necesita especificar un token y/o cabecera" - -#: Model/User.php:158;339 -msgid "The passwords are not equal." -msgstr "Las contraseñas no coinciden." - -#: Model/User.php:160 -msgid "Invalid password." -msgstr "Contraseña no válida." - -#: Model/User.php:242 -#: Test/Case/Controller/UsersControllerTest.php:382 -msgid "Invalid token, please check the email you were sent, and retry the verification link." -msgstr "Token inválido, por favor compruebe el correo de verificación que le enviamos a su cuenta y vuelva a intentarlo mediante el enlace que aparece en el contenido del mensaje." - -#: Model/User.php:247 -msgid "The token has expired." -msgstr "El token ha expirado." - -#: Model/User.php:301 -msgid "This Email Address exists but was never validated." -msgstr "La dirección de correo existe, pero nunca fue validada." - -#: Model/User.php:303 -msgid "This Email Address does not exist in the system." -msgstr "Esta dirección de correo no existe en el sistema." - -# Error? -#: Model/User.php:397 -msgid "$this->data['" -msgstr "$this->data['" - -#: Model/User.php:443 -msgid "The user does not exist." -msgstr "El usuario no existe." - -#: Model/User.php:481 -msgid "Invalid Email address." -msgstr "La cuenta de correo no es válida." - -#: Model/User.php:486 -msgid "This email is already verified." -msgstr "Este correo ya se ha verificado correctamente." - -#: Model/User.php:584 -msgid "Please enter your email address." -msgstr "Por favor introduce tu dirección de correo." - -#: Model/User.php:591 -msgid "The email address does not exist in the system" -msgstr "La dirección de correo no existe en el sistema" - -#: Model/User.php:596 -msgid "Your account is already authenticaed." -msgstr "Tu cuenta ya ha sido autenticada." - -#: Model/User.php:601 -msgid "Your account is disabled." -msgstr "Tu cuenta está deshabilitada" - -#: Test/Case/Controller/UsersControllerTest.php:55 -msgid "Sorry, but you need to login to access this location." -msgstr "Lo sentimos, pero debe iniciar sesión para acceder a esta ubicación" - -#: Test/Case/Controller/UsersControllerTest.php:275 -msgid "adminuser you have successfully logged in" -msgstr "adminuser has ingresado exitosamente" - -#: Test/Case/Controller/UsersControllerTest.php:401 -msgid "testuser you have successfully logged out" -msgstr "testuser has cerrado sesión" - -#: View/Elements/pagination.ctp:14 -msgid "previous" -msgstr "anterior" - -#: View/Elements/pagination.ctp:16 -msgid "next" -msgstr "siguiente" - -#: View/Elements/Users/admin_sidebar.ctp:3 -#: View/Elements/Users/sidebar.ctp:9 -msgid "Logout" -msgstr "Cerrar sesión" - -#: View/Elements/Users/admin_sidebar.ctp:4 -#: View/Elements/Users/sidebar.ctp:10 -msgid "My Account" -msgstr "Mi Cuenta" - -#: View/Elements/Users/admin_sidebar.ctp:6 -#, fuzzy -msgid "Add Users" -msgstr "Agregar usuario" - -#: View/Elements/Users/admin_sidebar.ctp:7 -#: View/Elements/Users/sidebar.ctp:15 -msgid "List Users" -msgstr "Listar usuarios" - -#: View/Elements/Users/admin_sidebar.ctp:9 -msgid "Frontend" -msgstr "Público" - -#: View/Elements/Users/sidebar.ctp:4 -#: View/Users/login.ctp:13 -msgid "Login" -msgstr "Nombre de Usuario" - -#: View/Elements/Users/sidebar.ctp:6 -msgid "Register an account" -msgstr "Registrar nueva cuenta" - -#: View/Elements/Users/sidebar.ctp:11 -#, fuzzy -msgid "Change password" -msgstr "Cambiar contraseña" - -#: View/Emails/text/account_verification.ctp:12 -msgid "Hello %s," -msgstr "Hola %s," - -#: View/Emails/text/account_verification.ctp:14 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "Para validar su cuenta, debe vistar el URL antes de 24 horas" - -#: View/Emails/text/new_password.ctp:12 -msgid "Your password has been reset" -msgstr "Su contraseña ha sido reiniciada" - -#: View/Emails/text/new_password.ctp:13 -msgid "Please login using this password and change your password" -msgstr "Por favor acceda usando esta contraseña y luego cámbiela" - -#: View/Emails/text/new_password.ctp:15 -msgid "Your new password is: %s" -msgstr "Su nueva contraseña es: %s" - -#: View/Emails/text/password_reset_request.ctp:12 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "Una solicitud para reiniciar la contraseña fue enviada. Para cambiarla haga click en el siguiente enlace" - -#: View/Users/add.ctp:13 -#: View/Users/admin_add.ctp:15 -msgid "Add User" -msgstr "Agregar usuario" - -#: View/Users/add.ctp:18 -#: View/Users/admin_add.ctp:18 -#: View/Users/admin_edit.ctp:19 -#: View/Users/admin_index.ctp:18 -#: View/Users/admin_view.ctp:15 -#: View/Users/search.ctp:18 -#: View/Users/view.ctp:15 -msgid "Username" -msgstr "Nombre de Usuario" - -#: View/Users/add.ctp:20 -#: View/Users/admin_add.ctp:20 -msgid "E-mail (used as login)" -msgstr "Correo (usado para acceder)" - -#: View/Users/add.ctp:21 -#: View/Users/admin_add.ctp:21 -msgid "Must be a valid email address" -msgstr "Debe ser una cuenta de correo válida" - -#: View/Users/add.ctp:22 -#: View/Users/admin_add.ctp:22 -msgid "An account with that email already exists" -msgstr "Una cuenta con dicho correo ya existe" - -#: View/Users/add.ctp:24 -#: View/Users/admin_add.ctp:24 -#: View/Users/login.ctp:23 -msgid "Password" -msgstr "Contraseña" - -#: View/Users/add.ctp:27 -#: View/Users/admin_add.ctp:27 -msgid "Password (confirm)" -msgstr "Contraseña (confirmación)" - -#: View/Users/add.ctp:29 -msgid "Terms of Service" -msgstr "Condiciones del Servicio" - -#: View/Users/add.ctp:31 -msgid "I have read and agreed to " -msgstr "He leído y estoy de acuerdo con las " - -#: View/Users/add.ctp:32 -#: View/Users/change_password.ctp:26 -#: View/Users/edit.ctp:25 -#: View/Users/login.ctp:30 -#: View/Users/request_password_change.ctp:22 -#: View/Users/resend_verification.ctp:22 -#: View/Users/reset_password.ctp:14 -msgid "Submit" -msgstr "Enviar" - -#: View/Users/admin_add.ctp:31 -#: View/Users/admin_edit.ctp:24 -msgid "Role" -msgstr "Rol" - -#: View/Users/admin_add.ctp:34 -#: View/Users/admin_edit.ctp:27 -msgid "Is Admin" -msgstr "Es Admin" - -#: View/Users/admin_add.ctp:36 -#: View/Users/admin_edit.ctp:29 -msgid "Active" -msgstr "Activo" - -#: View/Users/admin_edit.ctp:15 -#: View/Users/edit.ctp:15 -msgid "Edit User" -msgstr "Editar Usuario" - -#: View/Users/admin_edit.ctp:21 -#: View/Users/admin_index.ctp:19 -#: View/Users/login.ctp:21 -#: View/Users/search.ctp:20 -msgid "Email" -msgstr "Correo" - -#: View/Users/admin_index.ctp:13 -#: View/Users/index.ctp:13 -#: View/Users/search.ctp:13 -msgid "Users" -msgstr "Usuarios" - -#: View/Users/admin_index.ctp:15 -msgid "Filter" -msgstr "Filtrar" - -#: View/Users/admin_index.ctp:20 -#: View/Users/search.ctp:23 -msgid "Search" -msgstr "Buscar" - -#: View/Users/admin_index.ctp:32 -#: View/Users/index.ctp:25 -#: View/Users/search.ctp:35 -msgid "Actions" -msgstr "Acciones" - -#: View/Users/admin_index.ctp:50;53 -msgid "Yes" -msgstr "Sí" - -#: View/Users/admin_index.ctp:50;53 -msgid "No" -msgstr "No" - -#: View/Users/admin_index.ctp:59 -#: View/Users/index.ctp:39 -#: View/Users/search.ctp:49 -msgid "View" -msgstr "Ver" - -#: View/Users/admin_index.ctp:60 -#: View/Users/search.ctp:50 -msgid "Edit" -msgstr "Editar" - -#: View/Users/admin_index.ctp:61 -#: View/Users/search.ctp:52 -msgid "Delete" -msgstr "Eliminar" - -#: View/Users/admin_index.ctp:61 -#: View/Users/search.ctp:55 -msgid "Are you sure you want to delete # %s?" -msgstr "¿Está seguro que desea eliminar # %s?" - -#: View/Users/admin_view.ctp:13 -#: View/Users/view.ctp:13 -msgid "User" -msgstr "Usuario" - -#: View/Users/admin_view.ctp:20 -#: View/Users/view.ctp:20 -msgid "Created" -msgstr "Creado" - -#: View/Users/admin_view.ctp:25 -msgid "Modified" -msgstr "Modificado" - -#: View/Users/change_password.ctp:13 -#: View/Users/edit.ctp:22 -msgid "Change your password" -msgstr "Cambiar contraseña" - -#: View/Users/change_password.ctp:14 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "Por favor introduzca su contraseña anterior por razones de seguridad y luego su nueva contraseña dos veces." - -#: View/Users/change_password.ctp:18 -msgid "Old Password" -msgstr "Contraseña anterior" - -#: View/Users/change_password.ctp:21 -#: View/Users/reset_password.ctp:9 -msgid "New Password" -msgstr "Nueva contraseña" - -#: View/Users/change_password.ctp:24 -#: View/Users/reset_password.ctp:12 -msgid "Confirm" -msgstr "Confirmar" - -#: View/Users/dashboard.ctp:13 -msgid "Welcome" -msgstr "Bienvenido" - -#: View/Users/dashboard.ctp:14 -msgid "Recent broadcasts" -msgstr "Mensajes recientes" - -#: View/Users/index.ctp:17 -#: View/Users/search.ctp:27 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "Página %page% de %pages%, mostrando %current% registros de %count% en total, empezando en %start% y terminando en %end%" - -#: View/Users/login.ctp:25 -msgid "Remember Me" -msgstr "Recordarme" - -#: View/Users/login.ctp:26 -#, fuzzy -msgid "I forgot my password" -msgstr "¿Olvidó su contraseña?" - -#: View/Users/request_password_change.ctp:13 -msgid "Forgot your password?" -msgstr "¿Olvidó su contraseña?" - -#: View/Users/request_password_change.ctp:14 -#: View/Users/resend_verification.ctp:14 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Por favor introduzca el correo que utilizó para registrarse y recibirá un correo con más instrucciones" - -#: View/Users/request_password_change.ctp:21 -#: View/Users/resend_verification.ctp:21 -msgid "Your Email" -msgstr "Su correo" - -#: View/Users/resend_verification.ctp:13 -msgid "Resend the Email Verification" -msgstr "Reenviar el email de verificación" - -#: View/Users/reset_password.ctp:2 -msgid "Reset your password" -msgstr "Reiniciar contraseña" - -#: View/Users/search.ctp:22 -msgid "Name" -msgstr "Nombre" - -#: Plugin/Users/Model/User.php:validation -#: for field username -msgid "Please enter a username." -msgstr "Por favor, introduzca un nombre de usuario." - -#: Plugin/Users/Model/User.php:validation -#: for field username -#, fuzzy -msgid "The username must be alphanumeric." -msgstr "El nombre de usuario debe estar compuesto únicamente por letras y números, sin espacios" - -#: Plugin/Users/Model/User.php:validation -#: for field username -msgid "This username is already in use." -msgstr "Este nombre de usuario ya se encuentra en uso" - -#: Plugin/Users/Model/User.php:validation -#: for field username -msgid "The username must have at least 3 characters." -msgstr "El nombre de usuario debe contener al menos 3 caracteres" - -#: Plugin/Users/Model/User.php:validation -#: for field email -msgid "Please enter a valid email address." -msgstr "Por favor introduzca una dirección de correo electrónico válida." - -#: Plugin/Users/Model/User.php:validation -#: for field email -msgid "This email is already in use." -msgstr "Este correo ya se encuentra en uso." - -#: Plugin/Users/Model/User.php:validation -#: for field password -msgid "The password must have at least 6 characters." -msgstr "La contraseña debe tener al menos 6 caracteres." - -#: Plugin/Users/Model/User.php:validation -#: for field password -msgid "Please enter a password." -msgstr "Por favor introduzca una contraseña." - -#: Plugin/Users/Model/User.php:validation -#: for field temppassword -msgid "The passwords are not equal, please try again." -msgstr "Las contraseñas no coinciden, por favor inténtelo de nuevo." - -#: Plugin/Users/Model/User.php:validation -#: for field tos -msgid "You must agree to the terms of use." -msgstr "Debe aceptar las condiciones de uso." - -#~ msgid "Invalid Detail." -#~ msgstr "Detalle no válido." - -#~ msgid "Saved" -#~ msgstr "Guardado" - -#~ msgid "%s details saved" -#~ msgstr "%s detalles guardados" - -#~ msgid "Invalid id for Detail" -#~ msgstr "Identificador no válido para detalle" - -#~ msgid "Detail deleted" -#~ msgstr "Detalle eliminado" - -#~ msgid "The Detail has been saved" -#~ msgstr "El detalle ha sido guardado" - -#~ msgid "Invalid Detail" -#~ msgstr "Detalle no válido" - -#~ msgid "Profile saved." -#~ msgstr "Perfil guardado" - -#~ msgid "Could not save your profile." -#~ msgstr "No se pudo guardar su perfil." - -#~ msgid "There url you accessed is not longer valid" -#~ msgstr "El url que intentó acceder ya no es válido" - -#~ msgid "" -#~ "There was an error trying to validate your e-mail address. Please check " -#~ "your e-mail for the URL you should use to verify your e-mail address." -#~ msgstr "" -#~ "Ocurrió un error tratando de validar su dirección de correo. Por favor " -#~ "verifique su correo y utilice la URL que le hemos enviado para validar su " -#~ "cuenta. Tenga en cuenta que a veces los correos pueden ser clasificados " -#~ "como correo basura (SPAM) por error, por favor revise su bandeja de " -#~ "entrada y su bandeja de SPAM." - -#~ msgid "Invalid date" -#~ msgstr "Fecha no válida" - -#~ msgid "floriank you have successfully logged out" -#~ msgstr "floriank you have successfully logged out" - -#~ msgid "Add Detail" -#~ msgstr "Agregar detalle" - -#~ msgid "List Details" -#~ msgstr "Listar detalles" - -#~ msgid "New User" -#~ msgstr "Nuevo usuario" - -#~ msgid "List Groups" -#~ msgstr "Listar grupos" - -#~ msgid "New Group" -#~ msgstr "Nuevo grupo" - -#~ msgid "Edit Detail" -#~ msgstr "Editar detalle" - -#~ msgid "Details" -#~ msgstr "Detalles" - -#~ msgid "New Detail" -#~ msgstr "Nuevo detalle" - -#~ msgid "Detail" -#~ msgstr "Detalle" - -#~ msgid "Id" -#~ msgstr "Id" - -#~ msgid "Position" -#~ msgstr "Posición" - -#~ msgid "Field" -#~ msgstr "Campo" - -#~ msgid "Value" -#~ msgstr "Valor" - -#~ msgid "Delete Detail" -#~ msgstr "Eliminar detalle" - -#~ msgid "Related Groups" -#~ msgstr "Grupos relacionado" - -#~ msgid "User Id" -#~ msgstr "Usuario Id" - -#~ msgid "Is Public" -#~ msgstr "Es Público" - -#~ msgid "Description" -#~ msgstr "Descripción" - -#~ msgid "Delete User" -#~ msgstr "Eliminar Usuario" - -#~ msgid "My Groups" -#~ msgstr "Mis grupos" - -#~ msgid "Create a new group" -#~ msgstr "Crear un nuevo grupo" - -#~ msgid "Invite a user" -#~ msgstr "Invitar a un usuario" - -#~ msgid "Requests to join" -#~ msgstr "Solicitar ingreso" - -#~ msgid "My own groups" -#~ msgstr "Mis grupos" - -#~ msgid "Members" -#~ msgstr "Miembros" - -#~ msgid "Invite user" -#~ msgstr "Invitar usuario" - -#~ msgid "Manage Broadcast Scope" -#~ msgstr "Gestionar alcance de mensajes" - -#~ msgid "Access" -#~ msgstr "Acceso" - -#~ msgid "Addons" -#~ msgstr "Complementos" - -#~ msgid "Groups im a member in" -#~ msgstr "Grupos en los que el miembro está" - -#~ msgid "Leave group" -#~ msgstr "Dejar grupo" - -#~ msgid "Account registration" -#~ msgstr "Registro de cuenta" - -#~ msgid "Please select a username that is not already in use" -#~ msgstr "Por favor seleccione un nombre de usuario que no esté en uso" - -#~ msgid "Must be at least 3 characters" -#~ msgstr "Debe ser de al menos 3 caracteres" - -#~ msgid "Username must contain numbers and letters only" -#~ msgstr "El nombre de usuario debe contener solo letras y números" - -#~ msgid "Please choose username" -#~ msgstr "Por favor escoja un nombre de usuario" - -#~ msgid "Must be at least 5 characters long" -#~ msgstr "Debe ser de al menos 5 caracteres" - -#~ msgid "Passwords must match" -#~ msgstr "Las contraseñas deben coincidir" - -#~ msgid "You must verify you have read the Terms of Service" -#~ msgstr "Debe verificar que ha leído las Condiciones de Servicio" - -#~ msgid "Openid Identifier" -#~ msgstr "Identificador Openid" - -#~ msgid "Search for users" -#~ msgstr "Buscar usuarios" diff --git a/Locale/users.pot b/Locale/users.pot deleted file mode 100644 index ca48a99b2..000000000 --- a/Locale/users.pot +++ /dev/null @@ -1,526 +0,0 @@ -# LANGUAGE translation of CakePHP Application -# Copyright YEAR NAME -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2013-09-18 23:20+0200\n" -"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" -"Last-Translator: NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: Controller/UsersController.php:310 -msgid "Invalid User." -msgstr "" - -#: Controller/UsersController.php:328 -msgid "The User has been saved" -msgstr "" - -#: Controller/UsersController.php:345 -msgid "User saved" -msgstr "" - -#: Controller/UsersController.php:369 -msgid "User deleted" -msgstr "" - -#: Controller/UsersController.php:371 -#: Model/User.php:829;858 -msgid "Invalid User" -msgstr "" - -#: Controller/UsersController.php:393 -msgid "You are already registered and logged in!" -msgstr "" - -#: Controller/UsersController.php:413 -#: Test/Case/Controller/UsersControllerTest.php:342 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "" - -#: Controller/UsersController.php:418 -#: Test/Case/Controller/UsersControllerTest.php:357 -msgid "Your account could not be created. Please, try again." -msgstr "" - -#: Controller/UsersController.php:462 -msgid "%s you have successfully logged in" -msgstr "" - -#: Controller/UsersController.php:483 -#: Test/Case/Controller/UsersControllerTest.php:316 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "" - -#: Controller/UsersController.php:549 -msgid "%s you have successfully logged out" -msgstr "" - -#: Controller/UsersController.php:563 -msgid "The email was resent. Please check your inbox." -msgstr "" - -#: Controller/UsersController.php:566 -msgid "The email could not be sent. Please check errors." -msgstr "" - -#: Controller/UsersController.php:589 -#: Test/Case/Controller/UsersControllerTest.php:374 -msgid "Your e-mail has been validated!" -msgstr "" - -#: Controller/UsersController.php:612 -msgid "The url you accessed is not longer valid" -msgstr "" - -#: Controller/UsersController.php:618 -msgid "Your password was sent to your registered email account" -msgstr "" - -#: Controller/UsersController.php:622 -msgid "There was an error verifying your account. Please check the email you were sent, and retry the verification link." -msgstr "" - -#: Controller/UsersController.php:638;748 -msgid "Password Reset" -msgstr "" - -#: Controller/UsersController.php:655;819 -msgid "Password changed." -msgstr "" - -#: Controller/UsersController.php:716 -msgid "Account verification" -msgstr "" - -#: Controller/UsersController.php:775 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "" - -#: Controller/UsersController.php:779 -msgid "You should receive an email with further instructions shortly" -msgstr "" - -#: Controller/UsersController.php:783 -msgid "No user was found with that email." -msgstr "" - -#: Controller/UsersController.php:813 -msgid "Invalid password reset token, try again." -msgstr "" - -#: Controller/UsersController.php:822 -msgid "Password changed, you can now login with your new password." -msgstr "" - -#: Controller/Component/RememberMeComponent.php:230 -msgid "Invalid options %s" -msgstr "" - -#: Controller/Component/Auth/TokenAuthenticate.php:67 -msgid "You need to specify token parameter and/or header" -msgstr "" - -#: Model/User.php:158;339 -msgid "The passwords are not equal." -msgstr "" - -#: Model/User.php:160 -msgid "Invalid password." -msgstr "" - -#: Model/User.php:242 -#: Test/Case/Controller/UsersControllerTest.php:382 -msgid "Invalid token, please check the email you were sent, and retry the verification link." -msgstr "" - -#: Model/User.php:247 -msgid "The token has expired." -msgstr "" - -#: Model/User.php:301 -msgid "This Email Address exists but was never validated." -msgstr "" - -#: Model/User.php:303 -msgid "This Email Address does not exist in the system." -msgstr "" - -#: Model/User.php:397 -msgid "$this->data['" -msgstr "" - -#: Model/User.php:443 -msgid "The user does not exist." -msgstr "" - -#: Model/User.php:481 -msgid "Invalid Email address." -msgstr "" - -#: Model/User.php:486 -msgid "This email is already verified." -msgstr "" - -#: Model/User.php:584 -msgid "Please enter your email address." -msgstr "" - -#: Model/User.php:591 -msgid "The email address does not exist in the system" -msgstr "" - -#: Model/User.php:596 -msgid "Your account is already authenticated." -msgstr "" - -#: Model/User.php:601 -msgid "Your account is disabled." -msgstr "" - -#: Test/Case/Controller/UsersControllerTest.php:55 -msgid "Sorry, but you need to login to access this location." -msgstr "" - -#: Test/Case/Controller/UsersControllerTest.php:275 -msgid "adminuser you have successfully logged in" -msgstr "" - -#: Test/Case/Controller/UsersControllerTest.php:401 -msgid "testuser you have successfully logged out" -msgstr "" - -#: View/Elements/pagination.ctp:14 -msgid "previous" -msgstr "" - -#: View/Elements/pagination.ctp:16 -msgid "next" -msgstr "" - -#: View/Elements/Users/admin_sidebar.ctp:3 -#: View/Elements/Users/sidebar.ctp:9 -msgid "Logout" -msgstr "" - -#: View/Elements/Users/admin_sidebar.ctp:4 -#: View/Elements/Users/sidebar.ctp:10 -msgid "My Account" -msgstr "" - -#: View/Elements/Users/admin_sidebar.ctp:6 -msgid "Add Users" -msgstr "" - -#: View/Elements/Users/admin_sidebar.ctp:7 -#: View/Elements/Users/sidebar.ctp:15 -msgid "List Users" -msgstr "" - -#: View/Elements/Users/admin_sidebar.ctp:9 -msgid "Frontend" -msgstr "" - -#: View/Elements/Users/sidebar.ctp:4 -#: View/Users/login.ctp:13 -msgid "Login" -msgstr "" - -#: View/Elements/Users/sidebar.ctp:6 -msgid "Register an account" -msgstr "" - -#: View/Elements/Users/sidebar.ctp:11 -msgid "Change password" -msgstr "" - -#: View/Emails/text/account_verification.ctp:12 -msgid "Hello %s," -msgstr "" - -#: View/Emails/text/account_verification.ctp:14 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "" - -#: View/Emails/text/new_password.ctp:12 -msgid "Your password has been reset" -msgstr "" - -#: View/Emails/text/new_password.ctp:13 -msgid "Please login using this password and change your password" -msgstr "" - -#: View/Emails/text/new_password.ctp:15 -msgid "Your new password is: %s" -msgstr "" - -#: View/Emails/text/password_reset_request.ctp:12 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "" - -#: View/Users/add.ctp:13 -#: View/Users/admin_add.ctp:15 -msgid "Add User" -msgstr "" - -#: View/Users/add.ctp:18 -#: View/Users/admin_add.ctp:18 -#: View/Users/admin_edit.ctp:19 -#: View/Users/admin_index.ctp:18 -#: View/Users/admin_view.ctp:15 -#: View/Users/search.ctp:18 -#: View/Users/view.ctp:15 -msgid "Username" -msgstr "" - -#: View/Users/add.ctp:20 -#: View/Users/admin_add.ctp:20 -msgid "E-mail (used as login)" -msgstr "" - -#: View/Users/add.ctp:21 -#: View/Users/admin_add.ctp:21 -msgid "Must be a valid email address" -msgstr "" - -#: View/Users/add.ctp:22 -#: View/Users/admin_add.ctp:22 -msgid "An account with that email already exists" -msgstr "" - -#: View/Users/add.ctp:24 -#: View/Users/admin_add.ctp:24 -#: View/Users/login.ctp:23 -msgid "Password" -msgstr "" - -#: View/Users/add.ctp:27 -#: View/Users/admin_add.ctp:27 -msgid "Password (confirm)" -msgstr "" - -#: View/Users/add.ctp:29 -msgid "Terms of Service" -msgstr "" - -#: View/Users/add.ctp:31 -msgid "I have read and agreed to " -msgstr "" - -#: View/Users/add.ctp:32 -#: View/Users/change_password.ctp:26 -#: View/Users/edit.ctp:25 -#: View/Users/login.ctp:30 -#: View/Users/request_password_change.ctp:22 -#: View/Users/resend_verification.ctp:22 -#: View/Users/reset_password.ctp:14 -msgid "Submit" -msgstr "" - -#: View/Users/admin_add.ctp:31 -#: View/Users/admin_edit.ctp:24 -msgid "Role" -msgstr "" - -#: View/Users/admin_add.ctp:34 -#: View/Users/admin_edit.ctp:27 -msgid "Is Admin" -msgstr "" - -#: View/Users/admin_add.ctp:36 -#: View/Users/admin_edit.ctp:29 -msgid "Active" -msgstr "" - -#: View/Users/admin_edit.ctp:15 -#: View/Users/edit.ctp:15 -msgid "Edit User" -msgstr "" - -#: View/Users/admin_edit.ctp:21 -#: View/Users/admin_index.ctp:19 -#: View/Users/login.ctp:21 -#: View/Users/search.ctp:20 -msgid "Email" -msgstr "" - -#: View/Users/admin_index.ctp:13 -#: View/Users/index.ctp:13 -#: View/Users/search.ctp:13 -msgid "Users" -msgstr "" - -#: View/Users/admin_index.ctp:15 -msgid "Filter" -msgstr "" - -#: View/Users/admin_index.ctp:20 -#: View/Users/search.ctp:23 -msgid "Search" -msgstr "" - -#: View/Users/admin_index.ctp:32 -#: View/Users/index.ctp:25 -#: View/Users/search.ctp:35 -msgid "Actions" -msgstr "" - -#: View/Users/admin_index.ctp:50;53 -msgid "Yes" -msgstr "" - -#: View/Users/admin_index.ctp:50;53 -msgid "No" -msgstr "" - -#: View/Users/admin_index.ctp:59 -#: View/Users/index.ctp:39 -#: View/Users/search.ctp:49 -msgid "View" -msgstr "" - -#: View/Users/admin_index.ctp:60 -#: View/Users/search.ctp:50 -msgid "Edit" -msgstr "" - -#: View/Users/admin_index.ctp:61 -#: View/Users/search.ctp:52 -msgid "Delete" -msgstr "" - -#: View/Users/admin_index.ctp:61 -#: View/Users/search.ctp:55 -msgid "Are you sure you want to delete # %s?" -msgstr "" - -#: View/Users/admin_view.ctp:13 -#: View/Users/view.ctp:13 -msgid "User" -msgstr "" - -#: View/Users/admin_view.ctp:20 -#: View/Users/view.ctp:20 -msgid "Created" -msgstr "" - -#: View/Users/admin_view.ctp:25 -msgid "Modified" -msgstr "" - -#: View/Users/change_password.ctp:13 -#: View/Users/edit.ctp:22 -msgid "Change your password" -msgstr "" - -#: View/Users/change_password.ctp:14 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "" - -#: View/Users/change_password.ctp:18 -msgid "Old Password" -msgstr "" - -#: View/Users/change_password.ctp:21 -#: View/Users/reset_password.ctp:9 -msgid "New Password" -msgstr "" - -#: View/Users/change_password.ctp:24 -#: View/Users/reset_password.ctp:12 -msgid "Confirm" -msgstr "" - -#: View/Users/dashboard.ctp:13 -msgid "Welcome" -msgstr "" - -#: View/Users/dashboard.ctp:14 -msgid "Recent broadcasts" -msgstr "" - -#: View/Users/index.ctp:17 -#: View/Users/search.ctp:27 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "" - -#: View/Users/login.ctp:25 -msgid "Remember Me" -msgstr "" - -#: View/Users/login.ctp:26 -msgid "I forgot my password" -msgstr "" - -#: View/Users/request_password_change.ctp:13 -msgid "Forgot your password?" -msgstr "" - -#: View/Users/request_password_change.ctp:14 -#: View/Users/resend_verification.ctp:14 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "" - -#: View/Users/request_password_change.ctp:21 -#: View/Users/resend_verification.ctp:21 -msgid "Your Email" -msgstr "" - -#: View/Users/resend_verification.ctp:13 -msgid "Resend the Email Verification" -msgstr "" - -#: View/Users/reset_password.ctp:2 -msgid "Reset your password" -msgstr "" - -#: View/Users/search.ctp:22 -msgid "Name" -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field username -msgid "Please enter a username." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field username -msgid "The username must be alphanumeric." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field username -msgid "This username is already in use." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field username -msgid "The username must have at least 3 characters." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field email -msgid "Please enter a valid email address." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field email -msgid "This email is already in use." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field password -msgid "The password must have at least 6 characters." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field password -msgid "Please enter a password." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field temppassword -msgid "The passwords are not equal, please try again." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field tos -msgid "You must agree to the terms of use." -msgstr "" - diff --git a/Locale/zh_TW/LC_MESSAGES/users.po b/Locale/zh_TW/LC_MESSAGES/users.po deleted file mode 100644 index c677a24cc..000000000 --- a/Locale/zh_TW/LC_MESSAGES/users.po +++ /dev/null @@ -1,720 +0,0 @@ -# LANGUAGE translation of the CakePHP Users plugin -# -# Copyright 2010, Cake Development Corporation (http://cakedc.com) -# -# Licensed under The MIT License -# Redistributions of files must retain the above copyright notice. -# -# @copyright Copyright 2010, Cake Development Corporation (http://cakedc.com) -# @license MIT License (http://www.opensource.org/licenses/mit-license.php) -# -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2010-09-15 15:48+0200\n" -"PO-Revision-Date: 2012-03-06 02:04+0800\n" -"Last-Translator: \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "輸入詳細內容錯誤。" - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "儲存成功。" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "%s 詳細資料儲存成功" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "錯誤的詳細資料 id" - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "已經刪除。" - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "詳情儲存成功。" - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "詳情無法儲存,請稍後再試。" - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "輸入詳細內容錯誤" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "個人檔案儲存成功。" - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "無法儲存您的個人檔案。" - -#: /controllers/users_controller.php:193 -msgid "Invalid User." -msgstr "錯誤的使用者。" - -#: /controllers/users_controller.php:207 -msgid "The User has been saved" -msgstr "該使用者已經儲存成功。" - -#: /controllers/users_controller.php:223 -msgid "User saved" -msgstr "使用者儲存成功。" - -#: /controllers/users_controller.php:247 -msgid "User deleted" -msgstr "使用者已刪除" - -#: /controllers/users_controller.php:249 -#: /models/user.php:703 -msgid "Invalid User" -msgstr "錯誤的使用者" - -#: /controllers/users_controller.php:273 -msgid "You are already registered and logged in!" -msgstr "您已經註冊並且登入了!" - -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "您的帳號已經建立。稍後您將會收到認證郵件,一旦認證完畢即可登入。" - -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 -msgid "Your account could not be created. Please, try again." -msgstr "您的帳號無法建立,請稍後再試。" - -#: /controllers/users_controller.php:309 -msgid "%s you have successfully logged in" -msgstr "%s 您已經成功登入。" - -#: /controllers/users_controller.php:383 -msgid "%s you have successfully logged out" -msgstr "% 您已經成功登出。" - -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" -msgstr "您存取的網址已經失效。" - -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" -msgstr "重設密碼" - -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" -msgstr "您的密碼已被重設。" - -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" -msgstr "請使用此密碼登入並更改密碼。" - -#: /controllers/users_controller.php:438 -msgid "Your password was sent to your registered email account" -msgstr "您的密碼已經被送到您註冊的信箱。" - -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 -msgid "Your e-mail has been validated!" -msgstr "email 認證成功!" - -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "您的 email 地址驗證出現錯誤。" - -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 -msgid "The url you accessed is not longer valid" -msgstr "您要存取的網址已經失效" - -#: /controllers/users_controller.php:467 -msgid "Password changed." -msgstr "密碼更改成功。" - -#: /controllers/users_controller.php:521 -msgid "Account verification" -msgstr "帳戶認證" - -#: /controllers/users_controller.php:563 -msgid "%s has been sent an email with instruction to reset their password." -msgstr "一封指示怎麼重設密碼的郵件已經寄給 %s" - -#: /controllers/users_controller.php:567 -msgid "You should receive an email with further instructions shortly" -msgstr "您應該稍後就會收到一封郵件,指示您進一步的操作。" - -#: /controllers/users_controller.php:571 -msgid "No user was found with that email." -msgstr "該 email 並無使用者註冊。" - -#: /controllers/users_controller.php:588 -msgid "Invalid password reset token, try again." -msgstr "token 錯誤,請重新再試。" - -#: /controllers/users_controller.php:594 -msgid "Password changed, you can now login with your new password." -msgstr "密碼已經更改。您可以用新密碼登入。" - -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "請輸入使用者名稱。" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "使用者名稱只能包含英文與數字。" - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "該使用者名稱已經被使用。" - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "使用者名稱必須至少含 3 個字元。" - -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "請輸入正確的 email 地址。" - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "此 email 已經被註冊。" - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "密碼必須至少含 8 個字元。" - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "請輸入密碼" - -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." -msgstr "兩個密碼不一致,請重新再試" - -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "您必須同意使用者條款才行。" - -#: /models/user.php:137;357 -msgid "The passwords are not equal." -msgstr "兩個密碼不一致。" - -#: /models/user.php:139 -msgid "Invalid password." -msgstr "密碼錯誤" - -#: /models/user.php:150 -msgid "Invalid date" -msgstr "錯誤的日期" - -#: /models/user.php:315 -msgid "This Email Address exists but was never validated." -msgstr "該 Email 存在但是未認證通過。" - -#: /models/user.php:317 -msgid "This Email Address does not exist in the system." -msgstr "系統中不存在該電子郵件信箱。" - -#: /models/user.php:406 -msgid "$this->data['" -msgstr "" - -#: /models/user.php:460 -msgid "The user does not exist." -msgstr "使用者不存在。" - -#: /models/user.php:505 -msgid "Please enter your email address." -msgstr "請輸入您的 email。" - -#: /models/user.php:515 -msgid "The email address does not exist in the system" -msgstr "系統中不存在該電子郵件信箱。" - -#: /models/user.php:520 -msgid "Your account is already authenticated." -msgstr "您的帳號已經認證。" - -#: /models/user.php:525 -msgid "Your account is disabled." -msgstr "帳號停權中。" - -#: /tests/cases/controllers/users_controller.test.php:34 -msgid "Sorry, but you need to login to access this location." -msgstr "抱歉,您需要登入才能觀看此頁面。" - -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "錯誤的電子郵件 / 密碼組合。請重新再試。" - -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" -msgstr "" - -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" -msgstr "" - -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" -msgstr "新增詳細內容" - -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" -msgstr "顯示細節" - -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 -msgid "List Users" -msgstr "列出使用者" - -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "新使用者" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "顯示群組" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "新群組" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "編輯內容" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" -msgstr "刪除" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" -msgstr "確定要刪除 # %s?" - -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" -msgstr "詳細內容" - -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "第 %page% 頁,共 %pages% 頁,顯示 %count% 筆記錄中的 %current% 筆,由第 %start% 筆開始至第 %end 筆" - -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" -msgstr "操作" - -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" -msgstr "檢視" - -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" -msgstr "編輯" - -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 -msgid "previous" -msgstr "上一頁" - -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 -msgid "next" -msgstr "下一頁" - -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" -msgstr "新詳細內容" - -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" -msgstr "詳細內容" - -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" -msgstr "編號" - -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" -msgstr "使用者" - -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" -msgstr "位置" - -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" -msgstr "欄位" - -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" -msgstr "內容" - -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" -msgstr "建立時間" - -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" -msgstr "更改時間" - -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" -msgstr "刪除詳細內容" - -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" -msgstr "相關的群組" - -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" -msgstr "使用者編號" - -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" -msgstr "是否公開" - -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" -msgstr "名稱" - -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" -msgstr "描述" - -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" -msgstr "送出" - -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" -msgstr "電子郵件" - -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 -msgid "Password" -msgstr "密碼" - -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 -msgid "Login" -msgstr "登入" - -#: /views/elements/email/text/account_verification.ctp:2 -msgid "Hello %s," -msgstr "%s 您好," - -#: /views/elements/email/text/account_verification.ctp:4 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "您必須在 24 小時內開啟下面的網址,來啟動您的帳號。" - -#: /views/elements/email/text/password_reset_request.ctp:2 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "要重設您的密碼,請點選下面的連結。" - -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 -msgid "Add User" -msgstr "新增使用者" - -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 -msgid "Edit User" -msgstr "編輯使用者" - -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 -msgid "Users" -msgstr "使用者列表" - -#: /views/users/admin_index.ctp:4 -msgid "Filter" -msgstr "過濾" - -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" -msgstr "使用者名稱" - -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 -msgid "Search" -msgstr "搜尋" - -#: /views/users/admin_view.ctp:24 -msgid "Delete User" -msgstr "刪除使用者" - -#: /views/users/change_password.ctp:1 -msgid "Change your password" -msgstr "更改密碼" - -#: /views/users/change_password.ctp:3 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "為了安全考量,請輸入您的舊密碼,並輸入新密碼兩次。" - -#: /views/users/change_password.ctp:8 -msgid "Old Password" -msgstr "舊密碼" - -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 -msgid "New Password" -msgstr "新密碼" - -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 -msgid "Confirm" -msgstr "確認" - -#: /views/users/dashboard.ctp:2 -msgid "Welcome" -msgstr "歡迎光臨" - -#: /views/users/dashboard.ctp:3 -msgid "Recent broadcasts" -msgstr "最新通知" - -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "我的群組" - -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "建立一個新群組" - -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "邀請一個使用者" - -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "邀請列表" - -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "我自己的群組" - -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "成員" - -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "邀請使用者" - -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "管理通知的範圍" - -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "存取" - -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "附加" - -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "我加入的群組" - -#: /views/users/groups.ctp:68 -msgid "Leave group" -msgstr "離開群組" - -#: /views/users/login.ctp:11 -msgid "Remember Me" -msgstr "記住我的資訊" - -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "帳戶註冊" - -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" -msgstr "請選一個沒人用過的使用者名稱" - -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "至少要 3 個字元" - -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "使用者名稱只能包含英文和數字" - -#: /views/users/register.ctp:13 -msgid "Please choose username" -msgstr "請選擇使用者名稱" - -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" -msgstr "電子郵件信箱 (登入使用)" - -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" -msgstr "必須是一個正確的 email" - -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" -msgstr "該 email 已經註冊帳號了" - -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" -msgstr "至少要 5 個字元。" - -#: /views/users/register.ctp:23 -msgid "Password (confirm)" -msgstr "確認密碼" - -#: /views/users/register.ctp:25 -msgid "Passwords must match" -msgstr "兩個密碼必須一致" - -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " -msgstr "我已經閱讀並且同意" - -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" -msgstr "使用者條款" - -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" -msgstr "您必須確定您閱讀了使用者條款。" - -#: /views/users/register.ctp:46 -msgid "Openid Identifier" -msgstr "Openid 名稱" - -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" -msgstr "忘記密碼?" - -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "請輸入您註冊的 email,您將會收到進一步的指示。" - -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" -msgstr "您的電子郵件信箱" - -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" -msgstr "重設密碼" - -#: /views/users/search.ctp:1 -msgid "Search for users" -msgstr "搜尋使用者" - diff --git a/Model/User.php b/Model/User.php deleted file mode 100644 index 31f68c685..000000000 --- a/Model/User.php +++ /dev/null @@ -1,926 +0,0 @@ - true - ); - -/** - * All search fields need to be configured in the Model::filterArgs array. - * - * @var array - * @link https://github.com/CakeDC/search - */ - public $filterArgs = array( - 'username' => array('type' => 'like'), - 'email' => array('type' => 'value') - ); - -/** - * Displayfield - * - * @var string $displayField - */ - public $displayField = 'username'; - -/** - * Time the email verification token is valid in seconds - * - * @var integer - */ - public $emailTokenExpirationTime = 86400; - -/** - * Validation domain for translations - * - * @var string - */ - public $validationDomain = 'users'; - -/** - * Validation parameters - * - * @var array - */ - public $validate = array( - 'username' => array( - 'required' => array( - 'rule' => array('notEmpty'), - 'required' => true, 'allowEmpty' => false, - 'message' => 'Please enter a username.' - ), - 'alpha' => array( - 'rule' => array('alphaNumeric'), - 'message' => 'The username must be alphanumeric.' - ), - 'unique_username' => array( - 'rule' => array('isUnique', 'username'), - 'message' => 'This username is already in use.' - ), - 'username_min' => array( - 'rule' => array('minLength', '3'), - 'message' => 'The username must have at least 3 characters.' - ) - ), - 'email' => array( - 'isValid' => array( - 'rule' => 'email', - 'required' => true, - 'message' => 'Please enter a valid email address.' - ), - 'isUnique' => array( - 'rule' => array('isUnique', 'email'), - 'message' => 'This email is already in use.' - ) - ), - 'password' => array( - 'too_short' => array( - 'rule' => array('minLength', '6'), - 'message' => 'The password must have at least 6 characters.' - ), - 'required' => array( - 'rule' => 'notEmpty', - 'message' => 'Please enter a password.' - ) - ), - 'temppassword' => array( - 'rule' => 'confirmPassword', - 'message' => 'The passwords are not equal, please try again.' - ), - 'tos' => array( - 'rule' => array('custom','[1]'), - 'message' => 'You must agree to the terms of use.' - ) - ); - -/** - * Constructor - * - * @param bool|string $id ID - * @param string $table Table - * @param string $ds Datasource - */ - public function __construct($id = false, $table = null, $ds = null) { - $this->_setupBehaviors(); - $this->_setupValidation(); - parent::__construct($id, $table, $ds); - } - -/** - * Setup available plugins - * - * This checks for the existence of certain plugins, and if available, uses them. - * - * @return void - * @link https://github.com/CakeDC/search - * @link https://github.com/CakeDC/utils - */ - protected function _setupBehaviors() { - if (CakePlugin::loaded('Search') && class_exists('SearchableBehavior')) { - $this->actsAs[] = 'Search.Searchable'; - } - - if (CakePlugin::loaded('Utils') && class_exists('SluggableBehavior') && Configure::read('Users.disableSlugs') !== true) { - $this->actsAs['Utils.Sluggable'] = array( - 'label' => 'username', - 'method' => 'multibyteSlug' - ); - } - } - -/** - * Setup validation rules - * - * @return void - */ - protected function _setupValidation() { - $this->validatePasswordChange = array( - 'new_password' => $this->validate['password'], - 'confirm_password' => array( - 'required' => array('rule' => array('compareFields', 'new_password', 'confirm_password'), 'required' => true, 'message' => __d('users', 'The passwords are not equal.'))), - 'old_password' => array( - 'to_short' => array('rule' => 'validateOldPassword', 'required' => true, 'message' => __d('users', 'Invalid password.')) - ) - ); - } - -/** - * Create a hash from string using given method. - * Fallback on next available method. - * - * Override this method to use a different hashing method - * - * @param string $string String to hash - * @param string $type Method to use (sha1/sha256/md5) - * @param boolean $salt If true, automatically appends the application's salt - * value to $string (Security.salt) - * @return string Hash - */ - public function hash($string, $type = null, $salt = false) { - return Security::hash($string, $type, $salt); - } - -/** - * Custom validation method to ensure that the two entered passwords match - * - * @param string $password Password - * @return boolean Success - */ - public function confirmPassword($password = null) { - if ((isset($this->data[$this->alias]['password']) && isset($password['temppassword'])) - && !empty($password['temppassword']) - && ($this->data[$this->alias]['password'] === $password['temppassword'])) { - return true; - } - return false; - } - -/** - * Compares the email confirmation - * - * @param array $email Email data - * @return boolean - */ - public function confirmEmail($email = null) { - if ((isset($this->data[$this->alias]['email']) && isset($email['confirm_email'])) - && !empty($email['confirm_email']) - && (strtolower($this->data[$this->alias]['email']) === strtolower($email['confirm_email']))) { - return true; - } - return false; - } - -/** - * Checks the token for email verification - * - * @param string $token - * @return array - */ - public function checkEmailVerfificationToken($token = null) { - $result = $this->find('first', array( - 'contain' => array(), - 'conditions' => array( - $this->alias . '.email_verified' => 0, - $this->alias . '.email_token' => $token), - 'fields' => array( - 'id', 'email', 'email_token_expires', 'role') - ) - ); - - if (empty($result)) { - return false; - } - - return $result; - } - -/** - * Verifies a users email by a token that was sent to him via email and flags the user record as active - * - * @param string $token The token that wa sent to the user - * @throws RuntimeException - * @return array On success it returns the user data record - */ - public function verifyEmail($token = null) { - $user = $this->checkEmailVerfificationToken($token); - - if ($user === false) { - throw new RuntimeException(__d('users', 'Invalid token, please check the email you were sent, and retry the verification link.')); - } - - $expires = strtotime($user[$this->alias]['email_token_expires']); - if ($expires < time()) { - throw new RuntimeException(__d('users', 'The token has expired.')); - } - - $data[$this->alias]['active'] = 1; - $user[$this->alias]['email_verified'] = 1; - $user[$this->alias]['email_token'] = null; - $user[$this->alias]['email_token_expires'] = null; - - $user = $this->save($user, array( - 'validate' => false, - 'callbacks' => false - )); - $this->data = $user; - return $user; - } - -/** - * Updates the last activity field of a user - * - * @param string $userId User id - * @param string $field Default is "last_action", changing it allows you to use this method also for "last_login" for example - * @return boolean True on success - */ - public function updateLastActivity($userId = null, $field = 'last_action') { - if (!empty($userId)) { - $this->id = $userId; - } - if ($this->exists()) { - return $this->saveField($field, date('Y-m-d H:i:s', time())); - } - return false; - } - -/** - * Checks if an email is in the system, validated and if the user is active so that the user is allowed to reste his password - * - * @param array $postData post data from controller - * @return mixed False or user data as array on success - */ - public function passwordReset($postData = array()) { - $user = $this->find('first', array( - 'contain' => array(), - 'conditions' => array( - $this->alias . '.active' => 1, - $this->alias . '.email' => $postData[$this->alias]['email']))); - - if (!empty($user) && $user[$this->alias]['email_verified'] == 1) { - $sixtyMins = time() + 43000; - $token = $this->generateToken(); - $user[$this->alias]['password_token'] = $token; - $user[$this->alias]['email_token_expires'] = date('Y-m-d H:i:s', $sixtyMins); - $user = $this->save($user, false); - $this->data = $user; - return $user; - } elseif (!empty($user) && $user[$this->alias]['email_verified'] == 0) { - $this->invalidate('email', __d('users', 'This Email Address exists but was never validated.')); - } else { - $this->invalidate('email', __d('users', 'This Email Address does not exist in the system.')); - } - - return false; - } - -/** - * Checks the token for a password change - * - * @param string $token Token - * @return mixed False or user data as array - */ - public function checkPasswordToken($token = null) { - $user = $this->find('first', array( - 'contain' => array(), - 'conditions' => array( - $this->alias . '.active' => 1, - $this->alias . '.password_token' => $token, - $this->alias . '.email_token_expires >=' => date('Y-m-d H:i:s')))); - if (empty($user)) { - return false; - } - return $user; - } - -/** - * Changes the validation rules for the User::resetPassword() method - * - * @return array Set of rules required for the User::resetPassword() method - */ - public function setUpResetPasswordValidationRules() { - return array( - 'new_password' => $this->validate['password'], - 'confirm_password' => array( - 'required' => array( - 'rule' => array('compareFields', 'new_password', 'confirm_password'), - 'message' => __d('users', 'The passwords are not equal.') - ) - ) - ); - } - -/** - * Resets the password - * - * @param array $postData Post data from controller - * @return boolean True on success - */ - public function resetPassword($postData = array()) { - $result = false; - - $tmp = $this->validate; - $this->validate = $this->setUpResetPasswordValidationRules(); - - $this->set($postData); - if ($this->validates()) { - $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['new_password'], null, true); - $this->data[$this->alias]['password_token'] = null; - $result = $this->save($this->data, array( - 'validate' => false, - 'callbacks' => false) - ); - } - - $this->validate = $tmp; - return $result; - } - -/** - * Changes the password for a user - * - * @param array $postData Post data from controller - * @return boolean True on success - */ - public function changePassword($postData = array()) { - $this->validate = $this->validatePasswordChange; - - $this->set($postData); - if ($this->validates()) { - $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['new_password'], null, true); - $this->save($postData, array( - 'validate' => false, - 'callbacks' => false)); - return true; - } - return false; - } - -/** - * Validation method to check the old password - * - * @param array $password - * @throws OutOfBoundsException - * @return boolean True on success - */ - public function validateOldPassword($password) { - if (!isset($this->data[$this->alias]['id']) || empty($this->data[$this->alias]['id'])) { - if (Configure::read('debug') > 0) { - throw new OutOfBoundsException(__d('users', '$this->data[\'' . $this->alias . '\'][\'id\'] has to be set and not empty')); - } - } - - $currentPassword = $this->field('password', array($this->alias . '.id' => $this->data[$this->alias]['id'])); - return $currentPassword === $this->hash($password['old_password'], null, true); - } - -/** - * Validation method to compare two fields - * - * @param mixed $field1 Array or string, if array the first key is used as fieldname - * @param string $field2 Second fieldname - * @return boolean True on success - */ - public function compareFields($field1, $field2) { - if (is_array($field1)) { - $field1 = key($field1); - } - - if (isset($this->data[$this->alias][$field1]) && isset($this->data[$this->alias][$field2]) && - $this->data[$this->alias][$field1] == $this->data[$this->alias][$field2]) { - return true; - } - return false; - } - -/** - * Returns all data about a user - * - * @param string|integer $slug user slug or the uuid of a user - * @param string $field - * @throws NotFoundException - * @return array - */ - public function view($slug = null, $field = 'slug') { - $user = $this->find('first', array( - 'contain' => array(), - 'conditions' => array( - 'OR' => array( - $this->alias . '.' . $field => $slug, - $this->alias . '.' . $this->primaryKey => $slug), - $this->alias . '.active' => 1, - $this->alias . '.email_verified' => 1))); - - if (empty($user)) { - throw new NotFoundException(__d('users', 'The user does not exist.')); - } - - return $user; - } - -/** - * Finds an user simply by email - * - * Used by the following methods: - * - checkEmailVerification - * - resendVerification - * - * Override it as needed, to add additional models to contain for example - * - * @param string $email - * @return array - */ - public function findByEmail($email = null) { - return $this->find('first', array( - 'contain' => array(), - 'conditions' => array( - $this->alias . '.email' => $email, - ) - )); - } - -/** - * Checks if an email is already verified and if not renews the expiration time - * - * @param array $postData the post data from the request - * @param boolean $renew - * @return bool True if the email was not already verified - */ - public function checkEmailVerification($postData = array(), $renew = true) { - $user = $this->findByEmail($postData[$this->alias]['email']); - - if (empty($user)) { - $this->invalidate('email', __d('users', 'Invalid Email address.')); - return false; - } - - if ($user[$this->alias]['email_verified'] == 1) { - $this->invalidate('email', __d('users', 'This email is already verified.')); - return false; - } - - if ($user[$this->alias]['email_verified'] == 0) { - if ($renew === true) { - $user[$this->alias]['email_token_expires'] = $this->emailTokenExpirationTime(); - $this->save($user, array( - 'validate' => false, - 'callbacks' => false, - )); - } - $this->data = $user; - return true; - } - } - -/** - * Registers a new user - * - * Options: - * - bool emailVerification : Default is true, generates the token for email verification - * - bool removeExpiredRegistrations : Default is true, removes expired registrations to do cleanup when no cron is configured for that - * - bool returnData : Default is true, if false the method returns true/false the data is always available through $this->User->data - * - * @param array $postData Post data from controller - * @param mixed should be array now but can be boolean for emailVerification because of backward compatibility - * @return mixed - */ - public function register($postData = array(), $options = array()) { - $Event = new CakeEvent( - 'Users.Model.User.beforeRegister', - $this, - array( - 'data' => $postData, - 'options' => $options - ) - ); - - $this->getEventManager()->dispatch($Event); - if ($Event->isStopped()) { - return $Event->result; - } - - if (is_bool($options)) { - $options = array('emailVerification' => $options); - } - - $defaults = array( - 'emailVerification' => true, - 'removeExpiredRegistrations' => true, - 'returnData' => true); - extract(array_merge($defaults, $options)); - - $postData = $this->_beforeRegistration($postData, $emailVerification); - - if ($removeExpiredRegistrations) { - $this->_removeExpiredRegistrations(); - } - - $this->set($postData); - if ($this->validates()) { - $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); - $this->create(); - $this->data = $this->save($postData, false); - $this->data[$this->alias]['id'] = $this->id; - - $Event = new CakeEvent( - 'Users.Model.User.afterRegister', - $this, - array( - 'data' => $this->data, - 'options' => $options - ) - ); - - $this->getEventManager()->dispatch($Event); - - if ($Event->isStopped()) { - return $Event->result; - } - - if ($returnData) { - return $this->data; - } - return true; - } - return false; - } - -/** - * Resends the verification if the user is not already validated or invalid - * - * @param array $postData Post data from controller - * @return mixed False or user data array on success - */ - public function resendVerification($postData = array()) { - if (!isset($postData[$this->alias]['email']) || empty($postData[$this->alias]['email'])) { - $this->invalidate('email', __d('users', 'Please enter your email address.')); - return false; - } - - $user = $this->findByEmail($postData[$this->alias]['email']); - - if (empty($user)) { - $this->invalidate('email', __d('users', 'The email address does not exist in the system')); - return false; - } - - if ($user[$this->alias]['email_verified'] == 1) { - $this->invalidate('email', __d('users', 'Your account is already authenticated.')); - return false; - } - - if ($user[$this->alias]['active'] == 0) { - $this->invalidate('email', __d('users', 'Your account is disabled.')); - return false; - } - - $user[$this->alias]['email_token'] = $this->generateToken(); - $user[$this->alias]['email_token_expires'] = $this->emailTokenExpirationTime(); - - return $this->save($user, false); - } - -/** - * Returns the time the email verification token expires - * - * @return string - */ - public function emailTokenExpirationTime() { - return date('Y-m-d H:i:s', time() + $this->emailTokenExpirationTime); - } - -/** - * Generates a password - * - * @param int $length Password length - * @return string - */ - public function generatePassword($length = 10) { - srand((double)microtime() * 1000000); - $password = ''; - $vowels = array("a", "e", "i", "o", "u"); - $cons = array("b", "c", "d", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "u", "v", "w", "tr", - "cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr", "sl", "cl"); - for ($i = 0; $i < $length; $i++) { - $password .= $cons[mt_rand(0, 31)] . $vowels[mt_rand(0, 4)]; - } - return substr($password, 0, $length); - } - -/** - * Generate token used by the user registration system - * - * @param int $length Token Length - * @return string - */ - public function generateToken($length = 10) { - $possible = '0123456789abcdefghijklmnopqrstuvwxyz'; - $token = ""; - $i = 0; - - while ($i < $length) { - $char = substr($possible, mt_rand(0, strlen($possible) - 1), 1); - if (!stristr($token, $char)) { - $token .= $char; - $i++; - } - } - return $token; - } - -/** - * Optional data manipulation before the registration record is saved - * - * @param array post data array - * @param boolean Use email generation, create token, default true - * @return array - */ - protected function _beforeRegistration($postData = array(), $useEmailVerification = true) { - if ($useEmailVerification == true) { - $postData[$this->alias]['email_token'] = $this->generateToken(); - $postData[$this->alias]['email_token_expires'] = date('Y-m-d H:i:s', time() + 86400); - } else { - $postData[$this->alias]['email_verified'] = 1; - } - $postData[$this->alias]['active'] = 1; - $defaultRole = Configure::read('Users.defaultRole'); - if ($defaultRole) { - $postData[$this->alias]['role'] = $defaultRole; - } else { - $postData[$this->alias]['role'] = 'registered'; - } - return $postData; - } - -/** - * Returns the search data - Requires the CakeDC Search plugin to work - * - * @param string $state Find State - * @param string $query Query options - * @param array|string $results Result data - * @throws MissingPluginException - * @return array - * @link https://github.com/CakeDC/search - */ - protected function _findSearch($state, $query, $results = array()) { - if (!class_exists('SearchableBehavior')) { - throw new MissingPluginException(array('plugin' => 'Utils')); - } - - if ($state == 'before') { - $this->Behaviors->load('Containable', array( - 'autoFields' => false) - ); - $results = $query; - - if (empty($query['search'])) { - $query['search'] = ''; - } - - $by = $query['by']; - $like = '%' . $query['search'] . '%'; - - switch ($by) { - case 'username': - $results['conditions'] = Hash::merge( - $query['conditions'], - array($this->alias . '.username LIKE' => $like)); - break; - case 'email': - $results['conditions'] = Hash::merge( - $query['conditions'], - array($this->alias . '.email LIKE' => $like)); - break; - case 'any': - $results['conditions'] = Hash::merge( - $query['conditions'], - array('OR' => array( - array($this->alias . '.username LIKE' => $like), - array($this->alias . '.email LIKE' => $like)))); - break; - case '' : - $results['conditions'] = $query['conditions']; - break; - default : - $results['conditions'] = Hash::merge( - $query['conditions'], - array($this->alias . '.username LIKE' => $like)); - break; - } - - if (isset($query['operation']) && $query['operation'] == 'count') { - $results['fields'] = array('COUNT(DISTINCT ' . $this->alias . '.id)'); - } - - return $results; - } elseif ($state == 'after') { - if (isset($query['operation']) && $query['operation'] == 'count') { - if (isset($query['group']) && is_array($query['group']) && !empty($query['group'])) { - return count($results); - } - return $results[0][0]['COUNT(DISTINCT ' . $this->alias . '.id)']; - } - return $results; - } - } - -/** - * Customized paginateCount method - * - * @param array $conditions Find conditions - * @param int $recursive Recursive level - * @param array $extra Extra options - * @return array - */ - public function paginateCount($conditions = array(), $recursive = 0, $extra = array()) { - $parameters = compact('conditions'); - if ($recursive != $this->recursive) { - $parameters['recursive'] = $recursive; - } - if (isset($extra['type']) && isset($this->findMethods[$extra['type']])) { - $extra['operation'] = 'count'; - return $this->find($extra['type'], array_merge($parameters, $extra)); - } else { - return $this->find('count', array_merge($parameters, $extra)); - } - } - -/** - * Adds a new user, to be called from admin like user roles or interfaces - * - * This method is not sending any email like the register() method, its simply - * adding a new user record and sets a default role. - * - * The difference to register() is that this method here is intended to be used - * by admins to add new users without going through all the registration logic - * - * @param array post data, should be Controller->data - * @return boolean True if the data was saved successfully. - */ - public function add($postData = null) { - if (!empty($postData)) { - $this->data = $postData; - if ($this->validates()) { - if (empty($postData[$this->alias]['role'])) { - if (empty($postData[$this->alias]['is_admin'])) { - $defaultRole = Configure::read('Users.defaultRole'); - if ($defaultRole) { - $postData[$this->alias]['role'] = $defaultRole; - } else { - $postData[$this->alias]['role'] = 'registered'; - } - } else { - $postData[$this->alias]['role'] = 'admin'; - } - } - $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); - $this->create(); - $result = $this->save($postData, false); - if ($result) { - $result[$this->alias][$this->primaryKey] = $this->id; - $this->data = $result; - return true; - } - } - } - return false; - } - -/** - * Edits an existing user - * - * When saving a password it get hashed if the field is present AND not empty - * - * @param string $userId User ID - * @param array $postData controller post data usually $this->data - * @throws NotFoundException - * @return mixed True on successfully save else post data as array - */ - public function edit($userId = null, $postData = null) { - $user = $this->getUserForEditing($userId); - $this->set($user); - if (!empty($postData)) { - $this->set($postData); - if ($this->validates()) { - if (!empty($this->data[$this->alias]['password'])) { - $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['password'], 'sha1', true); - } - $result = $this->save(null, false); - if ($result) { - $this->data = $result; - return true; - } - } else { - return $postData; - } - } - } - -/** - * Gets the user data that needs to be edited - * - * Override this method and inject the conditions you need - * - * @var mixed $userId - * @var array $options - * @return array $user - * @throws NotFoundException - */ - public function getUserForEditing($userId = null, $options = array()) { - $defaults = array( - 'contain' => array(), - 'conditions' => array( - $this->alias . '.id' => $userId - ) - ); - $options = Hash::merge($defaults, $options); - - $user = $this->find('first', $options); - - if (empty($user)) { - throw new NotFoundException(__d('users', 'Invalid User')); - } - - return $user; - } - -/** - * Removes all users from the user table that are outdated - * - * Override it as needed for your specific project - * - * @return void - */ - protected function _removeExpiredRegistrations() { - $this->deleteAll(array( - $this->alias . '.email_verified' => 0, - $this->alias . '.email_token_expires <' => date('Y-m-d H:i:s')) - ); - } - -/** - * Returns a CakeEmail object - * - * @return object CakeEmail instance - * @link http://book.cakephp.org/2.0/en/core-utility-libraries/email.html - */ - public function getMailInstance() { - $emailConfig = Configure::read('Users.emailConfig'); - if ($emailConfig) { - return new CakeEmail($emailConfig); - } - return new CakeEmail('default'); - } -} diff --git a/Model/UsersAppModel.php b/Model/UsersAppModel.php deleted file mode 100644 index 94765e049..000000000 --- a/Model/UsersAppModel.php +++ /dev/null @@ -1,65 +0,0 @@ -recursive) { - $parameters['recursive'] = $recursive; - } - if (isset($extra['type']) && isset($this->findMethods[$extra['type']])) { - $extra['operation'] = 'count'; - return $this->find($extra['type'], array_merge($parameters, $extra)); - } - return $this->find('count', array_merge($parameters, $extra)); - } - -} diff --git a/README.md b/README.md deleted file mode 100644 index 84c5e08fe..000000000 --- a/README.md +++ /dev/null @@ -1,45 +0,0 @@ -CakeDC Users Plugin -=================== - -[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/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) - -The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. - -The plugin is thought as a base to extend your app specific users controller and model from. - -That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. You will have to extend the plugin on app level to customize it. Read the instructions carefully. - - -Requirements ------------- - -* CakePHP 2.5+ -* PHP 5.2.8+ -* [CakeDC Utils plugin](http://github.com/CakeDC/utils) (Optional but recommended) -* [CakeDC Search plugin](http://github.com/CakeDC/search) (Optional but recommended) - -Documentation -------------- - -For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory of this repository. - -Support -------- - -For bugs and feature requests, please use the [issues](https://github.com/CakeDC/users/issues) section of this repository. - -Commercial support is also available, [contact us](http://cakedc.com/contact) for more information. - -Contributing ------------- - -This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/contribution-guidelines) for detailed instructions. - -License -------- - -Copyright 2007-2014 Cake Development Corporation (CakeDC). All rights reserved. - -Licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) License. Redistributions of the source code included in this repository must retain the copyright notice found in each file. diff --git a/Test/Case/AllAuthenticateTest.php b/Test/Case/AllAuthenticateTest.php deleted file mode 100644 index bab10b726..000000000 --- a/Test/Case/AllAuthenticateTest.php +++ /dev/null @@ -1,22 +0,0 @@ -addTestDirectoryRecursive($path); - - return $suite; - } -} diff --git a/Test/Case/AllUsersTest.php b/Test/Case/AllUsersTest.php deleted file mode 100644 index 49233bf7b..000000000 --- a/Test/Case/AllUsersTest.php +++ /dev/null @@ -1,30 +0,0 @@ -addTestDirectory($basePath . DS . 'Controller'); - $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component'); - $Suite->addTestDirectory($basePath . DS . 'Controller' . DS . 'Component' . DS . 'Auth'); - $Suite->addTestDirectory($basePath . DS . 'Model'); - return $Suite; - } - -} \ No newline at end of file diff --git a/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php b/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php deleted file mode 100644 index 1ca0188e8..000000000 --- a/Test/Case/Controller/Component/Auth/CookieAuthenticateTest.php +++ /dev/null @@ -1,92 +0,0 @@ -request = new CakeRequest('posts/index', false); - Router::setRequestInfo($this->request); - $this->Collection = new ComponentCollection(); - $this->Collection->load('Cookie'); - $this->Collection->load('Session'); - $this->auth = new CookieAuthenticate($this->Collection, array( - 'fields' => array('username' => 'user', 'password' => 'password'), - 'userModel' => 'MultiUser', - )); - $password = Security::hash('password', null, true); - $User = ClassRegistry::init('MultiUser'); - $User->updateAll(array('password' => $User->getDataSource()->value($password))); - $this->response = $this->getMock('CakeResponse'); - } - -/** - * tearDown - * - * @return void - */ - public function tearDown() { - parent::tearDown(); - $this->Collection->Cookie->destroy(); - } - -/** - * test authenticate email or username - * - * @return void - */ - public function testAuthenticate() { - $expected = array( - 'id' => 1, - 'user' => 'mariano', - 'email' => 'mariano@example.com', - 'token' => '12345', - 'created' => '2007-03-17 01:16:23', - 'updated' => '2007-03-17 01:18:31' - ); - - $result = $this->auth->authenticate($this->request, $this->response); - $this->assertFalse($result); - - $this->Collection->Cookie->write('MultiUser', array('user' => 'mariano', 'password' => 'password')); - $result = $this->auth->authenticate($this->request, $this->response); - $this->assertEquals($expected, $result); - } -} diff --git a/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php b/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php deleted file mode 100644 index 2097812de..000000000 --- a/Test/Case/Controller/Component/Auth/MultiColumnAuthenticateTest.php +++ /dev/null @@ -1,152 +0,0 @@ -Collection = $this->getMock('ComponentCollection'); - $this->auth = new MultiColumnAuthenticate($this->Collection, array( - 'fields' => array('username' => 'user', 'password' => 'password'), - 'userModel' => 'MultiUser', - 'columns' => array('user', 'email') - )); - $password = Security::hash('password', null, true); - $User = ClassRegistry::init('MultiUser'); - $User->updateAll(array('password' => $User->getDataSource()->value($password))); - $this->response = $this->getMock('CakeResponse'); - } - -/** - * test authenticate email or username - * - * @return void - */ - public function testAuthenticateEmailOrUsername() { - $request = new CakeRequest('posts/index', false); - $expected = array( - 'id' => 1, - 'user' => 'mariano', - 'email' => 'mariano@example.com', - 'token' => '12345', - 'created' => '2007-03-17 01:16:23', - 'updated' => '2007-03-17 01:18:31' - ); - - $request->data = array('MultiUser' => array( - 'user' => 'mariano', - 'password' => 'password' - )); - $result = $this->auth->authenticate($request, $this->response); - $this->assertEquals($expected, $result); - - $request->data = array('MultiUser' => array( - 'user' => 'mariano@example.com', - 'password' => 'password' - )); - $result = $this->auth->authenticate($request, $this->response); - $this->assertEquals($expected, $result); - } - -/** - * test the authenticate method - * - * @return void - */ - public function testAuthenticateNoData() { - $request = new CakeRequest('posts/index', false); - $request->data = array(); - $this->assertFalse($this->auth->authenticate($request, $this->response)); - } - -/** - * test the authenticate method - * - * @return void - */ - public function testAuthenticateNoUsername() { - $request = new CakeRequest('posts/index', false); - $request->data = array('MultiUser' => array('password' => 'foobar')); - $this->assertFalse($this->auth->authenticate($request, $this->response)); - } - -/** - * test the authenticate method - * - * @return void - */ - public function testAuthenticateNoPassword() { - $request = new CakeRequest('posts/index', false); - $request->data = array('MultiUser' => array('user' => 'mariano')); - $this->assertFalse($this->auth->authenticate($request, $this->response)); - - $request->data = array('MultiUser' => array('user' => 'mariano@example.com')); - $this->assertFalse($this->auth->authenticate($request, $this->response)); - } - -/** - * test the authenticate method - * - * @return void - */ - public function testAuthenticateInjection() { - $request = new CakeRequest('posts/index', false); - $request->data = array( - 'MultiUser' => array( - 'user' => '> 1', - 'password' => "' OR 1 = 1" - )); - $this->assertFalse($this->auth->authenticate($request, $this->response)); - } - -/** - * test scope failure. - * - * @return void - */ - public function testAuthenticateScopeFail() { - $this->auth->settings['scope'] = array('user' => 'nate'); - $request = new CakeRequest('posts/index', false); - $request->data = array('User' => array( - 'user' => 'mariano', - 'password' => 'password' - )); - - $this->assertFalse($this->auth->authenticate($request, $this->response)); - } - -} diff --git a/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php b/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php deleted file mode 100644 index 3befe1282..000000000 --- a/Test/Case/Controller/Component/Auth/TokenAuthenticateTest.php +++ /dev/null @@ -1,120 +0,0 @@ -Collection = $this->getMock('ComponentCollection'); - $this->auth = new TokenAuthenticate($this->Collection, array( - 'fields' => array( - 'username' => 'user', - 'password' => 'password', - 'token' => 'token' - ), - 'userModel' => 'MultiUser', - )); - $password = Security::hash('password', null, true); - $User = ClassRegistry::init('MultiUser'); - $User->updateAll(array('password' => $User->getDataSource()->value($password))); - $this->response = $this->getMock('CakeResponse'); - } - -/** - * test authenticate token as query parameter - * - * @return void - */ - public function testAuthenticateTokenParameter() { - $this->auth->settings['_parameter'] = 'token'; - $request = new CakeRequest('posts/index?_token=54321'); - - $result = $this->auth->getUser($request, $this->response); - $this->assertFalse($result); - - $expected = array( - 'id' => '1', - 'user' => 'mariano', - 'email' => 'mariano@example.com', - 'token' => '12345', - 'created' => '2007-03-17 01:16:23', - 'updated' => '2007-03-17 01:18:31' - ); - $request = new CakeRequest('posts/index?_token=12345'); - $result = $this->auth->getUser($request, $this->response); - $this->assertEquals($expected, $result); - - $this->auth->settings['parameter'] = 'tokenname'; - $request = new CakeRequest('posts/index?tokenname=12345'); - $result = $this->auth->getUser($request, $this->response); - $this->assertEquals($expected, $result); - } - -/** - * test authenticate token as request header - * - * @return void - */ - public function testAuthenticateTokenHeader() { - $_SERVER['HTTP_X_APITOKEN'] = '54321'; - $request = new CakeRequest('posts/index', false); - - $result = $this->auth->getUser($request, $this->response); - $this->assertFalse($result); - - $expected = array( - 'id' => '1', - 'user' => 'mariano', - 'email' => 'mariano@example.com', - 'token' => '12345', - 'created' => '2007-03-17 01:16:23', - 'updated' => '2007-03-17 01:18:31' - ); - $_SERVER['HTTP_X_APITOKEN'] = '12345'; - $result = $this->auth->getUser($request, $this->response); - $this->assertEquals($expected, $result); - } - -} diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php deleted file mode 100644 index 7f5dbbffc..000000000 --- a/Test/Case/Controller/Component/RememberMeComponentTest.php +++ /dev/null @@ -1,171 +0,0 @@ - array( - 'email' => 'test@cakedc.com', - 'password' => 'test' - ), - 'admin' => array( - 'email' => 'admin@cakedc.com', - 'password' => 'admin' - ) - ); - -/** - * start - * - * @return void - */ - public function setUp() { - $_COOKIE = array(); - Configure::write('Config.language', 'eng'); - $this->request = new CakeRequest(); - $this->Controller = new RememberMeComponentTestController($this->request, new CakeResponse()); - $this->Controller->constructClasses(); - - $this->RememberMe = $this->Controller->RememberMe; - $this->RememberMe->Cookie = $this->getMock('CookieComponent', - array(), - array($this->Controller->Components)); - $this->RememberMe->Auth = $this->getMock('AuthComponent', - array(), - array($this->Controller->Components)); - $this->RememberMe->request = $this->request; - } - -/** - * testSetCookie - * - * @return void - */ - public function testSetCookie() { - $this->RememberMe->Cookie->expects($this->once()) - ->method('write') - ->with('rememberMe', array( - 'email' => 'email', - 'password' => 'password'), true); - - $this->RememberMe->setCookie(array( - 'User' => array( - 'email' => 'email', - 'password' => 'password') - ) - ); - } - -/** - * testRestoreLoginFromCookie - * - * @return void - */ - public function testRestoreLoginFromCookie() { - $this->RememberMe->Cookie->expects($this->any()) - ->method('read') - ->with($this->equalTo('rememberMe')) - ->will($this->returnValue($this->usersData['admin'])); - - $this->RememberMe->Auth->expects($this->once()) - ->method('login') - ->will($this->returnValue(true)); - - $this->__setPostData(array('User' => $this->usersData['test'])); - - $this->RememberMe->restoreLoginFromCookie(); - - // even if we post "test" user, we have a remember me cookie set and will prioritize the cookie over the post - // NOTE we check if the user is logged in in the startup method of the Component - $this->assertEquals($this->RememberMe->request->data, array( - 'User' => $this->usersData['admin'] - )); - } - -/** - * testRestoreLoginFromCookieIncorrectLogin - * - * We check the post request data is not modified when the cookie holds incorrect login credentials - * - * @return void - */ - public function testRestoreLoginFromCookieIncorrectLogin() { - // cookie will hold "admin" data, and post request will have "test" - $this->RememberMe->Cookie->expects($this->any()) - ->method('read') - ->with($this->equalTo('rememberMe')) - ->will($this->returnValue($this->usersData['admin'])); - // admin will not login - $this->RememberMe->Auth->expects($this->once()) - ->method('login') - ->will($this->returnValue(false)); - // post has "test" data - $this->__setPostData(array('User' => $this->usersData['test'])); - $this->RememberMe->restoreLoginFromCookie(); - $this->assertEquals($this->RememberMe->request->data, array( - 'User' => $this->usersData['test'])); - } - -/** - * testDestroyCookie - * - * @return void - */ - public function testDestroyCookie() { - $_COOKIE['User'] = 'defined'; - $this->RememberMe->Cookie->expects($this->once()) - ->method('destroy'); - $this->RememberMe->destroyCookie(); - } - -/** - * Set post data to the test controller - * - * @var array $data - * @return void - */ - private function __setPostData($data = array()) { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $this->RememberMe->request->data = $data; - } -} diff --git a/Test/Case/Controller/UsersControllerTest.php b/Test/Case/Controller/UsersControllerTest.php deleted file mode 100644 index aca10d220..000000000 --- a/Test/Case/Controller/UsersControllerTest.php +++ /dev/null @@ -1,615 +0,0 @@ -Auth->authorize = array('Controller'); - $this->Auth->fields = array('username' => 'email', 'password' => 'password'); - $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login', 'plugin' => 'users'); - $this->Auth->loginRedirect = $this->Session->read('Auth.redirect'); - $this->Auth->logoutRedirect = '/'; - $this->Auth->authError = __d('users', 'Sorry, but you need to login to access this location.'); - $this->Auth->autoRedirect = true; - $this->Auth->userModel = 'User'; - $this->Auth->userScope = array( - 'OR' => array( - 'AND' => - array('User.active' => 1, 'User.email_verified' => 1 - ) - ) - ); - } - -/** - * Public interface to _setCookie - */ - public function setCookie($options = array()) { - parent::_setCookie($options); - } - -/** - * Public intefface to _getMailInstance - */ - public function getMailInstance() { - return parent::_getMailInstance(); - } - -/** - * Auto render - * - * @var boolean - */ - public $autoRender = false; - -/** - * Redirect URL - * - * @var mixed - */ - public $redirectUrl = null; - -/** - * CakeEmail Mock - * - * @var object - */ - public $CakeEmail = null; - -/** - * Override controller method for testing - */ - public function redirect($url, $status = null, $exit = true) { - $this->redirectUrl = $url; - } - -/** - * Override controller method for testing - * - * @param string - * @param string - * @param string - * @return string - */ - public function render($action = null, $layout = null, $file = null) { - $this->renderedView = $action; - } - -/** - * Overriding the original method to return a mock object - * - * @return object CakeEmail instance - */ - protected function _getMailInstance() { - return $this->CakeEmail; - } - -} - -/** - * Email configuration override for testing - */ -class EmailConfig { - - public $default = array( - 'transport' => 'Debug', - 'from' => 'default@example.com', - ); - - public $another = array( - 'transport' => 'Debug', - 'from' => 'another@example.com', - ); -} - -class UsersControllerTestCase extends CakeTestCase { - -/** - * Instance of the controller - * - * @var mixed - */ - public $Users = null; - -/** - * Fixtures - * - * @var array - */ - public $fixtures = array( - 'plugin.users.user', - ); - -/** - * Sampletdata used for post data - * - * @var array - */ - public $usersData = array( - 'admin' => array( - 'email' => 'adminuser@cakedc.com', - 'username' => 'adminuser', - 'password' => 'test'), - 'validUser' => array( - 'email' => 'testuser@cakedc.com', - 'username' => 'testuser', - 'password' => 'secretkey', - 'redirect' => '/user/slugname'), - 'invalidUser' => array( - 'email' => 'wronguser@wronguser.com', - 'username' => 'invalidUser', - 'password' => 'invalid-password!'), - ); - -/** - * Start test - * - * @return void - */ - public function setUp() { - parent::setUp(); - - Configure::write('Config.language', 'eng'); - Configure::write('App.UserClass', null); - - $request = new CakeRequest(); - $response = $this->getMock('CakeResponse'); - - $this->Users = new TestUsersController($request, $response); - $this->Users->constructClasses(); - $this->Users->request->params = array( - 'pass' => array(), - 'named' => array(), - 'controller' => 'users', - 'admin' => false, - 'plugin' => 'users', - 'url' => array()); - - if (CakePlugin::loaded('Search')) { - $this->Users->Prg = $this->getMock('PrgComponent', - array('commonProcess'), - array($this->Users->Components, array())); - } - - $this->Users->CakeEmail = $this->getMock('CakeEmail'); - $this->Users->CakeEmail->expects($this->any()) - ->method('to') - ->will($this->returnSelf()); - $this->Users->CakeEmail->expects($this->any()) - ->method('from') - ->will($this->returnSelf()); - $this->Users->CakeEmail->expects($this->any()) - ->method('subject') - ->will($this->returnSelf()); - $this->Users->CakeEmail->expects($this->any()) - ->method('template') - ->will($this->returnSelf()); - $this->Users->CakeEmail->expects($this->any()) - ->method('viewVars') - ->will($this->returnSelf()); - $this->Users->CakeEmail->expects($this->any()) - ->method('emailFormat') - ->will($this->returnSelf()); - - $this->Users->Components->disable('Security'); - } - -/** - * Test controller instance - * - * @return void - */ - public function testUsersControllerInstance() { - $this->assertInstanceOf('UsersController', $this->Users); - } - -/** - * Test the user login - * - * @return void - */ - public function testUserLogin() { - $this->Users->request->params['action'] = 'login'; - $this->__setPost(array('User' => $this->usersData['admin'])); - $this->Users->request->url = '/users/users/login'; - - $this->Collection = $this->getMock('ComponentCollection'); - $session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session = $session; - $this->Users->Session->expects($this->any()) - ->method('setFlash') - ->with(__d('users', 'adminuser you have successfully logged in')); - $this->Users->Auth = $this->getMock('AuthComponent', array('login', 'user', 'redirectUrl'), array($this->Collection)); - $this->Users->Auth->Session = $session; - $this->Users->Auth->expects($this->once()) - ->method('login') - ->will($this->returnValue(true)); - $this->Users->Auth->staticExpects($this->at(0)) - ->method('user') - ->with('last_login') - ->will($this->returnValue(1)); - $this->Users->Auth->staticExpects($this->at(1)) - ->method('user') - ->with('id') - ->will($this->returnValue(1)); - $this->Users->Auth->staticExpects($this->at(2)) - ->method('user') - ->with('username') - ->will($this->returnValue('adminuser')); - - $this->Users->Auth->expects($this->once()) - ->method('redirectUrl') - ->with(null) - ->will($this->returnValue(Router::normalize('/'))); - - $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); - $this->Users->RememberMe->expects($this->any()) - ->method('destroyCookie'); - - $this->Users->login(); - $this->assertEquals(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); - } - -/** - * We should not see any flash message if we GET the login action - * - * @return void - */ - public function testUserLoginGet() { - // test with the login action - $this->Users->request->url = '/users/users/login'; - $this->Users->request->params['action'] = 'login'; - $this->__setGet(); - $this->Users->login(); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->never()) - ->method('setFlash'); - } - -/** - * testFailedUserLogin - * - * @return void - */ - public function testFailedUserLogin() { - $this->Users->request->params['action'] = 'login'; - $this->__setPost(array('User' => $this->usersData['invalidUser'])); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Auth = $this->getMock('AuthComponent', array('flash', 'login'), array($this->Collection)); - $this->Users->Auth->expects($this->once()) - ->method('login') - ->will($this->returnValue(false)); - $this->Users->Auth->expects($this->once()) - ->method('flash') - ->with(__d('users', 'Invalid e-mail / password combination. Please try again')); - $this->Users->login(); - } - -/** - * Test user registration - * - * @return void - */ - public function testAdd() { - $this->Users->CakeEmail->expects($this->at(0)) - ->method('send'); - $_SERVER['HTTP_HOST'] = 'test.com'; - $this->Users->params['action'] = 'add'; - $this->__setPost(array( - 'User' => array( - 'username' => 'newUser', - 'email' => 'newUser@newemail.com', - 'password' => 'password', - 'temppassword' => 'password', - 'tos' => 1))); - $this->Users->beforeFilter(); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login.')); - $this->Users->add(); - $this->__setPost(array( - 'User' => array( - 'username' => 'newUser', - 'email' => '', - 'password' => '', - 'temppassword' => '', - 'tos' => 0))); - $this->Users->beforeFilter(); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Your account could not be created. Please, try again.')); - $this->Users->add(); - } - -/** - * Test - * - * @return void - */ - public function testVerify() { - $this->Users->beforeFilter(); - $this->Users->User->id = '37ea303a-3bdc-4251-b315-1316c0b300fa'; - $this->Users->User->saveField('email_token_expires', date('Y-m-d H:i:s', strtotime('+1 year'))); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Your e-mail has been validated!')); - - $this->Users->verify('email', 'testtoken2'); - - $this->Users->beforeFilter(); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'Invalid token, please check the email you were sent, and retry the verification link.')); - - $this->Users->verify('email', 'invalid-token'); - } - -/** - * Test logout - * - * @return void - */ - public function testLogout() { - $this->Users->beforeFilter(); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Cookie = $this->getMock('CookieComponent', array(), array($this->Collection)); - $this->Users->Session = $this->getMock('SessionComponent', array('setFlash', 'destroy'), array($this->Collection)); - $this->Users->Session->expects($this->once()) - ->method('setFlash') - ->with(__d('users', 'testuser you have successfully logged out')); - $this->Users->Session->expects($this->once()) - ->method('destroy'); - $this->Users->Auth = $this->getMock('AuthComponent', array('logout', 'user'), array($this->Collection)); - $this->Users->Auth->expects($this->once()) - ->method('logout') - ->will($this->returnValue('/')); - $this->Users->Auth->staticExpects($this->at(0)) - ->method('user') - ->will($this->returnValue($this->usersData['validUser'])); - $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); - $this->Users->RememberMe->expects($this->any()) - ->method('destroyCookie'); - - $this->Users->logout(); - $this->assertEquals($this->Users->redirectUrl, '/'); - } - -/** - * testIndex - * - * @return void - */ - public function testIndex() { - $this->Users->passedArgs = array(); - $this->Users->index(); - $this->assertTrue(isset($this->Users->viewVars['users'])); - } - -/** - * testView - * - * @return void - */ - public function testView() { - $this->Users->view('adminuser'); - $this->assertTrue(isset($this->Users->viewVars['user'])); - - $this->Users->view('INVALID-SLUG'); - $this->assertEquals($this->Users->redirectUrl, '/'); - } - -/** - * change_password - * - * @return void - */ - public function testChangePassword() { - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->Auth = $this->getMock('AuthComponent', array('user'), array($this->Collection)); - $this->Users->Auth->staticExpects($this->once()) - ->method('user') - ->with('id') - ->will($this->returnValue(1)); - $this->__setPost(array( - 'User' => array( - 'new_password' => 'newpassword', - 'confirm_password' => 'newpassword', - 'old_password' => 'test'))); - $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); - $this->Users->RememberMe->expects($this->any()) - ->method('destroyCookie'); - - $this->Users->change_password(); - $this->assertEquals($this->Users->redirectUrl, '/'); - } - -/** - * testResetPassword - * - * @return void - */ - public function testResetPassword() { - $this->Users->CakeEmail->expects($this->at(0)) - ->method('send'); - $_SERVER['HTTP_HOST'] = 'test.com'; - $this->Users->User->id = '1'; - $this->Users->User->saveField('email_token_expires', date('Y-m-d H:i:s', strtotime('+1 year'))); - $this->Users->data = array( - 'User' => array( - 'email' => 'adminuser@cakedc.com' - ) - ); - $this->Users->reset_password(); - $this->assertEquals($this->Users->redirectUrl, array('action' => 'login')); - $this->Users->data = array( - 'User' => array( - 'new_password' => 'newpassword', - 'confirm_password' => 'newpassword' - ) - ); - $this->Users->reset_password('testtoken'); - $this->assertEquals($this->Users->redirectUrl, array('action' => 'reset_password')); - } - -/** - * testAdminIndex - * - * @return void - */ - public function testAdminIndex() { - $this->Users->params = array( - 'url' => array(), - 'named' => array( - 'search' => 'adminuser')); - $this->Users->passedArgs = array(); - $this->Users->admin_index(); - $this->assertTrue(isset($this->Users->viewVars['users'])); - } - -/** - * testAdminView - * - * @return void - */ - public function testAdminView() { - $this->Users->admin_view('1'); - $this->assertTrue(isset($this->Users->viewVars['user'])); - } - -/** - * testAdminDelete - * - * @return void - */ - public function testAdminDelete() { - $this->Users->User->id = '1'; - $this->assertTrue($this->Users->User->exists(true)); - $this->Users->admin_delete('1'); - $this->assertEquals($this->Users->redirectUrl, array('action' => 'index')); - $this->assertFalse($this->Users->User->exists(true)); - $this->Users->admin_delete('INVALID-ID'); - $this->assertEquals($this->Users->redirectUrl, array('action' => 'index')); - } - -/** - * Test setting the cookie - * - * @return void - */ - public function testSetCookie() { - $this->__setPost(array( - 'User' => array( - 'remember_me' => 1, - 'email' => 'testuser@cakedc.com', - 'username' => 'test', - 'password' => 'testtest'))); - $this->Collection = $this->getMock('ComponentCollection'); - $this->Users->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); - $this->Users->RememberMe->expects($this->once()) - ->method('configureCookie') - ->with(array('name' => 'userTestCookie')); - $this->Users->RememberMe->expects($this->once()) - ->method('setCookie'); - $this->Users->setCookie(array( - 'name' => 'userTestCookie')); - $this->assertEquals($this->Users->RememberMe->settings['cookieKey'], 'rememberMe'); - } - -/** - * Test getting default and setted email instance config - * - * @return void - */ - public function testGetMailInstance() { - $defaultConfig = $this->Users->getMailInstance()->config(); - $this->assertEquals($defaultConfig['from'], 'default@example.com'); - Configure::write('Users.emailConfig', 'another'); - $anotherConfig = $this->Users->getMailInstance()->config(); - $this->assertEquals($anotherConfig['from'], 'another@example.com'); - $this->setExpectedException('ConfigureException'); - Configure::write('Users.emailConfig', 'doesnotexist'); - $anotherConfig = $this->Users->getMailInstance()->config(); - } - -/** - * Test - * - * @var array $data - * @return void - */ - private function __setPost($data = array()) { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $this->Users->request->data = array_merge($data, array('_method' => 'POST')); - } - -/** - * Test - * - * @return void - */ - private function __setGet() { - $_SERVER['REQUEST_METHOD'] = 'GET'; - } - -/** - * Test - * - * @var string $method unused variable - * @return void - */ - public function endTest($method) { - unset($this->Users); - ClassRegistry::flush(); - } - -} diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php deleted file mode 100755 index dd8185d69..000000000 --- a/Test/Case/Model/UserTest.php +++ /dev/null @@ -1,494 +0,0 @@ -User = ClassRegistry::init('Users.User'); - } - -/** - * endTest - * - * @return void - */ - public function tearDown() { - parent::tearDown(); - unset($this->User); - ClassRegistry::flush(); - } - -/** - * Test User Instance - * - * @return void - */ - public function testUserInstance() { - $this->assertTrue(is_a($this->User, 'User')); - } - -/** - * Test to compare the passwords when a user adds - * - * @return void - */ - public function testConfirmPassword() { - $this->User->data['User']['password'] = 'password'; - $result = $this->User->confirmPassword(array('temppassword' => 'password')); - $this->assertTrue($result); - - $this->User->data['User']['password'] = 'different_password'; - $result = $this->User->confirmPassword(array('temppassword' => 'password')); - $this->assertFalse($result); - } - -/** - * testValidateEmailConfirmation - * - * @return void - */ - public function testConfirmEmail() { - $this->User->data['User'] = array( - 'email' => 'test@email.com'); - $this->assertFalse($this->User->confirmEmail(array('confirm_email' => 'test@wrong.com'))); - - $this->User->data['User'] = array( - 'email' => 'test@email.com'); - $this->assertTrue($this->User->confirmEmail(array('confirm_email' => 'test@email.com'))); - } - -/** - * Test if the generated token is a string - * - * @return void - */ - public function testGenerateToken() { - $result = $this->User->generateToken(); - $this->assertInternalType('string', $result); - } - -/** - * testUpdateLastActivity - * - * @return void - */ - public function testUpdateLastActivity() { - $id = 1; - $this->User->id = $id; - $lastDate = $this->User->field('last_action'); - $result = $this->User->updateLastActivity($id); - $this->assertTrue(is_array($result)); - $this->User->id = $id; - $newDate = $result['User']['last_action']; - $this->assertTrue($lastDate < $newDate); - $this->assertFalse($this->User->updateLastActivity('invalid-id!')); - } - - -/** - * testResetPassword - * - * @return void - */ - public function testResetPassword() { - $data = array( - 'User' => array( - 'id' => 1, - 'new_password' => '', - 'confirm_password' => 'dsgdsgsdg')); - $this->assertFalse($this->User->resetPassword($data)); - - $data = array( - 'User' => array( - 'id' => 1, - 'new_password' => '', - 'confirm_password' => '')); - $this->assertFalse($this->User->resetPassword($data)); - - $data = array( - 'User' => array( - 'id' => 1, - 'new_password' => 'newpassword', - 'confirm_password' => 'newpassword')); - $this->assertInternalType('array', $this->User->resetPassword($data)); - } - -/** - * testCheckPasswordToken - * - * @return void - */ - public function testCheckPasswordToken() { - $this->User->id = '1'; - $this->User->saveField('email_token_expires', date('Y-m-d H:i:s', strtotime('+1 year'))); - $this->assertInternalType('array', $this->User->checkPasswordToken('testtoken')); - $this->assertFalse($this->User->checkPasswordToken('something-wrong-here')); - } - -/** - * testPasswordReset - * - * @return void - */ - public function testPasswordReset() { - $data = array( - 'User' => array( - 'id' => 1, - 'email' => 'somethingwrong in here!')); - $this->assertFalse($this->User->passwordReset($data)); - - $this->User->id = '1'; - $this->User->saveField('email_token_expires', date('Y-m-d H:i:s', strtotime('+1 year'))); - $data = array( - 'User' => array( - 'id' => 1, - 'email' => 'adminuser@cakedc.com')); - $this->assertInternalType('array', $this->User->passwordReset($data)); - } - -/** - * testValidateOldPassword - * - * @return void - */ - public function testValidateOldPassword() { - $password = $this->User->hash('password', null, true); - $this->User->id = '1'; - $this->User->saveField('password', $password); - $this->User->data = array( - 'User' => array( - 'id' => '1', - 'password')); - - $result = $this->User->validateOldPassword(array('old_password' => 'password')); - $this->assertTrue($result); - - $result = $this->User->validateOldPassword(array('old_password' => 'FAIL!')); - $this->assertFalse($result); - } - -/** - * testView - * - * @return void - */ - public function testView() { - $result = $this->User->view('adminuser'); - $this->assertTrue(is_array($result) && !empty($result)); - - $this->expectException('NotFoundException'); - $result = $this->User->view('non-existing-user-slug'); - } - -/** - * Test the user registration method - * - * @return void - */ - public function testRegister() { - $postData = array(); - $result = $this->User->register($postData); - $this->assertFalse($result); - - $postData = array('User' => array( - 'username' => '#236236326sdg!!!.s#invalid', - 'email' => 'invalid', - 'password' => 'password', - 'temppassword' => 'wrong', - 'tos' => 0)); - $result = $this->User->register($postData); - $this->assertFalse($result); - $this->assertEquals(array_keys($this->User->invalidFields()), array( - 'username', 'email', 'temppassword', 'tos')); - - $postData = array('User' => array( - 'username' => 'validusername', - 'email' => 'test@test.com', - 'password' => '12345', - 'temppassword' => '12345', - 'tos' => 1)); - $result = $this->User->register($postData); - $this->assertFalse($result); - $this->assertEquals(array_keys($this->User->invalidFields()), array( - 'password')); - - $postData = array('User' => array( - 'username' => 'imanewuser', - 'email' => 'foo@bar.com', - 'password' => 'password', - 'temppassword' => 'password', - 'tos' => 1)); - $result = $this->User->register($postData, array('returnData' => false)); - $this->assertTrue($result); - $result = $this->User->data; - - $this->assertEquals($result['User']['active'], 1); - $this->assertEquals($result['User']['password'], $this->User->hash('password', 'sha1', true)); - $this->assertTrue(is_string($result['User']['email_token'])); - - $result = $this->User->findById($this->User->id); - $this->assertEquals($result['User']['id'], $this->User->id); - } - -/** - * testChangePassword - * - * @return void - */ - public function testChangePassword() { - $postData = array(); - $result = $this->User->changePassword($postData); - $this->assertFalse($result); - - $postData = array( - 'User' => array( - 'id' => 1, - 'old_password' => 'test', - 'new_password' => 'not', - 'confirm_password' => 'equal')); - - $result = $this->User->changePassword($postData); - $this->assertFalse($result); - $this->assertEquals(array('new_password', 'confirm_password'), array_keys($this->User->invalidFields())); - - $postData = array( - 'User' => array( - 'id' => 1, - 'old_password' => 'test', - 'new_password' => 'testtest', - 'confirm_password' => 'testtest')); - $result = $this->User->changePassword($postData); - $this->assertTrue($result); - $ressult = $this->User->find('first', array( - 'recursive' => -1, - 'conditions' => array( - 'User.id' => 1))); - $this->assertEquals($ressult['User']['password'], $this->User->hash('testtest', null, true)); - } - -/** - * Test validation method to compare two fields - * - * @return void - */ - public function testCompareFields() { - $this->User->data = array( - 'User' => array( - 'field1' => 'foo', - 'field2' => 'bar')); - $this->assertFalse($this->User->compareFields('field1', 'field2')); - - $this->User->data = array( - 'User' => array( - 'field1' => 'foo', - 'field2' => 'foo')); - $this->assertTrue($this->User->compareFields('field1', 'field2')); - } - -/** - * Test resending of the email authentication - * - * @return void - */ - public function testResendVerification() { - $postData = array( - 'User' => array()); - $this->assertFalse($this->User->resendVerification($postData)); - - $postData = array( - 'User' => array( - 'email' => 'doesnotexist!')); - $this->assertFalse($this->User->resendVerification($postData)); - - $postData = array( - 'User' => array( - 'email' => 'adminuser@cakedc.com')); - $this->assertFalse($this->User->resendVerification($postData)); - - $postData = array( - 'User' => array( - 'email' => 'oidtest2@testuser.com')); - $result = $this->User->resendVerification($postData); - $this->assertTrue(is_array($result)); - } - -/** - * Test resending of the email authentication - * - * @return void - */ - public function testGeneratePassword() { - $result = $this->User->generatePassword(); - $this->assertInternalType('string', $result); - $this->assertEquals(strlen($result), 10); - - $result = $this->User->generatePassword(15); - $this->assertInternalType('string', $result); - $this->assertEquals(strlen($result), 15); - } - -/** - * testDelete - * - * @return void - */ - public function testDelete() { - $this->User->id = '1'; - $this->assertTrue($this->User->exists()); - $this->assertTrue($this->User->delete('1')); - $this->assertFalse($this->User->exists()); - } - -/** - * testAdd - * - * @return void - */ - public function testAdd() { - $postData = array( - 'User' => array( - 'username' => 'newusername', - 'email' => 'newusername@newusername.com', - 'password' => 'password', - 'temppassword' => 'password', - 'tos' => 1)); - $result = $this->User->add($postData); - $this->assertTrue($result); - } - -/** - * testEdit - * - * @return void - **/ - public function testEdit() { - $userId = '1'; - $data = $this->User->read(null, $userId); - $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; - - $result = $this->User->edit(1, $data); - $this->assertTrue($result); - - $result = $this->User->read(null, 1); - $this->assertEquals($result['User']['username'], $data['User']['username']); - $this->assertEquals($result['User']['email'], $data['User']['email']); - - $result = $this->User->edit(1); - $this->assertNull($result); - } - -/** - * testEditPassword - * - * @return void - **/ - public function testEditPassword() { - $userId = '1'; - $data = $this->User->read(null, $userId); - $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; - $data['User']['password'] = 'anotherNewPassword'; - $data['User']['temppassword'] = 'anotherNewPassword'; - - $result = $this->User->edit(1, $data); - - $hashPassword = $this->User->hash($data['User']['password'], 'sha1', true); - $this->assertTrue($result); - $this->assertEquals($this->User->data['User']['password'], $hashPassword); - - $data2['User']['email'] = 'anotherEmail@anotheremail.com'; - $data2['User']['password'] = 'anotherNewPassword'; - $data2['User']['temppassword'] = 'differentPassword'; - - $this->User->edit(1, $data2); - - $invalid = $this->User->invalidFields(); - - $this->assertTrue(isset($invalid['temppassword'])); - $this->assertFalse($this->User->validates()); - $this->assertNotEquals($data, $data2); - } - -/** - * testEditException - * - * @return void - */ - public function testEditException() { - $this->setExpectedException('NotFoundException'); - $userId = '1'; - $data = $this->User->read(null, $userId); - $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; - $this->User->edit('bogus id', $userId, $data); - } - -/** - * testDisableSlugs - * - * @return void - */ - public function testDisableSlugs() { - $this->skipIf(CakePlugin::loaded('Utils') === false, __('Utils plugin not present, test skipped.')); - - ClassRegistry::flush(); - $this->User = ClassRegistry::init('Users.User'); - $this->User->create(); - $this->User->save(array( - 'username' => 'foo2'), array('validate' => false)); - $result = $this->User->read(null, $this->User->id); - $this->assertEquals($result['User']['slug'], 'foo2'); - - ClassRegistry::flush(); - Configure::write('Users.disableSlugs', true); - $this->User = ClassRegistry::init('Users.User'); - $this->User->create(); - $this->User->save(array( - 'username' => 'bar2'), array('validate' => false)); - $result = $this->User->read(null, $this->User->id); - $this->assertTrue(empty($result['User']['slug'])); - } - -} diff --git a/Test/Fixture/MultiUserFixture.php b/Test/Fixture/MultiUserFixture.php deleted file mode 100644 index 230ecb2fe..000000000 --- a/Test/Fixture/MultiUserFixture.php +++ /dev/null @@ -1,38 +0,0 @@ - array('type' => 'integer', 'key' => 'primary'), - 'user' => array('type' => 'string', 'null' => false), - 'email' => array('type' => 'string', 'null' => false), - 'password' => array('type' => 'string', 'null' => false), - 'token' => array('type' => 'string', 'null' => false), - 'created' => 'datetime', - 'updated' => 'datetime' - ); - -/** - * records property - * - * @var array - */ - public $records = array( - array('user' => 'mariano', 'email' => 'mariano@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '12345', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), - array('user' => 'nate', 'email' => 'nate@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '23456', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31'), - array('user' => 'larry', 'email' => 'larry@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '34567', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31'), - array('user' => 'garrett', 'email' => 'garrett@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '45678', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31'), - array('user' => 'chartjes', 'email' => 'chartjes@example.com', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'token' => '56789', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31'), - ); -} diff --git a/Test/Fixture/UserFixture.php b/Test/Fixture/UserFixture.php deleted file mode 100644 index 838df1cd2..000000000 --- a/Test/Fixture/UserFixture.php +++ /dev/null @@ -1,195 +0,0 @@ - array('type' => 'string', 'null' => false, 'length' => 36, 'key' => 'primary'), - 'username' => array('type' => 'string', 'null' => false, 'default' => null), - 'slug' => array('type' => 'string', 'null' => false, 'default' => null), - 'password' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), - 'password_token' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 128), - 'email' => array('type' => 'string', 'null' => true, 'default' => null), - 'email_verified' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'email_token' => array('type' => 'string', 'null' => true, 'default' => null), - 'email_token_expires' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'tos' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'active' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'last_action' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'last_login' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'is_admin' => array('type' => 'boolean', 'null' => true, 'default' => '0'), - 'role' => array('type' => 'string', 'null' => true, 'default' => null), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1)) - ); - -/** - * Records - * - * @var array - */ - public $records = array( - array( - 'id' => '1', - 'username' => 'adminuser', - 'slug' => 'adminuser', - 'password' => 'test', // test - 'password_token' => 'testtoken', - 'email' => 'adminuser@cakedc.com', - 'email_verified' => 1, - 'email_token' => 'testtoken', - 'email_token_expires' => '2008-03-25 02:45:46', - 'tos' => 1, - 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', - 'last_login' => '2008-03-25 02:45:46', - 'is_admin' => 1, - 'role' => 'admin', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' - ), - array( - 'id' => '47ea303a-3cyc-k251-b313-4811c0a800bf', - 'username' => 'testuser', - 'slug' => 'testuser', - 'password' => 'secretkey', // secretkey - 'password_token' => '', - 'email' => 'testuser@cakedc.com', - 'email_verified' => '1', - 'email_token' => '', - 'email_token_expires' => '2008-03-25 02:45:46', - 'tos' => 1, - 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', - 'last_login' => '2008-03-25 02:45:46', - 'is_admin' => 0, - 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' - ), - array( - 'id' => '37ea303a-3bdc-4251-b315-1316c0b300fa', - 'username' => 'user1', - 'slug' => 'user1', - 'password' => 'newpass', // newpass - 'password_token' => '', - 'email' => 'testuser1@testuser.com', - 'email_verified' => 0, - 'email_token' => 'testtoken2', - 'email_token_expires' => '2008-03-28 02:45:46', - 'tos' => 0, - 'active' => 0, - 'last_action' => '2008-03-25 02:45:46', - 'last_login' => '2008-03-25 02:45:46', - 'is_admin' => 0, - 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' - ), - array( - 'id' => '495e36a2-1f00-46b9-8247-58a367265f11', - 'username' => 'oidtest', - 'slug' => 'oistest', - 'password' => 'newpass', // newpass - 'password_token' => '', - 'email' => 'oidtest@testuser.com', - 'email_verified' => 0, - 'email_token' => 'testtoken2', - 'email_token_expires' => '2008-03-28 02:45:46', - 'tos' => 0, - 'active' => 0, - 'last_action' => '2008-03-25 02:45:46', - 'last_login' => '2008-03-25 02:45:46', - 'is_admin' => 0, - 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' - ), - array( - 'id' => '315e36a2-1fxj-46b9-8247-58a367265f11', - 'username' => 'oidtest2', - 'slug' => 'oistest', - 'password' => 'newpass', // newpass - 'password_token' => '', - 'email' => 'oidtest2@testuser.com', - 'email_verified' => 0, - 'email_token' => 'testtoken2', - 'email_token_expires' => '2008-03-28 02:45:46', - 'tos' => 1, - 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', - 'last_login' => '2008-03-25 02:45:46', - 'is_admin' => 0, - 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' - ), - array( - 'id' => '515e36a2-5fjj-46b9-8247-584367265f11', - 'username' => 'resetuser', - 'slug' => 'resetuser', - 'password' => 'newpass', // newpass - 'password_token' => 'testtoken', - 'email' => 'resetuser@testuser.com', - 'email_verified' => 1, - 'email_token' => 'testtoken', - 'email_token_expires' => '2008-03-28 02:45:46', - 'tos' => 1, - 'active' => 1, - 'last_action' => '2008-03-25 02:45:46', - 'last_login' => '2008-03-25 02:45:46', - 'is_admin' => 0, - 'role' => 'user', - 'created' => '2008-03-25 02:45:46', - 'modified' => '2008-03-25 02:45:46' - ) - ); - -/** - * Constructor - * - */ - public function __construct() { - parent::__construct(); - $this->User = ClassRegistry::init('Users.User'); - foreach ($this->records as &$record) { - $record['password'] = $this->User->hash($record['password'], null, true); - } - } - -} diff --git a/View/Elements/Users/admin_sidebar.ctp b/View/Elements/Users/admin_sidebar.ctp deleted file mode 100644 index fb93c0c38..000000000 --- a/View/Elements/Users/admin_sidebar.ctp +++ /dev/null @@ -1,11 +0,0 @@ -
-
    -
  • Html->link(__d('users', 'Logout'), array('admin' => false, 'action' => 'logout')); ?> -
  • Html->link(__d('users', 'My Account'), array('admin' => false, 'action' => 'edit')); ?> -
  •  
  • -
  • Html->link(__d('users', 'Add Users'), array('admin' => true, 'action'=>'add'));?>
  • -
  • Html->link(__d('users', 'List Users'), array('admin' => true, 'action'=>'index'));?>
  • -
  •  
  • -
  • Html->link(__d('users', 'Frontend'), array('admin' => false, 'action'=>'index')); ?>
  • -
-
\ No newline at end of file diff --git a/View/Elements/Users/sidebar.ctp b/View/Elements/Users/sidebar.ctp deleted file mode 100644 index 68bc08a98..000000000 --- a/View/Elements/Users/sidebar.ctp +++ /dev/null @@ -1,18 +0,0 @@ -
-
    - Session->read('Auth.User.id')) : ?> -
  • Html->link(__d('users', 'Login'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'login')); ?>
  • - -
  • Html->link(__d('users', 'Register an account'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'add')); ?>
  • - - -
  • Html->link(__d('users', 'Logout'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'logout')); ?> -
  • Html->link(__d('users', 'My Account'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'edit')); ?> -
  • Html->link(__d('users', 'Change password'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'change_password')); ?> - - Session->read('Auth.User.is_admin')) : ?> -
  •  
  • -
  • Html->link(__d('users', 'List Users'), array('plugin' => 'users', 'controller' => 'users', 'action' => 'index'));?>
  • - -
-
diff --git a/View/Elements/pagination.ctp b/View/Elements/pagination.ctp deleted file mode 100644 index ca280b6ab..000000000 --- a/View/Elements/pagination.ctp +++ /dev/null @@ -1,18 +0,0 @@ - -
- Paginator->prev('< ' . __d('users', 'previous'), array(), null, array('class' => 'prev disabled')); - echo $this->Paginator->numbers(array('separator' => '')); - echo $this->Paginator->next(__d('users', 'next') . ' >', array(), null, array('class' => 'next disabled')); - ?> -
diff --git a/View/Elements/paging.ctp b/View/Elements/paging.ctp deleted file mode 100644 index 477e734dc..000000000 --- a/View/Elements/paging.ctp +++ /dev/null @@ -1,4 +0,0 @@ -Paginator->counter(array( - 'format' => 'Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%')); -?> \ No newline at end of file diff --git a/View/Emails/text/account_verification.ctp b/View/Emails/text/account_verification.ctp deleted file mode 100644 index e884215e5..000000000 --- a/View/Emails/text/account_verification.ctp +++ /dev/null @@ -1,16 +0,0 @@ - false, 'plugin' => 'users', 'controller' => 'users', 'action' => 'verify', 'email', $user[$model]['email_token']), true); diff --git a/View/Emails/text/new_password.ctp b/View/Emails/text/new_password.ctp deleted file mode 100644 index 08f9571e7..000000000 --- a/View/Emails/text/new_password.ctp +++ /dev/null @@ -1,15 +0,0 @@ - false, 'plugin' => 'users', 'controller' => 'users', 'action' => 'reset_password', $token), true); diff --git a/View/Users/add.ctp b/View/Users/add.ctp deleted file mode 100644 index c736d7d5c..000000000 --- a/View/Users/add.ctp +++ /dev/null @@ -1,36 +0,0 @@ - -
-

-
- Form->create($model); - echo $this->Form->input('username', array( - 'label' => __d('users', 'Username'))); - echo $this->Form->input('email', array( - 'label' => __d('users', 'E-mail (used as login)'), - 'error' => array('isValid' => __d('users', 'Must be a valid email address'), - 'isUnique' => __d('users', 'An account with that email already exists')))); - echo $this->Form->input('password', array( - 'label' => __d('users', 'Password'), - 'type' => 'password')); - echo $this->Form->input('temppassword', array( - 'label' => __d('users', 'Password (confirm)'), - 'type' => 'password')); - $tosLink = $this->Html->link(__d('users', 'Terms of Service'), array('controller' => 'pages', 'action' => 'tos', 'plugin' => null)); - echo $this->Form->input('tos', array( - 'label' => __d('users', 'I have read and agreed to ') . $tosLink)); - echo $this->Form->end(__d('users', 'Submit')); - ?> -
-
-element('Users.Users/sidebar'); ?> diff --git a/View/Users/admin_add.ctp b/View/Users/admin_add.ctp deleted file mode 100644 index 8b0efff4e..000000000 --- a/View/Users/admin_add.ctp +++ /dev/null @@ -1,41 +0,0 @@ - -
- Form->create($model); ?> -
- - Form->input('username', array( - 'label' => __d('users', 'Username'))); - echo $this->Form->input('email', array( - 'label' => __d('users', 'E-mail (used as login)'), - 'error' => array('isValid' => __d('users', 'Must be a valid email address'), - 'isUnique' => __d('users', 'An account with that email already exists')))); - echo $this->Form->input('password', array( - 'label' => __d('users', 'Password'), - 'type' => 'password')); - echo $this->Form->input('temppassword', array( - 'label' => __d('users', 'Password (confirm)'), - 'type' => 'password')); - if (!empty($roles)) { - echo $this->Form->input('role', array( - 'label' => __d('users', 'Role'), 'values' => $roles)); - } - echo $this->Form->input('is_admin', array( - 'label' => __d('users', 'Is Admin'))); - echo $this->Form->input('active', array( - 'label' => __d('users', 'Active'))); - ?> -
- Form->end('Submit'); ?> -
-element('Users.Users/admin_sidebar'); ?> \ No newline at end of file diff --git a/View/Users/admin_edit.ctp b/View/Users/admin_edit.ctp deleted file mode 100644 index 02cd058ca..000000000 --- a/View/Users/admin_edit.ctp +++ /dev/null @@ -1,34 +0,0 @@ - -
- Form->create($model); ?> -
- - Form->input('id'); - echo $this->Form->input('username', array( - 'label' => __d('users', 'Username'))); - echo $this->Form->input('email', array( - 'label' => __d('users', 'Email'))); - if (!empty($roles)) { - echo $this->Form->input('role', array( - 'label' => __d('users', 'Role'), 'values' => $roles)); - } - echo $this->Form->input('is_admin', array( - 'label' => __d('users', 'Is Admin'))); - echo $this->Form->input('active', array( - 'label' => __d('users', 'Active'))); - ?> -
- Form->end('Submit'); ?> -
-element('Users.Users/admin_sidebar'); ?> \ No newline at end of file diff --git a/View/Users/admin_index.ctp b/View/Users/admin_index.ctp deleted file mode 100644 index b89b567c2..000000000 --- a/View/Users/admin_index.ctp +++ /dev/null @@ -1,70 +0,0 @@ - -
-

- - ' . __d('users', 'Filter') . ''; - echo $this->Form->create($model, array('action' => 'index')); - echo $this->Form->input('username', array('label' => __d('users', 'Username'))); - echo $this->Form->input('email', array('label' => __d('users', 'Email'))); - echo $this->Form->end(__d('users', 'Search')); - } - ?> - - element('Users.paging'); ?> - element('Users.pagination'); ?> - - - - - - - - - - - > - - - - - - - - -
Paginator->sort('username'); ?>Paginator->sort('email'); ?>Paginator->sort('email_verified'); ?>Paginator->sort('active'); ?>Paginator->sort('created'); ?>
- - - - - - - - - - - Html->link(__d('users', 'View'), array('action' => 'view', $user[$model]['id'])); ?> - Html->link(__d('users', 'Edit'), array('action' => 'edit', $user[$model]['id'])); ?> - Html->link(__d('users', 'Delete'), array('action' => 'delete', $user[$model]['id']), null, sprintf(__d('users', 'Are you sure you want to delete # %s?'), $user[$model]['id'])); ?> -
- element('Users.pagination'); ?> -
-element('Users.Users/admin_sidebar'); ?> diff --git a/View/Users/admin_view.ctp b/View/Users/admin_view.ctp deleted file mode 100644 index 8960a41ba..000000000 --- a/View/Users/admin_view.ctp +++ /dev/null @@ -1,32 +0,0 @@ - -
-

-
- > - > - -   - - > - > - -   - - > - > - -   - -
-
-element('Users.Users/admin_sidebar'); ?> \ No newline at end of file diff --git a/View/Users/change_password.ctp b/View/Users/change_password.ctp deleted file mode 100644 index 3817a0532..000000000 --- a/View/Users/change_password.ctp +++ /dev/null @@ -1,29 +0,0 @@ - -
-

-

- Form->create($model, array('action' => 'change_password')); - echo $this->Form->input('old_password', array( - 'label' => __d('users', 'Old Password'), - 'type' => 'password')); - echo $this->Form->input('new_password', array( - 'label' => __d('users', 'New Password'), - 'type' => 'password')); - echo $this->Form->input('confirm_password', array( - 'label' => __d('users', 'Confirm'), - 'type' => 'password')); - echo $this->Form->end(__d('users', 'Submit')); - ?> -
-element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/dashboard.ctp b/View/Users/dashboard.ctp deleted file mode 100644 index 41cccf50b..000000000 --- a/View/Users/dashboard.ctp +++ /dev/null @@ -1,15 +0,0 @@ - -
-

-

-
\ No newline at end of file diff --git a/View/Users/edit.ctp b/View/Users/edit.ctp deleted file mode 100644 index cc929de0b..000000000 --- a/View/Users/edit.ctp +++ /dev/null @@ -1,22 +0,0 @@ - -
- Form->create($model); ?> -
- -

- Html->link(__d('users', 'Change your password'), array('action' => 'change_password')); ?> -

-
- Form->end(__d('users', 'Submit')); ?> -
-element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/index.ctp b/View/Users/index.ctp deleted file mode 100644 index 82116ca27..000000000 --- a/View/Users/index.ctp +++ /dev/null @@ -1,46 +0,0 @@ - -
-

- -

Paginator->counter(array( - 'format' => __d('users', 'Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%') - )); - ?>

- - - - - - - - - > - - - - - -
Paginator->sort('username'); ?>Paginator->sort('created'); ?>
Html->link($user[$model]['username'], array('action' => 'view', $user[$model]['id'])); ?> - Html->link(__d('users', 'View'), array('action' => 'view', $user[$model]['id'])); ?> -
- element('Users.pagination'); ?> -
-element('Users.Users/sidebar'); ?> diff --git a/View/Users/login.ctp b/View/Users/login.ctp deleted file mode 100644 index f6fde0dcc..000000000 --- a/View/Users/login.ctp +++ /dev/null @@ -1,33 +0,0 @@ - -
-

- Session->flash('auth');?> -
- Form->create($model, array( - 'id' => 'LoginForm')); - echo $this->Form->input('email', array( - 'label' => __d('users', 'Email'))); - echo $this->Form->input('password', array( - 'label' => __d('users', 'Password'))); - - echo '

' . $this->Form->input('remember_me', array('type' => 'checkbox', 'label' => __d('users', 'Remember Me'))) . '

'; - echo '

' . $this->Html->link(__d('users', 'I forgot my password'), array('action' => 'reset_password')) . '

'; - - echo $this->Form->hidden('User.return_to', array( - 'value' => $return_to)); - echo $this->Form->end(__d('users', 'Submit')); - ?> -
-
-element('Users.Users/sidebar'); ?> diff --git a/View/Users/request_password_change.ctp b/View/Users/request_password_change.ctp deleted file mode 100644 index a62b0a3d2..000000000 --- a/View/Users/request_password_change.ctp +++ /dev/null @@ -1,26 +0,0 @@ - -
-

-

-Form->create($model, array( - 'url' => array( - 'admin' => false, - 'action' => 'reset_password'))); - echo $this->Form->input('email', array( - 'label' => __d('users', 'Your Email'))); - echo $this->Form->submit(__d('users', 'Submit')); - echo $this->Form->end(); -?> -
-element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/resend_verification.ctp b/View/Users/resend_verification.ctp deleted file mode 100644 index cfa55f022..000000000 --- a/View/Users/resend_verification.ctp +++ /dev/null @@ -1,26 +0,0 @@ - -
-

-

- Form->create($model, array( - 'url' => array( - 'admin' => false, - 'action' => 'resend_verification'))); - echo $this->Form->input('email', array( - 'label' => __d('users', 'Your Email'))); - echo $this->Form->submit(__d('users', 'Submit')); - echo $this->Form->end(); - ?> -
-element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/reset_password.ctp b/View/Users/reset_password.ctp deleted file mode 100644 index 325a2aa1b..000000000 --- a/View/Users/reset_password.ctp +++ /dev/null @@ -1,18 +0,0 @@ -
-

-Form->create($model, array( - 'url' => array( - 'action' => 'reset_password', - $token))); - echo $this->Form->input('new_password', array( - 'label' => __d('users', 'New Password'), - 'type' => 'password')); - echo $this->Form->input('confirm_password', array( - 'label' => __d('users', 'Confirm'), - 'type' => 'password')); - echo $this->Form->submit(__d('users', 'Submit')); - echo $this->Form->end(); -?> -
-element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/search.ctp b/View/Users/search.ctp deleted file mode 100644 index 4e10d788e..000000000 --- a/View/Users/search.ctp +++ /dev/null @@ -1,63 +0,0 @@ - -
-

- Form->create($model, array( - 'action' => 'search')); - echo $this->Form->input('username', array( - 'label' => __d('users', 'Username'))); - echo $this->Form->input('email', array( - 'label' => __d('users', 'Email'))); - echo $this->Form->input('Profile.name', array( - 'label' => __d('users', 'Name'))); - echo $this->Form->end(__d('users', 'Search')); - ?> -

Paginator->counter(array( - 'format' => __d('users', 'Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%') - )); - ?>

- - - - - - - - - > - - - - - -
Paginator->sort('username'); ?>Paginator->sort('created'); ?>
- Html->link(__d('users', 'View'), array('action' => 'view', $user[$model]['id'])); ?> - Html->link(__d('users', 'Edit'), array('action' => 'edit', $user[$model]['id'])); ?> - Html->link( - __d('users', 'Delete'), - array('action' => 'delete', $user[$model]['id']), - null, - sprintf(__d('users', 'Are you sure you want to delete # %s?'), $user[$model]['id']) - ); ?> -
- element('Users.paging'); ?> -
-element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/View/Users/view.ctp b/View/Users/view.ctp deleted file mode 100644 index c80f27152..000000000 --- a/View/Users/view.ctp +++ /dev/null @@ -1,37 +0,0 @@ - -
-

-
- > - > - -   - - > - > - -   - - $details) : - foreach ($details as $field => $value) : - echo '
' . $section . ' - ' . $field . '
'; - echo '
' . $value . '
'; - endforeach; - endforeach; - endif; - ?> -
-
-element('Users.Users/sidebar'); ?> \ No newline at end of file diff --git a/composer.json b/composer.json deleted file mode 100644 index 994be689f..000000000 --- a/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "cakedc/users", - "description": "Users Plugin for CakePHP", - "type": "cakephp-plugin", - "keywords": ["cakephp","users","auth"], - "homepage": "http://cakedc.com", - "license": "MIT", - "authors": [ - { - "name": "Cake Development Corporation", - "email": "team@cakedc.com", - "homepage": "http://cakedc.com" - } - ], - "support": { - "email": "team@cakedc.com", - "issues": "https://github.com/CakeDC/users/issues", - "forum": "http://stackoverflow.com/tags/cakedc", - "wiki": "https://github.com/CakeDC/users/blob/master/Docs/Home.md", - "irc": "irc://irc.freenode.org/cakephp", - "source": "https://github.com/CakeDC/users" - }, - "require": { - "php": ">=5.2.8", - "composer/installers": "*" - }, - "suggest": { - "cakedc/search": "Search functionality for the admin.", - "cakedc/utils": "If you want to generate slugs based on the username." - }, - "extra": { - "installer-name": "Users" - } -} From a169a09c8ee32477617aab0f9331cc1f02523b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 29 Jul 2015 19:02:03 +0100 Subject: [PATCH 0143/1476] CakeDC Users migration to CakePHP 3.x, featuring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Social login * User management * Roles and SimpleRbac rules Initial migration version by Alejandro Ibarra, Yelitza Parra and Jorge González. Peer code review by Chris Burke and Jad Bitar. Big thanks to: * CakeDC, of course, http://cakedc.com * https://github.com/uzyn/cakephp-opauth Plugin ideas used for our Opauth integration --- CONTRIBUTING.md | 2 +- Docs/Documentation/Configuration.md | 149 ++ Docs/Documentation/Events.md | 53 + Docs/Documentation/Extending-the-Plugin.md | 147 ++ Docs/Documentation/Installation.md | 74 + Docs/Documentation/Overview.md | 17 + Docs/Documentation/SimpleRbacAuthorize.md | 87 ++ Docs/Documentation/SocialAuthenticate.md | 82 ++ Docs/Documentation/SuperuserAuthorize.md | 18 + Docs/Home.md | 30 + LICENSE.txt | 1 + README.md | 71 + composer.json | 29 + composer.lock | 1297 +++++++++++++++++ config/Migrations/20150513201111_initial.php | 186 +++ config/bootstrap.php | 21 + config/permissions.php | 78 + config/routes.php | 33 + config/users.php | 114 ++ phpunit.xml.dist | 36 + src/Auth/Factory/OpauthFactory.php | 35 + src/Auth/RememberMeAuthenticate.php | 51 + src/Auth/SimpleRbacAuthorize.php | 239 +++ src/Auth/SocialAuthenticate.php | 75 + src/Auth/SuperuserAuthorize.php | 53 + src/Controller/AppController.php | 33 + .../Component/RememberMeComponent.php | 152 ++ .../Component/UsersAuthComponent.php | 178 +++ src/Controller/SocialAccountsController.php | 92 ++ .../Traits/CustomUsersTableTrait.php | 50 + src/Controller/Traits/LoginTrait.php | 133 ++ .../Traits/PasswordManagementTrait.php | 113 ++ src/Controller/Traits/ProfileTrait.php | 52 + src/Controller/Traits/RegisterTrait.php | 106 ++ src/Controller/Traits/SimpleCrudTrait.php | 131 ++ src/Controller/Traits/SocialTrait.php | 82 ++ src/Controller/Traits/UserValidationTrait.php | 104 ++ src/Controller/UsersController.php | 34 + .../AccountAlreadyActiveException.php | 18 + src/Exception/AccountNotActiveException.php | 19 + src/Exception/BadConfigurationException.php | 18 + src/Exception/MissingEmailException.php | 18 + src/Exception/TokenExpiredException.php | 18 + src/Exception/UserAlreadyActiveException.php | 18 + src/Exception/UserNotFoundException.php | 18 + src/Exception/WrongPasswordException.php | 10 + src/Locale/Users.pot | 534 +++++++ src/Model/Entity/SocialAccount.php | 42 + src/Model/Entity/User.php | 98 ++ src/Model/Table/SocialAccountsTable.php | 240 +++ src/Model/Table/UsersTable.php | 626 ++++++++ src/Template/Email/html/reset_password.ctp | 31 + .../Email/html/social_account_validation.ctp | 36 + src/Template/Email/html/validation.ctp | 31 + src/Template/Email/text/reset_password.ctp | 25 + .../Email/text/social_account_validation.ctp | 27 + src/Template/Email/text/validation.ctp | 25 + src/Template/Users/add.ctp | 34 + src/Template/Users/change_password.ctp | 15 + src/Template/Users/edit.ctp | 44 + src/Template/Users/index.ctp | 55 + src/Template/Users/login.ctp | 51 + src/Template/Users/profile.ctp | 72 + src/Template/Users/register.ctp | 28 + src/Template/Users/request_reset_password.ctp | 10 + .../Users/resend_token_validation.ctp | 22 + src/Template/Users/social_email.ctp | 21 + src/Template/Users/view.ctp | 108 ++ src/Traits/RandomStringTrait.php | 29 + src/View/Helper/UserHelper.php | 112 ++ tests/Fixture/SocialAccountsFixture.php | 131 ++ tests/Fixture/UsersFixture.php | 243 +++ .../Auth/RememberMeAuthenticateTest.php | 190 +++ .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 565 +++++++ .../TestCase/Auth/SuperuserAuthorizeTest.php | 93 ++ .../Component/RememberMeComponentTest.php | 196 +++ .../Component/UsersAuthComponentTest.php | 126 ++ .../Traits/CustomUsersTableTraitTest.php | 42 + .../Controller/Traits/LoginTraitTest.php | 126 ++ .../Traits/PasswordManagementTraitTest.php | 47 + .../Controller/Traits/ProfileTraitTest.php | 37 + .../Controller/Traits/RegisterTraitTest.php | 47 + .../Controller/Traits/SocialTraitTest.php | 128 ++ .../Traits/UserValidationTraitTest.php | 71 + tests/TestCase/Model/Entity/UserTest.php | 104 ++ .../Model/Table/SocialAccountsTableTest.php | 198 +++ tests/TestCase/Model/Table/UsersTableTest.php | 467 ++++++ .../TestCase/Traits/RandomStringTraitTest.php | 43 + tests/TestCase/View/Helper/UserHelperTest.php | 195 +++ tests/bootstrap.php | 30 + vendor/autoload.php | 7 + vendor/composer/ClassLoader.php | 413 ++++++ vendor/composer/autoload_classmap.php | 9 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 13 + vendor/composer/autoload_real.php | 50 + webroot/empty | 0 webroot/img/avatar_placeholder.png | Bin 0 -> 4015 bytes 98 files changed, 10270 insertions(+), 1 deletion(-) create mode 100644 Docs/Documentation/Configuration.md create mode 100644 Docs/Documentation/Events.md create mode 100644 Docs/Documentation/Extending-the-Plugin.md create mode 100644 Docs/Documentation/Installation.md create mode 100644 Docs/Documentation/Overview.md create mode 100644 Docs/Documentation/SimpleRbacAuthorize.md create mode 100644 Docs/Documentation/SocialAuthenticate.md create mode 100644 Docs/Documentation/SuperuserAuthorize.md create mode 100644 Docs/Home.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/Migrations/20150513201111_initial.php create mode 100644 config/bootstrap.php create mode 100644 config/permissions.php create mode 100644 config/routes.php create mode 100644 config/users.php create mode 100644 phpunit.xml.dist create mode 100644 src/Auth/Factory/OpauthFactory.php create mode 100644 src/Auth/RememberMeAuthenticate.php create mode 100644 src/Auth/SimpleRbacAuthorize.php create mode 100755 src/Auth/SocialAuthenticate.php create mode 100644 src/Auth/SuperuserAuthorize.php create mode 100644 src/Controller/AppController.php create mode 100644 src/Controller/Component/RememberMeComponent.php create mode 100644 src/Controller/Component/UsersAuthComponent.php create mode 100644 src/Controller/SocialAccountsController.php create mode 100644 src/Controller/Traits/CustomUsersTableTrait.php create mode 100644 src/Controller/Traits/LoginTrait.php create mode 100644 src/Controller/Traits/PasswordManagementTrait.php create mode 100644 src/Controller/Traits/ProfileTrait.php create mode 100644 src/Controller/Traits/RegisterTrait.php create mode 100644 src/Controller/Traits/SimpleCrudTrait.php create mode 100644 src/Controller/Traits/SocialTrait.php create mode 100644 src/Controller/Traits/UserValidationTrait.php create mode 100644 src/Controller/UsersController.php create mode 100644 src/Exception/AccountAlreadyActiveException.php create mode 100644 src/Exception/AccountNotActiveException.php create mode 100644 src/Exception/BadConfigurationException.php create mode 100644 src/Exception/MissingEmailException.php create mode 100644 src/Exception/TokenExpiredException.php create mode 100644 src/Exception/UserAlreadyActiveException.php create mode 100644 src/Exception/UserNotFoundException.php create mode 100644 src/Exception/WrongPasswordException.php create mode 100644 src/Locale/Users.pot create mode 100644 src/Model/Entity/SocialAccount.php create mode 100644 src/Model/Entity/User.php create mode 100644 src/Model/Table/SocialAccountsTable.php create mode 100644 src/Model/Table/UsersTable.php create mode 100644 src/Template/Email/html/reset_password.ctp create mode 100644 src/Template/Email/html/social_account_validation.ctp create mode 100644 src/Template/Email/html/validation.ctp create mode 100644 src/Template/Email/text/reset_password.ctp create mode 100644 src/Template/Email/text/social_account_validation.ctp create mode 100644 src/Template/Email/text/validation.ctp create mode 100644 src/Template/Users/add.ctp create mode 100644 src/Template/Users/change_password.ctp create mode 100644 src/Template/Users/edit.ctp create mode 100644 src/Template/Users/index.ctp create mode 100644 src/Template/Users/login.ctp create mode 100644 src/Template/Users/profile.ctp create mode 100644 src/Template/Users/register.ctp create mode 100644 src/Template/Users/request_reset_password.ctp create mode 100644 src/Template/Users/resend_token_validation.ctp create mode 100644 src/Template/Users/social_email.ctp create mode 100644 src/Template/Users/view.ctp create mode 100644 src/Traits/RandomStringTrait.php create mode 100644 src/View/Helper/UserHelper.php create mode 100644 tests/Fixture/SocialAccountsFixture.php create mode 100644 tests/Fixture/UsersFixture.php create mode 100644 tests/TestCase/Auth/RememberMeAuthenticateTest.php create mode 100644 tests/TestCase/Auth/SimpleRbacAuthorizeTest.php create mode 100644 tests/TestCase/Auth/SuperuserAuthorizeTest.php create mode 100644 tests/TestCase/Controller/Component/RememberMeComponentTest.php create mode 100644 tests/TestCase/Controller/Component/UsersAuthComponentTest.php create mode 100644 tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/LoginTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/ProfileTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/RegisterTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/SocialTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/UserValidationTraitTest.php create mode 100644 tests/TestCase/Model/Entity/UserTest.php create mode 100644 tests/TestCase/Model/Table/SocialAccountsTableTest.php create mode 100644 tests/TestCase/Model/Table/UsersTableTest.php create mode 100644 tests/TestCase/Traits/RandomStringTraitTest.php create mode 100644 tests/TestCase/View/Helper/UserHelperTest.php create mode 100644 tests/bootstrap.php create mode 100644 vendor/autoload.php create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 webroot/empty create mode 100644 webroot/img/avatar_placeholder.png diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 408e81198..68e6881de 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing ============ -This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugins). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/plugins) for detailed instructions. \ No newline at end of file +This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/contribution-guidelines) for detailed instructions. \ No newline at end of file diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md new file mode 100644 index 000000000..70b2d96f7 --- /dev/null +++ b/Docs/Documentation/Configuration.md @@ -0,0 +1,149 @@ +Configuration +============= + +Overriding the default configuration +------------------------- + +For easier configuration, you can specify an array of config files to override the default plugin keys this way: + +config/bootstrap.php +``` +Configure::write('Users.config', ['users']); +Plugin::load('Users', ['routes' => true, 'bootstrap' => true]); +``` + +Then in your config/users.php +``` +return [ + 'Opauth.Strategy.Facebook.app_id' => 'YOUR APP ID', + 'Opauth.Strategy.Facebook.app_secret' => 'YOUR APP SECRET', + //etc +]; +``` + +Configuration for social login +--------------------- + +Create the facebook/twitter applications you want to use and setup the configuration like this: + +config/bootstrap.php +``` +Configure::write('Opauth.Strategy.Facebook.app_id', 'YOUR APP ID'); +Configure::write('Opauth.Strategy.Facebook.app_secret', 'YOUR APP SECRET'); + +Configure::write('Opauth.Strategy.Twitter.key', 'YOUR APP KEY'); +Configure::write('Opauth.Strategy.Twitter.secret', 'YOUR APP SECRET'); +``` + +Or use the config override option when loading the plugin (see above) + +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 Opauth component for your application. + +If you prefer to setup AuthComponent by yourself, you'll need to load AuthComponent before UsersAuthComponent +and set +``` +Configure::write('Users.auth', false); +``` + + + + +Interesting UsersAuthComponent options and defaults + +NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/users/config/users.php` for the complete list + +``` + 'Users' => [ + //Table used to manage users + 'table' => 'Users.Users', + //configure Auth component + 'auth' => true, + 'Email' => [ + //determines if the user should include email + 'required' => true, + //determines if registration workflow includes email validation + 'validate' => true, + ], + 'Registration' => [ + //determines if the register is enabled + 'active' => true, + ], + 'Tos' => [ + //determines if the user should include tos accepted + 'required' => true, + ], + 'Social' => [ + //enable social login + 'login' => true, + ], + //Avatar placeholder + 'Avatar' => ['placeholder' => 'Users.avatar_placeholder.png'], + 'RememberMe' => [ + //configure Remember Me component + 'active' => true, + ], + ], +//default configuration used to auto-load the Auth Component, override to change the way Auth works + 'Auth' => [ + 'authenticate' => [ + 'all' => [ + 'scope' => ['active' => 1] + ], + 'Users.RememberMe', + 'Form', + ], + 'authorize' => [ + 'Users.Superuser', + 'Users.SimpleRbac', + ], + ], +]; + +``` + +Default Authenticate and Authorize Objects used +------------------------ + +Using the UsersAuthComponent default initialization, the component will load the following objects into AuthComponent: +* Authenticate + * 'Form' + * 'Social' check [SocialAuthenticate](SocialAuthenticate.md) for configuration options + * 'RememberMe' check [SocialAuthenticate](RememberMeAuthenticate.md) for configuration options +* Authorize + * 'Users.Superuser' check [SuperuserAuthorize](SuperuserAuthorize.md) for configuration options + * 'Users.SimpleRbac' check [SimpleRbacAuthorize](SimpleRbacAuthorize.md) for configuration options + +Email Templates +--------------- + +To modify the templates as needed copy them to your application + +``` +cp -r vendor/cakedc/users/src/Template/Email/* src/Template/Plugin/Users/Email/ +``` + +Then customize the email templates as you need under the src/Template/Plugin/Users/Email/ directory + +Plugin Templates +--------------- + +Similar to Email Templates customization, follow the CakePHP conventions to put your new templates under +src/Template/Plugin/Users/[Controller]/[view].ctp + +Check http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application + +Flash Messages +--------------- + +To modify the flash messages, use the standard PO file provided by the plugin and customize the messages +Check http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#setting-up-translations +for more details about how the PO files should be managed in your application. + +We've included an updated POT file with all the `Users` domain keys for your customization. \ No newline at end of file diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md new file mode 100644 index 000000000..ea16d4c34 --- /dev/null +++ b/Docs/Documentation/Events.md @@ -0,0 +1,53 @@ +Events +====== + +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'; + +The events allow you to inject data into the plugin on the before* plugins and use the data for your +own business login in the after* events, for example + +``` + /** + * Forced login using a beforeLogin event + */ + public function eventLogin() + { + $this->eventManager()->on(UsersAuthComponent::EVENT_BEFORE_LOGIN, function () { + //the callback function should return the user data array to force login + return [ + 'id' => 1337, + 'username' => 'forceLogin', + 'email' => 'event@example.com', + 'active' => true, + ]; + }); + $this->login(); + $this->render('login'); + } + + /** + * beforeRegister event + */ + public function eventRegister() + { + $this->eventManager()->on(UsersAuthComponent::EVENT_BEFORE_REGISTER, function ($event) { + //the callback function should return the user data array to force register + return $event->data['usersTable']->newEntity([ + 'username' => 'forceEventRegister', + 'email' => 'eventregister@example.com', + 'password' => 'password', + 'active' => true, + 'tos' => true, + ]); + }); + $this->register(); + $this->render('register'); + } +``` \ No newline at end of file diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md new file mode 100644 index 000000000..fc2610c4c --- /dev/null +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -0,0 +1,147 @@ +Extending the Plugin +==================== + +Extending the Model (Table/Entity) +------------------- + +Create a new Table and Entity in your app, matching the table you want to use for storing the +users data. Check the initial users migration to know the default columns expected in the table. +If your column names doesn't match the columns in your current table, you could use the Entity to +match the colums using accessors & mutators as described here http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators + +Example: we are going to use a custom table in our application ```my_users``` +* Create a new Table under src/Model/Table/MyUsersTable.php + +```php +namespace App\Model\Table; + +use Users\Model\Table\UsersTable; + +/** + * Users Model + */ +class MyUsersTable extends UsersTable +{ +} + +* Create a new Entity under src/Model/Entity/MyUser.php + +```php +namespace App\Model\Entity; + +use Users\Model\Entity\User; + +class MyUser extends User +{ +} +``` + +* Pass the new table configuration to Users Plugin Configuration + +config/bootstrap.php +``` +Configure::write('Users.config', ['users']); +Plugin::load('Users', ['routes' => true, 'bootstrap' => true]); +``` + +Then in your config/users.php +``` +return [ + 'Users.table' => 'MyUsers', +]; +``` + +Now the Users Plugin will use MyUsers Table and Entity to register and login user in. Use the +Entity to match your own columns in case they don't match the default column names: + +```sql +CREATE TABLE IF NOT EXISTS `users` ( + `id` char(36) NOT NULL, + `username` varchar(255) NOT NULL, + `email` varchar(255) DEFAULT NULL, + `password` varchar(255) NOT NULL, + `first_name` varchar(50) DEFAULT NULL, + `last_name` varchar(50) DEFAULT NULL, + `token` varchar(255) DEFAULT NULL, + `token_expires` datetime DEFAULT NULL, + `api_token` varchar(255) DEFAULT NULL, + `activation_date` datetime DEFAULT NULL, + `tos_date` datetime DEFAULT NULL, + `active` int(1) NOT NULL DEFAULT '0', + `is_superuser` int(1) NOT NULL DEFAULT '0', + `role` varchar(255) DEFAULT 'user', + `created` datetime NOT NULL, + `modified` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +``` + +Extending the Controller +------------------- + +You want to use one of your controllers to handle all the users features in your app, and keep the +login/register/etc actions from Users Plugin, + +```php +getUsersTable()->find() + ->where(['id' => $userId]) + ->hydrate(false) + ->first(); + $this->Auth->setUser($user); + return $this->redirect('/'); + } +} + +Updating the Templates +------------------- + +Use the standard CakePHP conventions to override Plugin views using your application views +http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application + + + diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md new file mode 100644 index 000000000..c6fffb0d1 --- /dev/null +++ b/Docs/Documentation/Installation.md @@ -0,0 +1,74 @@ +Installation +============ + +Composer +------ + +``` +composer require cakedc/users:~3.0 +``` + +if you want to use social login features... + +``` +composer require opauth/opauth:1.0.x-dev +composer require opauth/facebook:1.0.x-dev +composer require opauth/twitter:1.0.x-dev +``` + +Creating Required Tables +------------------------ +If you want to use the Users tables to store your users and social accounts: + +``` +bin/cake migrations migrate -p Users +``` + +Note you don't need to use the provided tables, you could customize the table names, fields etc in your +application and then use the plugin configuration to use your own tables instead. Please refer to the [Extending the Plugin](Extending-the-Plugin.md) +section to check all the customization options + +Load the Plugin +----------- + +Ensure the Users Plugin is loaded in your config/bootstrap.php file + +``` +Plugin::load('Users', ['routes' => true, 'bootstrap' => true]); +``` + +Customization +---------- + +config/bootstrap.php +``` +Configure::write('Users.config', ['users']); +Plugin::load('Users', ['routes' => true, 'bootstrap' => true]); +``` + +Then in your config/users.php +``` +return [ + 'Opauth.Strategy.Facebook.app_id' => 'YOUR APP ID', + 'Opauth.Strategy.Facebook.app_secret' => 'YOUR APP SECRET', + //etc +]; +``` + +For more details, check the Configuration doc page + +Load the UsersAuth Component +--------------------- + +Load the Component in your src/Controller/AppController.php, and use the passed Component configuration to customize the Users Plugin: + +``` + public function initialize() + { + parent::initialize(); + $this->loadComponent('Flash'); + $this->loadComponent('Users.UsersAuth'); + } +``` + + diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md new file mode 100644 index 000000000..5974a3666 --- /dev/null +++ b/Docs/Documentation/Overview.md @@ -0,0 +1,17 @@ +Overview +======== + +You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. + +The plugin itself is already capable of: + +* User registration +* Account verification by a token sent via email +* User login (email / password) +* Social login (Twitter, Facebook) +* Password reset based on requesting a token by email and entering a new password +* User management (add / edit / delete) +* Simple roles management +* Simple Rbac and SuperUser Authorize +* RememberMe using cookie feature + diff --git a/Docs/Documentation/SimpleRbacAuthorize.md b/Docs/Documentation/SimpleRbacAuthorize.md new file mode 100644 index 000000000..e236f9a6f --- /dev/null +++ b/Docs/Documentation/SimpleRbacAuthorize.md @@ -0,0 +1,87 @@ +@todo: callbacks +SimpleRbacAuthorize +============= + +Setup +--------------- + +SimpleRbacAuthorize is configured by default, but you can customize the way it works easily + +Example, in you AppController, you can configure the way the SimpleRbac works by setting the options: + +```php +$config['Auth']['authorize']['Users.SimpleRbac'] = [ + //autoload permissions.php + 'autoload_config' => 'permissions', + //role field in the Users table + 'role_field' => 'role', + //default role, used in new users registered and also as role matcher when no role is available + 'default_role' => 'user', + /* + * This is a quick roles-permissions implementation + * Rules are evaluated top-down, first matching rule will apply + * Each line define + * [ + * 'role' => 'admin', + * 'plugin', (optional, default = null) + * 'controller', + * 'action', + * 'allowed' (optional, default = true) + * ] + * You could use '*' to match anything + * Suggestion: put your rules into a specific config file + */ + 'permissions' => [], // you could set an array of permissions or load them using a file 'autoload_config' + ]; +``` + +This is the default configuration, based on it the Authorize object will first check your ```config/permissions.php``` +file and load the permissions using the configuration key ```Users.SimpleRbac.permissions```, there is an +example file you can copy into your ```config/permissions.php``` under the Plugin's config directory. + +If you don't want to use a file for configuring the permissions, you just need to tweak the configuration and set +```'autoload_config' => false,``` then define all your rules in AppController (not a good practice as the rules +tend to grow over time). + +The Users Plugin will use the field ```role_field``` in the Users Table to match the role of the user and +check if there is a rule allowing him to access the url. + +The ```default_role``` will be used to set the role of the registered users by default. + +Permission rules syntax +----------------- + +* Rules are evaluated top-down, first matching rule will apply +* Each rule is defined: +```php +[ + 'role' => 'REQUIRED_NAME_OF_THE_ROLE_OR_*', + 'plugin' => 'OPTIONAL_NAME_OF_THE_PLUGIN_OR_*_DEFAULT_NULL', + 'controller' => 'REQUIRED_NAME_OF_THE_CONTROLLER_OR_*' + 'action' => 'REQUIRED_NAME_OF_ACTION_OR_*', + 'allowed' => 'OPTIONAL_BOOLEAN_DEFAULT_TRUE_OR_CALLABLE' +] +``` +* If no rule allowed = true is matched for a given user role and url, default return value will be false +* Note for Superadmin access (permission to access ALL THE THINGS in your app) there is a specific Authorize Object provided + +Permission Callbacks +----------------- +You could use a callback in your 'allowed' to process complex authentication, like + - ownership + - permissions stored in your database + - permission based on an external service API call + +Example *ownership* callback, to allow users to edit their own Posts: + +```php + 'allowed' => function (array $user, $role, Request $request) { + $postId = Hash::get($request->params, 'pass.0'); + $post = TableRegistry::get('Posts')->get($postId); + $userId = Hash::get($user, 'id'); + if (!empty($post->user_id) && !empty($userId)) { + return $post->user_id === $userId; + } + return false; + } +``` diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md new file mode 100644 index 000000000..2076b637b --- /dev/null +++ b/Docs/Documentation/SocialAuthenticate.md @@ -0,0 +1,82 @@ +SocialAuthenticate +============= + +Setup +--------------------- + +Create the Facebook/Twitter applications you want to use and setup the configuration like this: + +Config/bootstrap.php +``` +Configure::write('Opauth.Strategy.Facebook.app_id', 'YOUR APP ID'); +Configure::write('Opauth.Strategy.Facebook.app_secret', 'YOUR APP SECRET'); + +Configure::write('Opauth.Strategy.Twitter.key', 'YOUR APP KEY'); +Configure::write('Opauth.Strategy.Twitter.secret', 'YOUR APP SECRET'); +``` + +You can also change the default settings for social authenticate: + +``` +Configure::write('Users', [ + 'Email' => [ + //determines if the user should include email + 'required' => true, + //determines if registration workflow includes email validation + 'validate' => true, + ], + 'Social' => [ + //enable social login + 'login' => true, + ], + 'Key' => [ + 'Session' => [ + //session key to store the social auth data + 'social' => 'Users.social', + ], + //form key to store the social auth data + 'Form' => [ + 'social' => 'social' + ], + 'Data' => [ + //data key to store email coming from social networks + 'socialEmail' => 'info.email', + ], + ], +]); +``` + +If email is required and the social network does not return the user email then the user will be required to input the email. Additionally, validation could be enabled, in that case the user will be asked to validate the email before be able to login. There are some cases where the email address already exists onto database, if so, the user will receive an email and will be asked to validate the social account in the app. It is important to take into account that the user account itself will remain active and accessible by other ways (other social network account or username/password). +``` +Configure::write('Opauth', [ + 'path' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit'], + 'callback_url' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit', 'callback'], + 'complete_url' => ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'login'], + 'Strategy' => [ + 'Facebook' => [ + 'scope' => ['public_profile', 'user_friends', 'email'] + ], + 'Twitter' => [ + 'curl_cainfo' => false, + 'curl_capath' => false + ] + ] +]); +``` + +In most situations you would not need to change any Opauth setting besides applications details. + +User Helper +--------------------- + +You can use the helper included with the plugin to create Facebook/Twitter buttons: + +In templates +``` +$this->User->facebookLogin(); + +$this->User->twitterLogin(); +``` + +We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. + diff --git a/Docs/Documentation/SuperuserAuthorize.md b/Docs/Documentation/SuperuserAuthorize.md new file mode 100644 index 000000000..7db2cb042 --- /dev/null +++ b/Docs/Documentation/SuperuserAuthorize.md @@ -0,0 +1,18 @@ +SuperuserAuthorize +============= + +Setup +--------------- + +SuperuserAuthorize is here to provide full permissions to specific "SUPER" users in your app. + +```php +$config['Auth']['authorize']['Users.Superuser'] = [ + //superuser field in the Users table + 'superuser_field' => 'is_superuser', + ]; +``` + +If the current user 'superuser_field' is true, he'll get full permissions in your app. + +Note if you don't have superusers, you can disable the SuperuserAuthorize in AuthComponent initialization \ No newline at end of file diff --git a/Docs/Home.md b/Docs/Home.md new file mode 100644 index 000000000..fb4c810d3 --- /dev/null +++ b/Docs/Home.md @@ -0,0 +1,30 @@ +Home +==== + +IMPORANT: Current status is **ALPHA**. We are working now on improving the unit test coverage and docs +Plugin is usable now if you want to download and take a look. PRs and Issues welcome! + +The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. + +The plugin is thought as a base to extend your app specific users controller and model from. + +That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. +Read the instructions carefully. + +Requirements +------------ + +* CakePHP 3.0+ +* PHP 5.4.16+ + +Documentation +------------- + +* [Overview](Documentation/Overview.md) +* [Installation](Documentation/Installation.md) +* [Configuration](Documentation/Configuration.md) +* [SimpleRbacAuthorize](Documentation/SimpleRbacAuthorize.md) +* [SuperuserAuthorize](Documentation/SuperuserAuthorize.md) +* [SocialAuthenticate](Documentation/SocialAuthenticate.md) +* [Events](Documentation/Events.md) +* [Extending the Plugin](Documentation/Extending-the-Plugin.md) diff --git a/LICENSE.txt b/LICENSE.txt index e6bdcdf69..6ee7e8fc0 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -4,6 +4,7 @@ Copyright 2009-2014 Cake Development Corporation 1785 E. Sahara Avenue, Suite 490-423 Las Vegas, Nevada 89104 +Phone: +1 702 425 5085 http://cakedc.com Permission is hereby granted, free of charge, to any person obtaining a diff --git a/README.md b/README.md new file mode 100644 index 000000000..9ee43700e --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +CakeDC Users Plugin +=================== + +[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=3.x)](http://travis-ci.org/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) + +The **Users** plugin is back! + +It covers the following features: +* User registration +* Login/logout +* Social login (Facebook, Twitter) +* Simple RBAC +* Remember me (Cookie) +* Manage user's profile +* Admin management + +The plugin is here to provide users related features following 2 approaches: +* Quick drop-in working solution for users login/registration. Get users working in 5 minutes. +* Extensible solution for a bigger/custom application. You'll be able to extend: + * UsersAuth Component + * Use your own UsersTable + * Use your own Controller + +On the previous versions of the plugin, extensibility was an issue, and one of the main +objectives of the 3.0 rewrite is to guarantee all the pieces could be extended/reused as +easily. + +Another decision made was limiting the plugin dependencies on other packages as much as possible. + +Requirements +------------ + +* CakePHP 3.0+ +* PHP 5.4.16+ + +Documentation +------------- + +For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory of this repository. + +Roadmap +------ + +* 3.0.0 Migration to CakePHP 3.x +* 3.0.1 General improvements + * Unit test coverage improvements + * Refactor UsersTable to Behavior + * Add google authentication + * Add captcha + * Link social accounts in profile + +Support +------- + +For bugs and feature requests, please use the [issues](https://github.com/CakeDC/users/issues) section of this repository. + +Commercial support is also available, [contact us](http://cakedc.com/contact) for more information. + +Contributing +------------ + +This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/contribution-guidelines) for detailed instructions. + +License +------- + +Copyright 2015 Cake Development Corporation (CakeDC). All rights reserved. + +Licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) License. Redistributions of the source code included in this repository must retain the copyright notice found in each file. diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..4cb651e03 --- /dev/null +++ b/composer.json @@ -0,0 +1,29 @@ +{ + "name": "cakedc/users", + "description": "Users plugin for CakePHP 3.x", + "type": "cakephp-plugin", + "require": { + "php": ">=5.4.16", + "cakephp/cakephp": "~3.0" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "opauth/opauth": "Used for Social Login, if you add Opauth, remember adding at least one strategy too", + "opauth/facebook": "Provide Social Login: Facebook Strategy, requires Opauth", + "opauth/twitter": "Provide Social Login: Twitter Strategy, requires Opauth" + }, + "autoload": { + "psr-4": { + "Users\\": "src", + "Users\\Test\\Fixture\\": "tests\\Fixture" + } + }, + "autoload-dev": { + "psr-4": { + "Users\\Test\\": "tests", + "Cake\\Test\\": "./vendor/cakephp/cakephp/tests" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 000000000..1f84e528b --- /dev/null +++ b/composer.lock @@ -0,0 +1,1297 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "272d2fc14a03fb78ed921ed2e143784b", + "packages": [ + { + "name": "aura/installer-default", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/auraphp/installer-default.git", + "reference": "52f8de3670cc1ef45a916f40f732937436d028c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/auraphp/installer-default/zipball/52f8de3670cc1ef45a916f40f732937436d028c8", + "reference": "52f8de3670cc1ef45a916f40f732937436d028c8", + "shasum": "" + }, + "type": "composer-installer", + "extra": { + "class": "Aura\\Composer\\DefaultInstaller" + }, + "autoload": { + "psr-0": { + "Aura\\Composer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Paul M. Jones", + "email": "pmjones88@gmail.com", + "homepage": "http://paul-m-jones.com" + } + ], + "description": "Installs Aura packages using the Composer defaults.", + "keywords": [ + "aura", + "installer" + ], + "time": "2012-11-26 21:35:57" + }, + { + "name": "aura/intl", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/auraphp/Aura.Intl.git", + "reference": "c5fe620167550ad6fa77dd3570fba2efc77a2a21" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/auraphp/Aura.Intl/zipball/c5fe620167550ad6fa77dd3570fba2efc77a2a21", + "reference": "c5fe620167550ad6fa77dd3570fba2efc77a2a21", + "shasum": "" + }, + "require": { + "aura/installer-default": "1.0.*", + "php": ">=5.4.0" + }, + "type": "aura-package", + "extra": { + "aura": { + "type": "library", + "config": { + "common": "Aura\\Intl\\_Config\\Common" + } + }, + "branch-alias": { + "dev-develop": "1.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Aura\\Intl": "src/" + }, + "psr-4": { + "Aura\\Intl\\_Config\\": "config/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Paul M. Jones", + "email": "pmjones88@gmail.com", + "homepage": "http://paul-m-jones.com" + }, + { + "name": "Aura.Intl Contributors", + "homepage": "https://github.com/auraphp/Aura.Intl/contributors" + }, + { + "name": "Pascal Borreli", + "email": "pascal@borreli.com" + }, + { + "name": "Mapthegod", + "email": "mapthegod@gmail.com" + }, + { + "name": "Jose Lorenzo Rodriguez", + "email": "jose.zap@gmail.com" + } + ], + "description": "The Aura.Intl package provides internationalization (I18N) tools, specifically\npackage-oriented per-locale message translation.", + "homepage": "http://auraphp.com/Aura.Intl", + "keywords": [ + "g11n", + "globalization", + "i18n", + "internationalization", + "intl", + "l10n", + "localization" + ], + "time": "2014-08-24 00:00:00" + }, + { + "name": "cakephp/cakephp", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/cakephp/cakephp.git", + "reference": "22976db9856c1d6dea8b94136030cf8804609035" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/cakephp/zipball/22976db9856c1d6dea8b94136030cf8804609035", + "reference": "22976db9856c1d6dea8b94136030cf8804609035", + "shasum": "" + }, + "require": { + "aura/intl": "1.1.*", + "ext-intl": "*", + "ext-mbstring": "*", + "ircmaxell/password-compat": "1.0.*", + "nesbot/carbon": "1.13.*", + "php": ">=5.4.16", + "psr/log": "1.0" + }, + "replace": { + "cakephp/cache": "self.version", + "cakephp/collection": "self.version", + "cakephp/core": "self.version", + "cakephp/database": "self.version", + "cakephp/datasource": "self.version", + "cakephp/event": "self.version", + "cakephp/i18n": "self.version", + "cakephp/log": "self.version", + "cakephp/orm": "self.version", + "cakephp/utility": "self.version", + "cakephp/validation": "self.version" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "dev-master", + "phpunit/phpunit": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cake\\": "src" + }, + "files": [ + "src/Core/functions.php", + "src/Collection/functions.php", + "src/I18n/functions.php", + "src/Utility/bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/cakephp/graphs/contributors" + } + ], + "description": "The CakePHP framework", + "homepage": "http://cakephp.org", + "keywords": [ + "framework" + ], + "time": "2015-05-08 01:45:39" + }, + { + "name": "ircmaxell/password-compat", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ], + "time": "2014-11-20 16:49:30" + }, + { + "name": "nesbot/carbon", + "version": "1.13.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "5cb6e71055f7b0b57956b73d324cc4de31278f42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/5cb6e71055f7b0b57956b73d324cc4de31278f42", + "reference": "5cb6e71055f7b0b57956b73d324cc4de31278f42", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Carbon": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "https://github.com/briannesbitt/Carbon", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2014-09-26 02:52:02" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "2.0.*@ALPHA" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Instantiator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2014-10-13 12:58:55" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, + { + "name": "phpspec/prophecy", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-04-27 22:15:08" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.0.16", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c", + "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "~1.0", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-04-11 04:35:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb", + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-04-02 05:19:05" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "Text/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2014-01-30 17:20:04" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2013-08-02 07:42:54" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "eab81d02569310739373308137284e0158424330" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", + "reference": "eab81d02569310739373308137284e0158424330", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-04-08 04:46:07" + }, + { + "name": "phpunit/phpunit", + "version": "4.6.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3afe303d873a4d64c62ef84de491b97b006fbdac", + "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "~1.3,>=1.3.1", + "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "~1.0", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.2", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.6.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2015-04-29 15:18:52" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", + "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "~1.0,>=1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-04-02 05:36:41" + }, + { + "name": "sebastian/comparator", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-01-29 16:28:08" + }, + { + "name": "sebastian/diff", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-02-22 15:13:53" + }, + { + "name": "sebastian/environment", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-01-01 10:01:08" + }, + { + "name": "sebastian/exporter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "84839970d05254c73cde183a721c7af13aede943" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", + "reference": "84839970d05254c73cde183a721c7af13aede943", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-01-27 07:23:06" + }, + { + "name": "sebastian/global-state", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2014-10-06 09:23:50" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-01-24 09:48:32" + }, + { + "name": "sebastian/version", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-02-24 06:35:25" + }, + { + "name": "symfony/yaml", + "version": "v2.6.7", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.4.16" + }, + "platform-dev": [] +} diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php new file mode 100644 index 000000000..b55ab65cf --- /dev/null +++ b/config/Migrations/20150513201111_initial.php @@ -0,0 +1,186 @@ +table('social_accounts', ['id' => false, 'primary_key' => ['id']]); + $table + ->addColumn('id', 'char', [ + 'default' => null, + 'limit' => 36, + 'null' => false, + ]) + ->addColumn('user_id', 'string', [ + 'default' => null, + 'limit' => 36, + 'null' => false, + ]) + ->addColumn('provider', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('username', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('reference', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('avatar', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('description', 'text', [ + 'default' => null, + 'limit' => null, + 'null' => true, + ]) + ->addColumn('link', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('token', 'string', [ + 'default' => null, + 'limit' => 500, + 'null' => false, + ]) + ->addColumn('token_secret', 'string', [ + 'default' => null, + 'limit' => 500, + 'null' => true, + ]) + ->addColumn('token_expires', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => true, + ]) + ->addColumn('active', 'boolean', [ + 'default' => 1, + 'limit' => 1, + 'null' => false, + ]) + ->addColumn('data', 'text', [ + 'default' => null, + 'limit' => null, + 'null' => false, + ]) + ->addColumn('created', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => false, + ]) + ->addColumn('modified', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => false, + ]) + ->create(); + $table = $this->table('users', ['id' => false, 'primary_key' => ['id']]); + $table + ->addColumn('id', 'char', [ + 'default' => null, + 'limit' => 36, + 'null' => false, + ]) + ->addColumn('username', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('email', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('password', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('first_name', 'string', [ + 'default' => null, + 'limit' => 50, + 'null' => true, + ]) + ->addColumn('last_name', 'string', [ + 'default' => null, + 'limit' => 50, + 'null' => true, + ]) + ->addColumn('token', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('token_expires', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => true, + ]) + ->addColumn('api_token', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('activation_date', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => true, + ]) + ->addColumn('tos_date', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => true, + ]) + ->addColumn('active', 'boolean', [ + 'default' => 0, + 'limit' => 1, + 'null' => false, + ]) + ->addColumn('is_superuser', 'integer', [ + 'default' => 0, + 'limit' => 1, + 'null' => false, + ]) + ->addColumn('role', 'string', [ + 'default' => 'user', + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('created', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => false, + ]) + ->addColumn('modified', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => false, + ]) + ->create(); + } + + public function down() + { + $this->dropTable('social_accounts'); + $this->dropTable('users'); + } +} diff --git a/config/bootstrap.php b/config/bootstrap.php new file mode 100644 index 000000000..096267b8e --- /dev/null +++ b/config/bootstrap.php @@ -0,0 +1,21 @@ +each(function ($file) { + Configure::load($file); +}); + +if (Configure::check('Users.auth')) { + Configure::write('Auth.authenticate.all.userModel', Configure::read('Users.table')); +} diff --git a/config/permissions.php b/config/permissions.php new file mode 100644 index 000000000..2c0be29c2 --- /dev/null +++ b/config/permissions.php @@ -0,0 +1,78 @@ + + * [ + * 'plugin', (default = null) + * 'controller', + * 'action', + * 'allowed' (default = true) + * ] + * You could use '*' to match anything + * 'allowed' will be considered true if not defined. It allows a callable to manage complex + * permissions, like this + * 'allowed' => function (array $user, $role, Request $request) {} + * + * Example, using allowed callable to define permissions only for the owner of the Posts to edit/delete + * + * (remember to add the 'uses' at the top of the permissions.php file for Hash, TableRegistry and Request + [ + 'role' => ['user'], + 'controller' => ['Posts'], + 'action' => ['edit', 'delete'], + 'allowed' => function(array $user, $role, Request $request) { + $postId = Hash::get($request->params, 'pass.0'); + $post = TableRegistry::get('Posts')->get($postId); + $userId = Hash::get($user, 'id'); + if (!empty($post->user_id) && !empty($userId)) { + return $post->user_id === $userId; + } + return false; + } + ], + */ + +return [ + 'Users.SimpleRbac.permissions' => [ + [ + 'role' => '*', + 'plugin' => 'Users', + 'controller' => '*', + 'action' => '*', + ], + [ + 'role' => 'user', + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => ['register', 'edit', 'view'], + ], + [ + 'role' => 'user', + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => '*', + 'allowed' => false, + ], + [ + 'role' => ['user'], + 'controller' => ['Pages'], + 'action' => ['other', 'display'], + 'allowed' => true, + ], + ]]; diff --git a/config/routes.php b/config/routes.php new file mode 100644 index 000000000..1c5fbf3c8 --- /dev/null +++ b/config/routes.php @@ -0,0 +1,33 @@ +fallbacks('DashedRoute'); +}); + +Router::scope('/auth', function ($routes) { + $routes->connect( + '/*', + Configure::read('Opauth.path') + ); +}); +Router::connect('/accounts/validate/*', [ + 'admin' => false, + 'plugin' => 'Users', + 'controller' => 'SocialAccounts', + 'action' => 'validate' +]); +Router::connect('/profile/*', ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); +Router::connect('/login', ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); +Router::connect('/logout', ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout']); diff --git a/config/users.php b/config/users.php new file mode 100644 index 000000000..cc73fdc6d --- /dev/null +++ b/config/users.php @@ -0,0 +1,114 @@ + [ + //Table used to manage users + 'table' => 'Users.Users', + //configure Auth component + 'auth' => true, + //token expiration, 1 hour + 'Token' => ['expiration' => 3600], + 'Email' => [ + //determines if the user should include email + 'required' => true, + //determines if registration workflow includes email validation + 'validate' => true, + ], + 'Registration' => [ + //determines if the register is enabled + 'active' => true, + ], + 'Tos' => [ + //determines if the user should include tos accepted + 'required' => true, + ], + 'Social' => [ + //enable social login + 'login' => true, + ], + 'Profile' => [ + //Allow view other users profiles + 'viewOthers' => true, + ], + 'Key' => [ + 'Session' => [ + //session key to store the social auth data + 'social' => 'Users.social', + //userId key used in reset password workflow + 'resetPasswordUserId' => 'Users.resetPasswordUserId', + ], + //form key to store the social auth data + 'Form' => [ + 'social' => 'social' + ], + 'Data' => [ + //data key to store the users email + 'email' => 'email', + //data key to store email coming from social networks + 'socialEmail' => 'info.email', + //data key to check if the remember me option is enabled + 'rememberMe' => 'remember_me', + ], + ], + //Avatar placeholder + 'Avatar' => ['placeholder' => 'Users.avatar_placeholder.png'], + 'RememberMe' => [ + //configure Remember Me component + 'active' => true, + 'Cookie' => [ + 'name' => 'remember_me', + 'Config' => [ + 'expires' => '1 month', + 'httpOnly' => true, + ] + ] + ], + ], +//default configuration used to auto-load the Auth Component, override to change the way Auth works + 'Auth' => [ + 'loginAction' => [ + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => 'login', + ], + 'authenticate' => [ + 'all' => [ + 'scope' => ['active' => 1] + ], + 'Users.RememberMe', + 'Form', + ], + 'authorize' => [ + 'Users.Superuser', + 'Users.SimpleRbac', + ], + ], +//default Opauth configuration, you'll need to provide the strategy keys + 'Opauth' => [ + 'path' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit'], + 'callback_param' => 'callback', + 'complete_url' => ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'login'], + 'Strategy' => [ + 'Facebook' => [ + 'scope' => ['public_profile', 'user_friends', 'email'] + ], + 'Twitter' => [ + 'curl_cainfo' => false, + 'curl_capath' => false + ] + ] + ] +]; + +return $config; diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 000000000..500c19975 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,36 @@ + + + + + + + + + + + ./tests/TestCase + + + + + ./src + + + + + + + + + + + + diff --git a/src/Auth/Factory/OpauthFactory.php b/src/Auth/Factory/OpauthFactory.php new file mode 100644 index 000000000..6fdfbcd77 --- /dev/null +++ b/src/Auth/Factory/OpauthFactory.php @@ -0,0 +1,35 @@ +_registry->Cookie->check($cookieName)) { + return false; + } + $cookie = $this->_registry->Cookie->read($cookieName); + $this->config('fields.username', 'id'); + $user = $this->_findUser($cookie['id']); + if ($user && + !empty($cookie['user_agent']) && + $request->header('User-Agent') === $cookie['user_agent']) { + return $user; + } + + return false; + } +} diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php new file mode 100644 index 000000000..cbc95d9e1 --- /dev/null +++ b/src/Auth/SimpleRbacAuthorize.php @@ -0,0 +1,239 @@ + 'permissions', + //role field in the Users table + 'role_field' => 'role', + //default role, used in new users registered and also as role matcher when no role is available + 'default_role' => 'user', + /* + * This is a quick roles-permissions implementation + * Rules are evaluated top-down, first matching rule will apply + * Each line define + * [ + * 'role' => 'admin', + * 'plugin', (optional, default = null) + * 'controller', + * 'action', + * 'allowed' (optional, default = true) + * ] + * You could use '*' to match anything + * You could use [] to match an array of options, example 'role' => ['adm1', 'adm2'] + * You could use a callback in your 'allowed' to process complex authentication, like + * - ownership + * - permissions stored in your database + * - permission based on an external service API call + * Example ownership callback, to allow users to edit their own Posts: + * + * 'allowed' => function (array $user, $role, Request $request) { + $postId = Hash::get($request->params, 'pass.0'); + $post = TableRegistry::get('Posts')->get($postId); + $userId = Hash::get($user, 'id'); + if (!empty($post->user_id) && !empty($userId)) { + return $post->user_id === $userId; + } + return false; + } + * + * Suggestion: put your rules into a specific config file + */ + 'permissions' => [], + ]; + + /** + * Default permissions to be loaded if no provided permissions + * + * @var array + */ + protected $_defaultPermissions = [ + //admin role allowed to use Users plugin actions + [ + 'role' => 'admin', + 'plugin' => '*', + 'controller' => '*', + 'action' => '*', + ], + //specific actions allowed for the user role in Users plugin + [ + 'role' => 'user', + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => ['profile', 'logout'], + ], + //all roles allowed to Pages/display + [ + 'role' => '*', + 'plugin' => null, + 'controller' => ['Pages'], + 'action' => ['display'], + ], + ]; + + /** + * Autoload permission configuration + * @param ComponentRegistry $registry component registry + * @param array $config config + */ + public function __construct(ComponentRegistry $registry, array $config = []) + { + parent::__construct($registry, $config); + $autoload = $this->config('autoload_config'); + if ($autoload) { + $loadedPermissions = $this->_loadPermissions($autoload, 'default'); + $this->config('permissions', $loadedPermissions); + } + } + + /** + * Load config and retrieve permissions + * If the configuration file does not exist, or the permissions key not present, return defaultPermissions + * To be mocked + * + * @param string $key name of the configuration file to read permissions from + * @return array permissions + */ + protected function _loadPermissions($key) + { + try { + Configure::load($key, 'default'); + $permissions = Configure::read('Users.SimpleRbac.permissions'); + } catch (Exception $ex) { + $msg = __d('Users', 'Missing configuration file: "config/{0}.php". Using default permissions', $key); + $this->log($msg, LogLevel::WARNING); + } + + if (empty($permissions)) { + return $this->_defaultPermissions; + } + + return $permissions; + } + + /** + * Match the current plugin/controller/action against loaded permissions + * Set a default role if no role is provided + * + * @param array $user user data + * @param Request $request request + * @return bool + */ + public function authorize($user, Request $request) + { + $roleField = $this->config('role_field'); + $role = $this->config('default_role'); + if (Hash::check($user, $roleField)) { + $role = Hash::get($user, $roleField); + } + + $allowed = $this->_checkRules($user, $role, $request); + return $allowed; + } + + /** + * Match against permissions, return if matched + * Permissions are processed based on the 'permissions' config values + * + * @param array $user current user array + * @param string $role effective role for the current user + * @param Request $request request + * @return bool true if there is a match in permissisons + */ + protected function _checkRules(array $user, $role, Request $request) + { + $permissions = $this->config('permissions'); + foreach ($permissions as $permission) { + if ($allowed = $this->_matchRule($permission, $user, $role, $request)) { + return $allowed; + } + } + + return false; + } + + /** + * Match the rule for current permission + * + * @param array $permission configuration + * @param array $user current user + * @param string $role effective user role + * @param Request $request request + * @return bool + */ + protected function _matchRule($permission, $user, $role, $request) + { + $plugin = $request->plugin; + $controller = $request->controller; + $action = $request->action; + if ($this->_matchOrAsterisk($permission, 'role', $role) && + $this->_matchOrAsterisk($permission, 'plugin', $plugin, true) && + $this->_matchOrAsterisk($permission, 'controller', $controller) && + $this->_matchOrAsterisk($permission, 'action', $action)) { + $allowed = Hash::get($permission, 'allowed'); + if ($allowed === null) { + //allowed will be true by default + return true; + } elseif (is_callable($allowed)) { + return (bool)call_user_func($allowed, $user, $role, $request); + } else { + return (bool)$allowed; + } + } + + return false; + } + + /** + * Check if rule matched or '*' present in rule matching anything + * + * @param string $permission permission configuration + * @param string $key key to retrieve and check in permissions configuration + * @param string $value value to check with (coming from the request) We'll check the DASHERIZED value too + * @param bool $allowEmpty true if we allow + * @return bool + */ + protected function _matchOrAsterisk($permission, $key, $value, $allowEmpty = false) + { + $possibleValues = (array)Hash::get($permission, $key); + if ($allowEmpty && empty($possibleValues) && $value === null) { + return true; + } + if (Hash::get($permission, $key) === '*' || + in_array($value, $possibleValues) || + in_array(Inflector::camelize($value, '-'), $possibleValues)) { + return true; + } + + return false; + } +} diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php new file mode 100755 index 000000000..480c5c204 --- /dev/null +++ b/src/Auth/SocialAuthenticate.php @@ -0,0 +1,75 @@ +session()->read(Configure::read('Users.Key.Session.social')); + + if (empty($data)) { + return false; + } + $socialMail = Hash::get($data->info, Configure::read('Users.Key.Data.email')); + + if (!empty($socialMail)) { + $data->email = $socialMail; + $data->validated = true; + } else { + $data->email = $request->data(Configure::read('Users.Key.Data.email')); + $data->validated = false; + } + $user = $this->_findOrCreateUser($data); + return $user; + } + + /** + * Checks the social user against the database + * + * @param array $data User data array. + * @return mixed + */ + protected function _findOrCreateUser($data) + { + $userModel = Configure::read('Users.table'); + $User = TableRegistry::get($userModel); + $options = [ + 'use_email' => Configure::read('Users.Email.required'), + 'validate_email' => Configure::read('Users.Email.validate'), + 'token_expiration' => Configure::read('Users.Token.expiration') + ]; + $user = $User->socialLogin($data, $options); + if (!empty($user->username)) { + $user = $this->_findUser($user->username); + } + return $user; + } +} diff --git a/src/Auth/SuperuserAuthorize.php b/src/Auth/SuperuserAuthorize.php new file mode 100644 index 000000000..8718aa6ba --- /dev/null +++ b/src/Auth/SuperuserAuthorize.php @@ -0,0 +1,53 @@ + 'is_superuser', + ]; + + /** + * Check if the user is superuser + * + * @param type $user User information object. + * @param Request $request Cake request object. + * @return bool + */ + public function authorize($user, Request $request) + { + $user = (array)$user; + $superuserField = $this->config('superuser_field'); + if (Hash::check($user, $superuserField)) { + return (bool)Hash::get($user, $superuserField); + } + + return false; + } +} diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php new file mode 100644 index 000000000..802051335 --- /dev/null +++ b/src/Controller/AppController.php @@ -0,0 +1,33 @@ +loadComponent('Security'); + $this->loadComponent('Csrf'); + $this->loadComponent('Users.UsersAuth'); + } +} diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php new file mode 100644 index 000000000..3f6da32d1 --- /dev/null +++ b/src/Controller/Component/RememberMeComponent.php @@ -0,0 +1,152 @@ +_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::salt(), '8bit') < 32) { + throw new InvalidArgumentException( + __d('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->_registry->getController()->eventManager(); + $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->request->header('User-Agent'); + $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) + { + if (!empty($this->Auth->user()) || $this->request->is(['post', 'put']) || $this->request->action === 'logout' || $this->request->session()->check(Configure::read('Users.Key.Session.social'))) { + return; + } + + $user = $this->Auth->identify(); + //No user no cookies + if (empty($user)) { + return; + } + $this->Auth->setUser($user); + $event = $this->_registry->getController()->dispatchEvent(UsersAuthComponent::EVENT_AFTER_COOKIE_LOGIN); + if (is_array($event->result)) { + return $this->_registry->getController()->redirect($event->result); + } + $url = $this->Auth->redirectUrl(); + return $this->_registry->getController()->redirect($url); + } +} diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php new file mode 100644 index 000000000..d5aa71a77 --- /dev/null +++ b/src/Controller/Component/UsersAuthComponent.php @@ -0,0 +1,178 @@ +_validateConfig(); + $this->_initAuth(); + + if (Configure::read('Users.Social.login') && !empty(Configure::read('Opauth'))) { + $this->_configOpauthRoutes(); + } + if (Configure::read('Users.Social.login')) { + $this->_loadSocialLogin(); + } + if (Configure::read('Users.RememberMe.active')) { + $this->_loadRememberMe(); + } + + $this->_attachPermissionChecker(); + } + + /** + * Load Social Auth object + * + * @return void + */ + protected function _loadSocialLogin() + { + $this->_registry->getController()->Auth->config('authenticate', [ + 'Users.Social' + ], true); + } + + /** + * Load RememberMe component and Auth objects + * + * @return void + */ + protected function _loadRememberMe() + { + $this->_registry->getController()->loadComponent('Users.RememberMe'); + } + + /** + * Attach the isUrlAuthorized event to allow using the Auth authorize from the UserHelper + * + * @return void + */ + protected function _attachPermissionChecker() + { + $this->_registry->getController()->eventManager()->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->_registry->getController()->loadComponent('Auth', Configure::read('Auth')); + } + + $this->_registry->getController()->Auth->allow([ + 'register', + 'validate', + 'resendTokenValidation', + 'login', + 'socialEmail', + 'opauthInit', + 'resetPassword', + 'requestResetPassword', + 'changePassword', + ]); + } + + /** + * Check if a given url is authorized + * + * @param Event $event event + * + * @return bool + */ + public function isUrlAuthorized(Event $event) + { + if (empty($this->_registry->getController()->Auth->user())) { + return false; + } + $url = Hash::get($event->data, 'url'); + if (empty($url)) { + return false; + } + + if (is_array($url)) { + $requestParams = $url; + $requestUrl = Router::reverse($url); + } else { + $requestParams = Router::parse($url); + $requestUrl = $url; + } + $request = new Request($url); + $request->params = $requestParams; + + $isAuthorized = $this->_registry->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('Users', 'You can\'t enable email validation workflow if use_email is false'); + throw new BadConfigurationException($message); + } + } + + /** + * Config Opauth urls + * + * @return void + */ + protected function _configOpauthRoutes() + { + $path = Configure::read('Opauth.path'); + Configure::write('Opauth.path', Router::url($path) . '/'); + //Generate callback url + if (is_array($path)) { + $path[] = Configure::read('Opauth.callback_param'); + } else { + $path = $path . Configure::read('Opauth.callback_param'); + } + Configure::write('Opauth.callback_url', Router::url($path)); + } +} diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php new file mode 100644 index 000000000..5f3957b99 --- /dev/null +++ b/src/Controller/SocialAccountsController.php @@ -0,0 +1,92 @@ +Auth->allow(['validate', 'resendValidation']); + } + + /** + * Validates social account + * + * @param string $provider provider + * @param string $reference reference + * @param string $token token + * @return Response + */ + public function validate($provider, $reference, $token) + { + try { + $result = $this->SocialAccounts->validateAccount($provider, $reference, $token); + if ($result) { + $this->Flash->success(__d('Users', 'Account validated successfully')); + } else { + $this->Flash->error(__d('Users', 'Account could not be validated')); + } + } catch (RecordNotFoundException $exception) { + $this->Flash->error(__d('Users', 'Invalid token and/or social account')); + } catch (AccountAlreadyActiveException $exception) { + $this->Flash->error(__d('Users', 'SocialAccount already active')); + } catch (Exception $exception) { + $this->Flash->error(__d('Users', 'Social Account could not be validated')); + } + return $this->redirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + } + + /** + * Resends validation email if required + * + * @param string $provider provider + * @param string $reference reference + * @return Response|void + * @throws \Users\Model\Table\AccountAlreadyActiveException + */ + public function resendValidation($provider, $reference) + { + try { + $result = $this->SocialAccounts->resendValidation($provider, $reference); + if ($result) { + $this->Flash->success(__d('Users', 'Email sent successfully')); + } else { + $this->Flash->error(__d('Users', 'Email could not be sent')); + } + } catch (RecordNotFoundException $exception) { + $this->Flash->error(__d('Users', 'Invalid account')); + } catch (AccountAlreadyActiveException $exception) { + $this->Flash->error(__d('Users', 'Social Account already active')); + } catch (Exception $exception) { + $this->Flash->error(__d('Users', 'Email could not be resent')); + } + return $this->redirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + } +} diff --git a/src/Controller/Traits/CustomUsersTableTrait.php b/src/Controller/Traits/CustomUsersTableTrait.php new file mode 100644 index 000000000..5d6f47866 --- /dev/null +++ b/src/Controller/Traits/CustomUsersTableTrait.php @@ -0,0 +1,50 @@ +_usersTable instanceof Table) { + return $this->_usersTable; + } + $this->_usersTable = TableRegistry::get(Configure::read('Users.table')); + return $this->_usersTable; + } + + /** + * Set the users table + * + * @param Table $table table + * @return void + */ + public function setUsersTable(Table $table) + { + $this->_usersTable = $table; + } +} diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php new file mode 100644 index 000000000..a1e73baa9 --- /dev/null +++ b/src/Controller/Traits/LoginTrait.php @@ -0,0 +1,133 @@ +dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGIN); + if (is_array($event->result)) { + $this->Auth->setUser($event->result); + return $this->_afterIdentifyUser($event->result); + } + if ($event->isStopped()) { + return $this->redirect($event->result); + } + $socialLogin = $this->_isSocialLogin(); + + if (!$this->request->is('post') && !$socialLogin) { + return; + } + + try { + $user = $this->Auth->identify(); + return $this->_afterIdentifyUser($user, $socialLogin); + } catch (AccountNotActiveException $ex) { + $socialKey = Configure::read('Users.Key.Session.social'); + $this->request->session()->delete($socialKey); + $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); + $this->Flash->success($msg); + } catch (MissingEmailException $ex) { + $this->Flash->success(__d('Users', 'Please enter your email')); + return $this->redirect(['controller' => 'Users', 'action' => 'socialEmail']); + } + } + + /** + * Update remember me and 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) + { + $socialKey = Configure::read('Users.Key.Session.social'); + if (!empty($user)) { + $this->request->session()->delete($socialKey); + $this->Auth->setUser($user); + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN); + if (is_array($event->result)) { + return $this->redirect($event->result); + } + $url = $this->Auth->redirectUrl(); + return $this->redirect($url); + } else { + $message = __d('Users', 'Username or password is incorrect'); + if ($socialLogin) { + $socialData = $this->request->session()->check($socialKey); + if (Configure::read('Users.Email.required') && + empty($socialData->info[Configure::read('data_email_key')]) && + empty($this->request->data(Configure::read('Users.Key.Data.email')))) { + return $this->redirect([ + 'controller' => 'Users', + 'action' => 'socialEmail' + ]); + } else { + $message = __d('Users', 'There was an error associating your social network account'); + } + } + $this->Flash->error($message, 'default', [], 'auth'); + } + } + + /** + * Logout + * + * @return type + */ + public function logout() + { + $eventBefore = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGOUT); + if (is_array($eventBefore->result)) { + return $this->redirect($eventBefore->result); + } + + $this->request->session()->destroy(); + $this->Flash->success(__d('Users', 'You\'ve successfully logged out')); + + $eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT); + if (is_array($eventAfter->result)) { + return $this->redirect($eventAfter->result); + } + + return $this->redirect($this->Auth->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->session()->check(Configure::read('Users.Key.Session.social')); + } +} diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php new file mode 100644 index 000000000..4968c5fa2 --- /dev/null +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -0,0 +1,113 @@ +getUsersTable()->newEntity(); + $id = $this->Auth->user('id'); + if (!empty($id)) { + $user->id = $this->Auth->user('id'); + $validatePassword = true; + //@todo add to the documentation: list of routes used + $redirect = ['admin' => false, 'plugin' => 'Users', 'controller' => 'users', 'action' => 'profile']; + } else { + $user->id = $this->request->session()->read(Configure::read('Users.Key.Session.resetPasswordUserId')); + $validatePassword = false; + //@todo add to the documentation: list of routes used + $redirect = ['admin' => false, 'plugin' => 'Users', 'controller' => 'users', 'action' => 'login']; + } + $this->set('validatePassword', $validatePassword); + if ($this->request->is('post')) { + try { + $user = $this->getUsersTable()->patchEntity($user, $this->request->data(), ['validate' => 'passwordConfirm']); + $user = $this->getUsersTable()->changePassword($user); + if ($user) { + $this->Flash->success(__d('Users', 'Password has been changed successfully')); + return $this->redirect($redirect); + } else { + $this->Flash->error(__d('Users', 'Password could not be changed')); + } + } catch (UserNotFoundException $exception) { + $this->Flash->error(__d('Users', 'User was not found')); + } catch (WrongPasswordException $wpe) { + $this->Flash->error(__d('Users', 'The current password does not match')); + } catch (Exception $exception) { + $this->Flash->error(__d('Users', 'Password could not be changed')); + } + } + $this->set(compact('user')); + $this->set('_serialize', ['user']); + } + + /** + * Reset password + * + * @param null $token token data. + * @return void + */ + public function resetPassword($token = null) + { + $this->validate('password', $token); + } + + /** + * Reset password + * + * @return void|\Cake\Network\Response + */ + public function requestResetPassword() + { + if ($this->request->is('post')) { + $reference = $this->request->data('reference'); + try { + $resetUser = $this->getUsersTable()->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => false, + 'sendMail' => true, + ]); + if ($resetUser) { + $msg = __d('Users', 'Please check your email to continue with password reset process'); + $this->Flash->success($msg); + } else { + $msg = __d('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('Users', 'User {0} was not found', $reference)); + } catch (Exception $exception) { + $this->Flash->error(__d('Users', 'Token could not be reset')); + } + } + $this->set('user', $this->getUsersTable()->newEntity()); + $this->set('_serialize', ['user']); + } +} diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php new file mode 100644 index 000000000..be2e4146b --- /dev/null +++ b/src/Controller/Traits/ProfileTrait.php @@ -0,0 +1,52 @@ +Auth->user('id'); + $isCurrentUser = false; + if (!Configure::read('Users.Profile.viewOthers') || empty($id)) { + $id = $loggedUserId; + } + try { + $user = $this->getUsersTable()->get($id, [ + 'contain' => ['SocialAccounts'] + ]); + $this->set('avatarPlaceholder', Configure::read('Users.Avatar.placeholder')); + if ($user->id === $loggedUserId) { + $isCurrentUser = true; + } + + } catch (InvalidPrimaryKeyException $ipke) { + $this->Flash->error(__d('Users', 'User was not found', $id)); + return $this->redirect($this->request->referer()); + } + $this->set(compact('user', 'isCurrentUser')); + $this->set('_serialize', ['user', 'isCurrentUser']); + } +} diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php new file mode 100644 index 000000000..5fc9f29ef --- /dev/null +++ b/src/Controller/Traits/RegisterTrait.php @@ -0,0 +1,106 @@ +getUsersTable(); + $user = $usersTable->newEntity(); + $validateEmail = (bool)Configure::read('Users.Email.validate'); + $useTos = (bool)Configure::read('Users.Tos.required'); + $tokenExpiration = Configure::read('Users.Token.expiration'); + $options = [ + 'token_expiration' => $tokenExpiration, + 'validate_email' => $validateEmail, + 'use_tos' => $useTos + ]; + $requestData = $this->request->data; + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_REGISTER, [ + 'usersTable' => $usersTable, + 'options' => $options, + ]); + if ($event->result instanceof EntityInterface) { + $options['validator'] = 'default'; + if ($userSaved = $usersTable->register($user, $event->result->toArray(), $options)) { + return $this->_afterRegister($userSaved); + } + } + if ($event->isStopped()) { + return $this->redirect($event->result); + } + + if ($this->request->is('post')) { + if ($userSaved = $usersTable->register($user, $requestData, $options)) { + return $this->_afterRegister($userSaved); + } else { + $this->Flash->error(__d('Users', 'The user could not be saved')); + } + } + $this->set(compact('user')); + $this->set('_serialize', ['user']); + } + + /** + * Prepare flash messages after registration, and dispatch afterRegister event + * + * @param EntityInterface $userSaved User entity saved + * @return Response + */ + protected function _afterRegister(EntityInterface $userSaved) + { + $validateEmail = (bool)Configure::read('Users.Email.validate'); + $message = __d('Users', 'You have registered successfully, please log in'); + if ($validateEmail) { + $message = __d('Users', 'Please validate your account before log in'); + } + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, [ + 'user' => $userSaved + ]); + if ($event->result instanceof Response) { + return $event->result; + } + $this->Flash->success($message); + return $this->redirect(['action' => 'login']); + } + + /** + * Validate an email + * + * @param string $token token + * @return void + */ + public function validateEmail($token = null) + { + $this->validate('email', $token); + } +} diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php new file mode 100644 index 000000000..9171ed4df --- /dev/null +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -0,0 +1,131 @@ +loadModel(); + $tableAlias = $table->alias(); + $this->set($tableAlias, $this->paginate($table)); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + } + + /** + * View method + * + * @param string|null $id User id. + * @return void + * @throws NotFoundException When record not found. + */ + public function view($id = null) + { + $table = $this->loadModel(); + $tableAlias = $table->alias(); + $entity = $table->get($id, [ + 'contain' => [] + ]); + $this->set($tableAlias, $entity); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + } + + /** + * Add method + * + * @return void Redirects on successful add, renders view otherwise. + */ + public function add() + { + $table = $this->loadModel(); + $tableAlias = $table->alias(); + $entity = $table->newEntity(); + $this->set($tableAlias, $entity); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + if (!$this->request->is('post')) { + return; + } + $entity = $table->patchEntity($entity, $this->request->data); + if ($table->save($entity)) { + $this->Flash->success(__d('Users', 'The {0} has been saved', Inflector::humanize($tableAlias))); + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__d('Users', 'The {0} could not be saved', Inflector::humanize($tableAlias))); + } + + /** + * Edit method + * + * @param string|null $id User id. + * @return void Redirects on successful edit, renders view otherwise. + * @throws NotFoundException When record not found. + */ + public function edit($id = null) + { + $table = $this->loadModel(); + $tableAlias = $table->alias(); + $entity = $table->get($id, [ + 'contain' => [] + ]); + $this->set($tableAlias, $entity); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + if (!$this->request->is(['patch', 'post', 'put'])) { + return; + } + $entity = $table->patchEntity($entity, $this->request->data); + if ($table->save($entity)) { + $this->Flash->success(__d('Users', 'The {0} has been saved', Inflector::humanize($tableAlias))); + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__d('Users', 'The {0} could not be saved', Inflector::humanize($tableAlias))); + } + + /** + * Delete method + * + * @param string|null $id User id. + * @return void Redirects to index. + * @throws NotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $table = $this->loadModel(); + $tableAlias = $table->alias(); + $entity = $table->get($id, [ + 'contain' => [] + ]); + if ($table->delete($entity)) { + $this->Flash->success(__d('Users', 'The {0} has been deleted', Inflector::humanize($tableAlias))); + } else { + $this->Flash->error(__d('Users', 'The {0} could not be deleted', Inflector::humanize($tableAlias))); + } + return $this->redirect(['action' => 'index']); + } +} diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php new file mode 100644 index 000000000..2796065c7 --- /dev/null +++ b/src/Controller/Traits/SocialTrait.php @@ -0,0 +1,82 @@ +autoRender = false; + $Opauth = $this->_getOpauthInstance(); + $response = $Opauth->run(); + if (empty($callback)) { + return; + } + $url = $this->_generateOpauthCompleteUrl(); + $this->request->session()->write(Configure::read('Users.Key.Session.social'), $response); + $this->redirect($url); + } + + /** + * Generates the opauth callback url + * + * @return string Full translated URL with base path. + */ + protected function _generateOpauthCompleteUrl() + { + $url = Configure::read('Opauth.complete_url'); + if (!is_array($url)) { + $url = Router::parse($url); + } + $url['?'] = ['social' => $this->request->query('code')]; + return Router::url($url); + } + + /** + * Render the social email form + * + * @throws NotFoundException + * @return void + */ + public function socialEmail() + { + if (!$this->request->session()->check(Configure::read('Users.Key.Session.social'))) { + throw new NotFoundException(); + } + } + + /** + * Gets OpauthFactory instance + * + * @return OpauthFactory + */ + protected function _getOpauthInstance() + { + return OpauthFactory::create(Configure::read('Opauth')); + } +} diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php new file mode 100644 index 000000000..385c4e843 --- /dev/null +++ b/src/Controller/Traits/UserValidationTrait.php @@ -0,0 +1,104 @@ +getUsersTable()->validate($token, 'activateUser'); + if ($result) { + $this->Flash->success(__d('Users', 'User account validated successfully')); + } else { + $this->Flash->error(__d('Users', 'User account could not be validated')); + } + } catch (UserAlreadyActiveException $exception) { + $this->Flash->error(__d('Users', 'User already active')); + } + break; + case 'password': + $result = $this->getUsersTable()->validate($token); + if (!empty($result)) { + $this->Flash->success(__d('Users', 'Reset password token was validated successfully')); + $this->request->session()->write(Configure::read('Users.Key.Session.resetPasswordUserId'), $result->id); + $this->redirect(['action' => 'changePassword']); + } else { + $this->Flash->error(__d('Users', 'Reset password token could not be validated')); + } + break; + default: + throw new InvalidArgumentException(); + } + } catch (UserNotFoundException $exception) { + $this->Flash->error(__d('Users', 'Invalid token and/or email')); + } catch (TokenExpiredException $exception) { + $this->Flash->error(__d('Users', 'Token already expired')); + } catch (InvalidArgumentException $iae) { + $this->Flash->error(__d('Users', 'Invalid validation type')); + } + return $this->redirect(['action' => 'login']); + } + + /** + * Resend Token validation + * + * @return mixed + */ + public function resendTokenValidation() + { + if ($this->request->is('post')) { + $reference = $this->request->data('reference'); + try { + if ($this->getUsersTable()->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => true, + ])) { + $this->Flash->success(__d('Users', 'Token has been reset successfully')); + } else { + $this->Flash->error(__d('Users', 'Token could not be reset')); + } + return $this->redirect(['action' => 'login']); + } catch (UserNotFoundException $exception) { + $this->Flash->error(__d('Users', 'User {0} was not found', $reference)); + } catch (UserAlreadyActiveException $exception) { + $this->Flash->error(__d('Users', 'User {0} is already active', $reference)); + } catch (Exception $exception) { + $this->Flash->error(__d('Users', 'Token could not be reset')); + } + } + $this->set('user', $this->getUsersTable()->newEntity()); + $this->set('_serialize', ['user']); + } +} diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php new file mode 100644 index 000000000..92255d7e9 --- /dev/null +++ b/src/Controller/UsersController.php @@ -0,0 +1,34 @@ +\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=INTEGER; plural=EXPRESSION;\n" + +#: Auth/SimpleRbacAuthorize.php:132 +msgid "Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "" + +#: Controller/SocialAccountsController.php:59 +msgid "SocialAccount already active" +msgstr "" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "" + +#: Controller/SocialAccountsController.php:79 +msgid "Email sent successfully" +msgstr "" + +#: Controller/SocialAccountsController.php:81 +msgid "Email could not be sent" +msgstr "" + +#: Controller/SocialAccountsController.php:84 +msgid "Invalid account" +msgstr "" + +#: Controller/SocialAccountsController.php:86 +msgid "Social Account already active" +msgstr "" + +#: Controller/SocialAccountsController.php:88 +msgid "Email could not be resent" +msgstr "" + +#: Controller/Component/RememberMeComponent.php:70 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" + +#: Controller/Component/UsersAuthComponent.php:156 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" + +#: Controller/Traits/LoginTrait.php:55 +msgid "The social account is not active. Please check your email for instructions. {0}" +msgstr "" + +#: Controller/Traits/LoginTrait.php:58 +#: Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "" + +#: Controller/Traits/LoginTrait.php:82 +msgid "Username or password is incorrect" +msgstr "" + +#: Controller/Traits/LoginTrait.php:93 +msgid "There was an error associating your social network account" +msgstr "" + +#: Controller/Traits/LoginTrait.php:113 +msgid "You've successfully logged out" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:53 +msgid "Password has been changed successfully" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:56;63 +msgid "Password could not be changed" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:59 +#: Controller/Traits/ProfileTrait.php:46 +msgid "User was not found" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:61 +msgid "The current password does not match" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:93 +msgid "Please check your email to continue with password reset process" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:96 +msgid "The password token could not be generated. Please try again" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:101 +#: Controller/Traits/UserValidationTrait.php:94 +msgid "User {0} was not found" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:103 +#: Controller/Traits/UserValidationTrait.php:90;98 +msgid "Token could not be reset" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:66 +msgid "The user could not be saved" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:82 +msgid "You have registered successfully, please log in" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:84 +msgid "Please validate your account before log in" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:75;103 +msgid "The {0} has been saved" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:78;106 +msgid "The {0} could not be saved" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:125 +msgid "The {0} has been deleted" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:127 +msgid "The {0} could not be deleted" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token and/or email" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid validation type" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:88 +msgid "Token has been reset successfully" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:96 +msgid "User {0} is already active" +msgstr "" + +#: Model/Table/SocialAccountsTable.php:208 +msgid "{0}Your social account validation link" +msgstr "" + +#: Model/Table/SocialAccountsTable.php:235;263 +msgid "Account already validated" +msgstr "" + +#: Model/Table/SocialAccountsTable.php:238;266 +msgid "Account not found for the given token and email." +msgstr "" + +#: Model/Table/UsersTable.php:84 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" + +#: Model/Table/UsersTable.php:178 +msgid "Username already exists" +msgstr "" + +#: Model/Table/UsersTable.php:184 +msgid "Email already exists" +msgstr "" + +#: Model/Table/UsersTable.php:213 +msgid "The \"tos\" property is not present" +msgstr "" + +#: Model/Table/UsersTable.php:271 +msgid "Token has already expired user with no token" +msgstr "" + +#: Model/Table/UsersTable.php:274 +msgid "User not found for the given token and email." +msgstr "" + +#: Model/Table/UsersTable.php:341 +msgid "User not found" +msgstr "" + +#: Model/Table/UsersTable.php:368 +msgid "+ {0} secs" +msgstr "" + +#: Model/Table/UsersTable.php:420 +msgid "Unable to login user with reference {0}" +msgstr "" + +#: Model/Table/UsersTable.php:453 +msgid "Email not present" +msgstr "" + +#: Model/Table/UsersTable.php:541 +msgid "{0}Your account validation link" +msgstr "" + +#: Model/Table/UsersTable.php:561 +msgid "{0}Your reset password link" +msgstr "" + +#: Model/Table/UsersTable.php:585 +msgid "The old password does not match" +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 correcly displayed, please copy the following address in your web browser {0}" +msgstr "" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "Please copy the following address in your web browser to activate your social login {0}" +msgstr "" + +#: Template/Users/add.ctp:13 +#: Template/Users/edit.ctp:13 +#: Template/Users/index.ctp:13;26 +#: Template/Users/view.ctp:13;77 +msgid "Actions" +msgstr "" + +#: Template/Users/add.ctp:15 +#: Template/Users/edit.ctp:21 +#: Template/Users/view.ctp:17 +msgid "List Users" +msgstr "" + +#: Template/Users/add.ctp:16 +#: Template/Users/edit.ctp:22 +#: Template/Users/view.ctp:19 +msgid "List Accounts" +msgstr "" + +#: Template/Users/add.ctp:22 +#: Template/Users/register.ctp:15 +msgid "Add User" +msgstr "" + +#: Template/Users/add.ctp:32 +#: Template/Users/change_password.ctp:13 +#: Template/Users/edit.ctp:42 +#: Template/Users/register.ctp:26 +#: 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:7 +msgid "Current password" +msgstr "" + +#: Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:40 +#: Template/Users/view.ctp:99 +msgid "Delete" +msgstr "" + +#: Template/Users/edit.ctp:18 +#: Template/Users/index.ctp:40 +#: Template/Users/view.ctp:16;99 +msgid "Are you sure you want to delete # {0}?" +msgstr "" + +#: Template/Users/edit.ctp:28 +#: Template/Users/view.ctp:15 +msgid "Edit User" +msgstr "" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "" + +#: Template/Users/index.ctp:37 +#: Template/Users/view.ctp:95 +msgid "View" +msgstr "" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "" + +#: Template/Users/index.ctp:39 +#: Template/Users/view.ctp:97 +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:26 +msgid "Remember me" +msgstr "" + +#: Template/Users/login.ctp:49 +msgid "Login" +msgstr "" + +#: Template/Users/profile.ctp:18 +msgid "{0} {1}" +msgstr "" + +#: Template/Users/profile.ctp:23 +msgid "Change Password" +msgstr "" + +#: Template/Users/profile.ctp:26 +#: Template/Users/view.ctp:28;68 +msgid "Username" +msgstr "" + +#: Template/Users/profile.ctp:28 +#: Template/Users/view.ctp:30 +msgid "Email" +msgstr "" + +#: Template/Users/profile.ctp:33 +msgid "Social Accounts" +msgstr "" + +#: Template/Users/profile.ctp:37 +#: Template/Users/view.ctp:70 +msgid "Avatar" +msgstr "" + +#: Template/Users/profile.ctp:38 +#: Template/Users/view.ctp:67 +msgid "Provider" +msgstr "" + +#: Template/Users/profile.ctp:39 +msgid "Link" +msgstr "" + +#: Template/Users/register.ctp:23 +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/view.ctp:16 +msgid "Delete User" +msgstr "" + +#: Template/Users/view.ctp:18 +msgid "New User" +msgstr "" + +#: Template/Users/view.ctp:26;65 +msgid "Id" +msgstr "" + +#: Template/Users/view.ctp:32 +msgid "First Name" +msgstr "" + +#: Template/Users/view.ctp:34 +msgid "Last Name" +msgstr "" + +#: Template/Users/view.ctp:36;71 +msgid "Token" +msgstr "" + +#: Template/Users/view.ctp:38 +msgid "Api Token" +msgstr "" + +#: Template/Users/view.ctp:42;73 +msgid "Active" +msgstr "" + +#: Template/Users/view.ctp:46;72 +msgid "Token Expires" +msgstr "" + +#: Template/Users/view.ctp:48 +msgid "Activation Date" +msgstr "" + +#: Template/Users/view.ctp:50 +msgid "Tos Date" +msgstr "" + +#: Template/Users/view.ctp:52;75 +msgid "Created" +msgstr "" + +#: Template/Users/view.ctp:54;76 +msgid "Modified" +msgstr "" + +#: Template/Users/view.ctp:61 +msgid "Related Accounts" +msgstr "" + +#: Template/Users/view.ctp:66 +msgid "User Id" +msgstr "" + +#: Template/Users/view.ctp:69 +msgid "Reference" +msgstr "" + +#: Template/Users/view.ctp:74 +msgid "Data" +msgstr "" + +#: View/Helper/UserHelper.php:43 +msgid "Sign in with Facebook" +msgstr "" + +#: View/Helper/UserHelper.php:57 +msgid "Sign in with Twitter" +msgstr "" + +#: View/Helper/UserHelper.php:71 +msgid "Logout" +msgstr "" + +#: View/Helper/UserHelper.php:109 +msgid "Welcome, {0}" +msgstr "" + diff --git a/src/Model/Entity/SocialAccount.php b/src/Model/Entity/SocialAccount.php new file mode 100644 index 000000000..9f9138aac --- /dev/null +++ b/src/Model/Entity/SocialAccount.php @@ -0,0 +1,42 @@ + true, + 'provider' => true, + 'username' => true, + 'reference' => true, + 'avatar' => true, + 'description' => true, + 'link' => true, + 'token' => true, + 'token_secret' => true, + 'token_expires' => true, + 'active' => true, + 'data' => true, + 'user' => true, + ]; +} diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php new file mode 100644 index 000000000..f1c00f924 --- /dev/null +++ b/src/Model/Entity/User.php @@ -0,0 +1,98 @@ + true, + 'email' => true, + 'password' => true, + 'confirm_password' => true, + 'first_name' => true, + 'last_name' => true, + 'token' => true, + 'token_expires' => true, + 'api_token' => true, + 'activation_date' => true, + //tos is a boolean, coming from the "accept the terms of service" checkbox but it is not stored onto database + 'tos' => true, + 'tos_date' => true, + 'active' => true, + 'social_accounts' => true, + 'current_password' => true + ]; + + /** + * @param string $password password that will be set. + * @return bool|string + */ + protected function _setPassword($password) + { + return (new DefaultPasswordHasher)->hash($password); + } + + /** + * @param string $password password that will be confirm. + * @return bool|string + */ + protected function _setConfirmPassword($password) + { + return (new DefaultPasswordHasher)->hash($password); + } + + /** + * Checks if a password is correctly hashed + * @param string $password password that will be check. + * @param string $hashedPassword hash used to check password. + * @return bool + */ + public function checkPassword($password, $hashedPassword) + { + return (new DefaultPasswordHasher)->check($password, $hashedPassword); + } + + /** + * Returns if the token has already expired + * + * @return bool + */ + public function tokenExpired() + { + return empty($this->token_expires) || strtotime($this->token_expires) < strtotime("now"); + } + + /** + * Getter for user avatar + * @return string|null avatar + */ + protected function _getAvatar() + { + $avatar = null; + if (!empty($this->_properties['social_accounts'][0])) { + $avatar = $this->_properties['social_accounts'][0]['avatar']; + } + return $avatar; + } +} diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php new file mode 100644 index 000000000..807af9296 --- /dev/null +++ b/src/Model/Table/SocialAccountsTable.php @@ -0,0 +1,240 @@ +table('social_accounts'); + $this->displayField('id'); + $this->primaryKey('id'); + $this->addBehavior('Timestamp'); + $this->belongsTo('Users', [ + 'foreignKey' => 'user_id', + 'joinType' => 'INNER', + 'className' => Configure::read('Users.table') + ]); + } + + /** + * Default validation rules. + * + * @param Validator $validator Validator instance. + * @return Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->add('id', 'valid', ['rule' => 'uuid']) + ->allowEmpty('id', 'create'); + + $validator + ->requirePresence('provider', 'create') + ->notEmpty('provider'); + + $validator + ->allowEmpty('username'); + + $validator + ->requirePresence('reference', 'create') + ->notEmpty('reference'); + + $validator + ->requirePresence('link', 'create') + ->notEmpty('reference'); + + $validator + ->allowEmpty('avatar'); + + $validator + ->allowEmpty('description'); + + $validator + ->requirePresence('token', 'create') + ->notEmpty('token'); + + $validator + ->allowEmpty('token_secret'); + + $validator + ->add('token_expires', 'valid', ['rule' => 'datetime']) + ->allowEmpty('token_expires'); + + $validator + ->add('active', 'valid', ['rule' => 'boolean']) + ->requirePresence('active', 'create') + ->notEmpty('active'); + + $validator + ->requirePresence('data', 'create') + ->notEmpty('data'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param RulesChecker $rules The rules object to be modified. + * @return RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->isUnique(['username'])); + $rules->add($rules->existsIn(['user_id'], 'Users')); + return $rules; + } + + /** + * After save callback + * + * @param Event $event event + * @param Entity $entity entity + * @param ArrayObject $options options + * @return mixed + */ + public function afterSave(Event $event, Entity $entity, $options) + { + if ($entity->active) { + return true; + } + $user = $this->Users->find()->where(['Users.id' => $entity->user_id, 'Users.active' => true])->first(); + if (empty($user)) { + return true; + } + return $this->sendSocialValidationEmail($entity, $user); + } + + /** + * Send social validation email to the user + * + * @param EntityInterface $socialAccount social account + * @param EntityInterface $user user + * @param Email $email Email instance or null to use 'default' configuration + * @return mixed + */ + public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) + { + $email = $this->Users->getEmailInstance($email); + $email->template('Users.social_account_validation'); + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + //note: we control the space after the username in the previous line + $subject = __d('Users', '{0}Your social account validation link', $firstName); + return $email + ->to($user['email']) + ->subject($subject) + ->viewVars(compact('user', 'socialAccount')) + ->send(); + } + + /** + * Validates the social account + * + * @param string $provider provider + * @param string $reference reference + * @param string $token token + * @throws RecordNotFoundException + * @throws AccountAlreadyActiveException + * @return User + */ + public function validateAccount($provider, $reference, $token) + { + $socialAccount = $this->find() + ->select(['id', 'provider', 'reference', 'active', 'token']) + ->where(['provider' => $provider, 'reference' => $reference]) + ->first(); + + if (!empty($socialAccount) && $socialAccount->token === $token) { + if ($socialAccount->active) { + throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); + } + } else { + throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); + } + + return $this->_activateAccount($socialAccount); + } + + /** + * Validates the social account + * + * @param string $provider provider + * @param string $reference reference + * @throws RecordNotFoundException + * @throws AccountAlreadyActiveException + * @return User + */ + public function resendValidation($provider, $reference) + { + $socialAccount = $this->find() + ->where(['provider' => $provider, 'reference' => $reference]) + ->contain('Users') + ->first(); + + if (!empty($socialAccount)) { + if ($socialAccount->active) { + throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); + } + } else { + throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); + } + + return $this->sendSocialValidationEmail($socialAccount, $socialAccount->user); + } + + /** + * Activates an account + * + * @param Account $socialAccount social account + * @return Account + */ + protected function _activateAccount($socialAccount) + { + $socialAccount->active = true; + $result = $this->save($socialAccount); + return $result; + } +} diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php new file mode 100644 index 000000000..c0ac5fd86 --- /dev/null +++ b/src/Model/Table/UsersTable.php @@ -0,0 +1,626 @@ +table('users'); + $this->displayField('id'); + $this->primaryKey('id'); + $this->addBehavior('Timestamp'); + $this->hasMany('SocialAccounts', [ + 'foreignKey' => 'user_id', + 'className' => 'Users.SocialAccounts' + ]); + } + + /** + * Adds some rules for password confirm + * @param Validator $validator Cake validator object. + * @return Validator + */ + public function validationPasswordConfirm(Validator $validator) + { + $validator + ->requirePresence('password_confirm', 'create') + ->notEmpty('password_confirm'); + + $validator->add('password', 'custom', [ + 'rule' => function ($value, $context) { + $confirm = Hash::get($context, 'data.password_confirm'); + if (!is_null($confirm) && $value != $confirm) { + return false; + } + return true; + }, + 'message' => __d('Users', 'Your password does not match your confirm password. Please try again'), + 'on' => ['create', 'update'], + 'allowEmpty' => false + ]); + + return $validator; + } + + /** + * Default validation rules. + * + * @param Validator $validator Validator instance. + * @return Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->allowEmpty('id', 'create'); + + $validator + ->requirePresence('username', 'create') + ->notEmpty('username'); + + $validator + ->requirePresence('password', 'create') + ->notEmpty('password'); + + $validator + ->allowEmpty('first_name'); + + $validator + ->allowEmpty('last_name'); + + $validator + ->allowEmpty('token'); + + $validator + ->add('token_expires', 'valid', ['rule' => 'datetime']) + ->allowEmpty('token_expires'); + + $validator + ->allowEmpty('api_token'); + + $validator + ->add('activation_date', 'valid', ['rule' => 'datetime']) + ->allowEmpty('activation_date'); + + $validator + ->add('tos_date', 'valid', ['rule' => 'datetime']) + ->allowEmpty('tos_date'); + + return $validator; + } + + /** + * Default+Email validation rules. + * + * @param Validator $validator Validator instance. + * @return Validator + */ + public function validationEmail(Validator $validator) + { + $validator = $this->validationRegister($validator); + $validator + ->add('email', 'valid', ['rule' => 'email']) + ->requirePresence('email', 'create') + ->notEmpty('email'); + return $validator; + } + + /** + * Wrapper for all validation rules for register + * @param Validator $validator Cake validator object. + * + * @return Validator + */ + public function validationRegister(Validator $validator) + { + $validator = $this->validationDefault($validator); + $validator = $this->validationPasswordConfirm($validator); + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param RulesChecker $rules The rules object to be modified. + * @return RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->isUnique(['username']), [ + 'errorField' => 'username', + 'message' => __d('Users', 'Username already exists') + ]); + + if ($this->isValidateEmail) { + $rules->add($rules->isUnique(['email']), [ + 'errorField' => 'email', + 'message' => __d('Users', 'Email already exists') + ]); + } + + return $rules; + } + + /** + * Registers an user. + * + * @param EntityInterface $user User information + * @param array $data User information + * @param array $options ['tokenExpiration] + * @return bool|EntityInterface + * @throws InvalidArgumentException + * @todo: move into new behavior + */ + public function register($user, $data, $options) + { + $validateEmail = Hash::get($options, 'validate_email'); + $validator = Hash::get($options, 'validator') ?: 'register'; + if ($validateEmail) { + $validator = 'email'; + } + $user = $this->patchEntity($user, $data, ['validate' => $validator]); + + $tokenExpiration = Hash::get($options, 'token_expiration'); + $useTos = Hash::get($options, 'use_tos'); + if ($useTos && !$user->tos) { + throw new InvalidArgumentException(__d('Users', 'The "tos" property is not present')); + } + + if (!empty($user['tos'])) { + $user->tos_date = new DateTime(); + } + $user->validated = false; + $this->_updateActive($user, $validateEmail, $tokenExpiration); + $this->isValidateEmail = $validateEmail; + $userSaved = $this->save($user); + if ($userSaved && $validateEmail) { + $this->sendValidationEmail($user); + } + return $userSaved; + } + + /** + * DRY for update active and token based on validateEmail flag + * + * @param type $user Reference of user to be updated. + * @param type $validateEmail email user to validate. + * @param type $tokenExpiration token to be updated. + * @return void + */ + protected function _updateActive(&$user, $validateEmail, $tokenExpiration) + { + $emailValidated = $user['validated']; + if (!$emailValidated && $validateEmail) { + $user['active'] = false; + $this->_updateToken($user, $tokenExpiration); + } else { + $user['active'] = true; + $user['activation_date'] = new DateTime(); + } + } + + /** + * Validates token and return user + * + * @param type $token toke to be validated. + * @param null $callback function that will be returned. + * @throws TokenExpiredException when token has expired. + * @throws UserNotFoundException when user isn't found. + * @return User $user + */ + public function validate($token, $callback = null) + { + $user = $this->find() + ->select(['token_expires', 'id', 'active', 'token']) + ->where(['token' => $token]) + ->first(); + if (!empty($user)) { + if (!$user->tokenExpired()) { + if (!empty($callback) && method_exists($this, $callback)) { + return $this->{$callback}($user); + } else { + return $user; + } + } else { + throw new TokenExpiredException(__d('Users', "Token has already expired user with no token")); + } + } else { + throw new UserNotFoundException(__d('Users', "User not found for the given token and email.")); + } + } + + /** + * Removes user token for validation + * + * @param User $user user object. + * @return User + * + * @todo: move into new behavior + */ + protected function _removesValidationToken(User $user) + { + $user->token = null; + $user->token_expires = null; + $result = $this->save($user); + + return $result; + } + + /** + * Activates an user + * + * @param User $user user object. + * @return mixed User entity or bool false if the user could not be activated + * @throws UserAlreadyActiveException + * @todo: move into new behavior + */ + public function activateUser(User $user) + { + if ($user->active) { + throw new UserAlreadyActiveException("User account already validated"); + } + $user = $this->_removesValidationToken($user); + $user->activation_date = new DateTime(); + $user->active = true; + $result = $this->save($user); + + return $result; + } + + /** + * Resets user token + * + * @param string $reference User username or email + * @param array $options checkActive, sendEmail, expiration + * + * @return string + * @throws InvalidArgumentException + * @throws UserNotFoundException + * @throws UserAlreadyActiveException + * @todo: move into new behavior + */ + public function resetToken($reference, array $options = []) + { + if (empty($reference)) { + throw new InvalidArgumentException(sprintf('Reference cannot be null')); + } + + if (empty(Hash::get($options, 'expiration'))) { + throw new InvalidArgumentException(sprintf('Token expiration cannot be null')); + } + + $user = $this->findAllByUsernameOrEmail($reference, $reference)->first(); + + if (empty($user)) { + throw new UserNotFoundException(__d('Users', "User not found")); + } + if (Hash::get($options, 'checkActive')) { + if ($user->active) { + throw new UserAlreadyActiveException("User account already validated"); + } + $user->active = false; + $user->activation_date = null; + } + $this->_updateToken($user, Hash::get($options, 'expiration')); + $saveResult = $this->save($user); + if (Hash::get($options, 'sendEmail')) { + $this->sendResetPasswordEmail($saveResult); + } + return $saveResult; + } + + /** + * Generate token_expires and token in a user + * @param type $user Reference to user. + * @param string $tokenExpiration new token_expires user. + * + * @return type + */ + protected function _updateToken(&$user, $tokenExpiration) + { + $expires = new DateTime(); + $expires->modify(__d('Users', '+ {0} secs', $tokenExpiration)); + $user['token_expires'] = $expires; + $user['token'] = $this->randomString(); + + return $user; + } + + /** + * Checks if username exists and generate a new one + * @param string $username username data. + * @return string + * + * @todo: move into new behavior + */ + protected function _generateUsername($username) + { + $i = 0; + while (true) { + $existingUsername = $this->find()->where([$this->alias() . '.username' => $username])->count(); + if ($existingUsername > 0) { + $username = $username . $i; + $i++; + continue; + } + break; + } + return $username; + } + + /** + * Performs social login + * @param array $data Array social login. + * @param array $options Array option data. + * @return bool|EntityInterface|mixed + * + * @todo: move into new behavior + * @todo: Improve docblock + */ + public function socialLogin($data, $options = []) + { + $provider = $data->provider; + $reference = $data->uid; + $existingAccount = $this->SocialAccounts->find() + ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $provider]) + ->contain(['Users']) + ->first(); + if (empty($existingAccount->user)) { + $user = $this->_createSocialUser($data, $options); + if (!empty($user->social_accounts[0])) { + $existingAccount = $user->social_accounts[0]; + } else { + //@todo: what if we don't have a social account after createSocialUser? + throw new InvalidArgumentException(__d('Users', 'Unable to login user with reference {0}', $reference)); + } + } else { + $user = $existingAccount->user; + } + if (!empty($existingAccount)) { + if ($existingAccount->active) { + return $user; + } else { + throw new AccountNotActiveException([ + $existingAccount->provider, + $existingAccount->reference + ]); + } + } + return false; + } + + /** + * Creates social user + * @param array $data Array social user. + * @param array $options Array option data. + * @return bool|EntityInterface|mixed + * + * @todo: move into new behavior + * @todo: Improve docblock + */ + protected function _createSocialUser($data, $options = []) + { + $useEmail = Hash::get($options, 'use_email'); + $validateEmail = Hash::get($options, 'validate_email'); + $tokenExpiration = Hash::get($options, 'token_expiration'); + if ($useEmail && empty($data->email)) { + throw new MissingEmailException(__d('Users', 'Email not present')); + } else { + $existingUser = $this->find() + ->where([$this->alias() . '.email' => $data->email]) + ->first(); + } + $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); + $this->isValidateEmail = $validateEmail; + $result = $this->save($user); + return $result; + } + + /** + * @param array $data Array social login. + * @param string $existingUser user data. + * @param string $useEmail email to use. + * @param string $validateEmail email to validate. + * @param string $tokenExpiration token_expires data. + * @return EntityInterface|\Cake\ORM\Entity + */ + protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) + { + $accountData['provider'] = $data->provider; + $accountData['username'] = Hash::get($data->info, 'nickname'); + $accountData['reference'] = $data->uid; + $accountData['avatar'] = Hash::get($data->info, 'image'); + /* @todo make a pull request to Opauth Facebook Strategy because it does not include link on info array */ + if ($data->provider == SocialAccountsTable::PROVIDER_TWITTER) { + $accountData['link'] = Hash::get($data->info, 'urls.twitter'); + } elseif ($data->provider == SocialAccountsTable::PROVIDER_FACEBOOK) { + $accountData['link'] = Hash::get($data->raw, 'link'); + } + $accountData['avatar'] = str_replace('square', 'large', $accountData['avatar']); + $accountData['description'] = Hash::get($data->info, 'description'); + $accountData['token'] = Hash::get((array)$data->credentials, 'token'); + $accountData['token_secret'] = Hash::get((array)$data->credentials, 'secret'); + $accountData['token_expires'] = !empty(Hash::get((array)$data->credentials, 'expires')) ? (new DateTime(Hash::get((array)$data->credentials, 'expires')))->format('Y-m-d H:i:s') : null; + $accountData['data'] = serialize($data->raw); + $accountData['active'] = true; + + if (empty($existingUser)) { + if (!empty($data->info['first_name']) && !empty($data->info['last_name'])) { + $userData['first_name'] = Hash::get($data->info, 'first_name'); + $userData['last_name'] = Hash::get($data->info, 'last_name'); + } else { + $name = explode(' ', $data->name); + $userData['first_name'] = Hash::get($name, 0); + array_shift($name); + $userData['last_name'] = implode(' ', $name); + } + $userData['username'] = Hash::get($data->info, 'nickname'); + if (empty(Hash::get($userData, 'username'))) { + if (!empty($data->email)) { + $email = explode('@', $data->email); + $userData['username'] = Hash::get($email, 0); + } else { + $firstName = Hash::get($userData, 'first_name'); + $lastName = Hash::get($userData, 'last_name'); + $userData['username'] = strtolower($firstName . $lastName); + $userData['username'] = preg_replace('/[^A-Za-z0-9]/i', '', Hash::get($userData, 'username')); + } + + } + $userData['username'] = $this->_generateUsername(Hash::get($userData, 'username')); + if ($useEmail) { + $userData['email'] = $data->email; + if (!$data->validated) { + $accountData['active'] = false; + } + } + $userData['password'] = $this->randomString(); + $userData['avatar'] = Hash::get($data->info, 'image'); + $userData['validated'] = $data->validated; + $this->_updateActive($userData, false, $tokenExpiration); + $userData['tos_date'] = date("Y-m-d H:i:s"); + $userData['gender'] = Hash::get($data->raw, 'gender'); + $userData['timezone'] = Hash::get($data->raw, 'timezone'); + $userData['social_accounts'][] = $accountData; + $user = $this->newEntity($userData, ['associated' => ['SocialAccounts']]); + } else { + if ($useEmail && !$data->validated) { + $accountData['active'] = false; + } + $user = $this->patchEntity($existingUser, [ + 'social_accounts' => [$accountData] + ], ['associated' => ['SocialAccounts']]); + } + return $user; + } + + /** + * Send the validation email to the newly registered user + * + * @param EntityInterface $user User entity + * @param Email $email instance, if null the default email configuration with the + * Users.validation template will be used, so set a ->template() if you pass an Email + * instance + * @return array email send result + */ + public function sendValidationEmail(EntityInterface $user, Email $email = null) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + $subject = __d('Users', '{0}Your account validation link', $firstName); + return $this->getEmailInstance($email) + ->to($user['email']) + ->subject($subject) + ->viewVars($user->toArray()) + ->send(); + } + + /** + * Send the reset password email + * + * @param EntityInterface $user User entity + * @param Email $email instance, if null the default email configuration with the + * Users.validation template will be used, so set a ->template() if you pass an Email + * instance + * @return array email send result + */ + public function sendResetPasswordEmail(EntityInterface $user, Email $email = null) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + $subject = __d('Users', '{0}Your reset password link', $firstName); + return $this->getEmailInstance($email) + ->template('Users.reset_password') + ->to($user['email']) + ->subject($subject) + ->viewVars($user->toArray()) + ->send(); + } + + /** + * Change password method + * + * @param User $user user data. + * @return mixed + * @internal param $data + */ + public function changePassword($user) + { + $currentUser = $this->get($user->id, [ + 'contain' => [] + ]); + + if (!empty($user->current_password)) { + if (!$user->checkPassword($user->current_password, $currentUser->password)) { + throw new WrongPasswordException(__d('Users', 'The old password does not match')); + } + } + $user = $this->save($user); + if (!empty($user)) { + $user = $this->_removesValidationToken($user); + } + return $user; + } + + /** + * Get or initialize the email instance. Used for mocking. + * + * @param Email $email if email provided, we'll use the instance instead of creating a new one + * @return Email + */ + public function getEmailInstance(Email $email = null) + { + if ($email === null) { + $email = new Email('default'); + $email->template('Users.validation') + ->emailFormat('both'); + } + + return $email; + } +} diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp new file mode 100644 index 000000000..189946af7 --- /dev/null +++ b/src/Template/Email/html/reset_password.ctp @@ -0,0 +1,31 @@ + true, + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => 'activate', + isset($token) ? $token : '' +]; +?> +

+, +

+

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

+

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

+

+ , +

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

+, +

+

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

+

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

+

+ , +

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

+, +

+

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

+

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

+

+ , +

diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp new file mode 100644 index 000000000..f57f61e1f --- /dev/null +++ b/src/Template/Email/text/reset_password.ctp @@ -0,0 +1,25 @@ + true, + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => 'activate', + isset($token) ? $token : '' +]; +?> +, + +Url->build($activationUrl)) ?> + +, + diff --git a/src/Template/Email/text/social_account_validation.ctp b/src/Template/Email/text/social_account_validation.ctp new file mode 100644 index 000000000..59240e0c3 --- /dev/null +++ b/src/Template/Email/text/social_account_validation.ctp @@ -0,0 +1,27 @@ + true, + 'plugin' => 'Users', + 'controller' => 'SocialAccounts', + 'action' => 'validateAccount', + $socialAccount['provider'], + $socialAccount['reference'], + $socialAccount['token'], + ]; +?> +, + +Url->build($activationUrl)) ?> + +, + diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp new file mode 100644 index 000000000..f57f61e1f --- /dev/null +++ b/src/Template/Email/text/validation.ctp @@ -0,0 +1,25 @@ + true, + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => 'activate', + isset($token) ? $token : '' +]; +?> +, + +Url->build($activationUrl)) ?> + +, + diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp new file mode 100644 index 000000000..29a1dfb61 --- /dev/null +++ b/src/Template/Users/add.ctp @@ -0,0 +1,34 @@ + +
+

+
    +
  • Html->link(__d('Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('Users', 'List Accounts'), ['controller' => 'Accounts', 'action' => 'index']) ?>
  • +
+
+
+ Form->create($Users); ?> +
+ + Form->input('username'); + echo $this->Form->input('email'); + echo $this->Form->input('password'); + echo $this->Form->input('first_name'); + echo $this->Form->input('last_name'); + echo $this->Form->input('active', ['type' => 'checkbox']); + ?> +
+ Form->button(__d('Users', 'Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/change_password.ctp b/src/Template/Users/change_password.ctp new file mode 100644 index 000000000..3250b033a --- /dev/null +++ b/src/Template/Users/change_password.ctp @@ -0,0 +1,15 @@ +
+ Flash->render('auth') ?> + Form->create($user) ?> +
+ + + Form->input('current_password', ['type' => 'password', 'required' => true, 'label' => __d('Users', 'Current password')]); ?> + + Form->input('password'); ?> + Form->input('password_confirm', ['type' => 'password', 'required' => true]); ?> + +
+ Form->button(__d('Users', 'Submit')); ?> + Form->end() ?> +
\ No newline at end of file diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp new file mode 100644 index 000000000..550b124fe --- /dev/null +++ b/src/Template/Users/edit.ctp @@ -0,0 +1,44 @@ + +
+

+
    +
  • Form->postLink( + __d('Users', 'Delete'), + ['action' => 'delete', $Users->id], + ['confirm' => __d('Users', 'Are you sure you want to delete # {0}?', $Users->id)] + ) + ?>
  • +
  • Html->link(__d('Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('Users', 'List Accounts'), ['controller' => 'Accounts', 'action' => 'index']) ?>
  • +
+
+
+ Form->create($Users); ?> +
+ + Form->input('username'); + echo $this->Form->input('email'); + echo $this->Form->input('first_name'); + echo $this->Form->input('last_name'); + echo $this->Form->input('token'); + echo $this->Form->input('token_expires'); + echo $this->Form->input('api_token'); + echo $this->Form->input('activation_date'); + echo $this->Form->input('tos_date'); + echo $this->Form->input('active'); + ?> +
+ Form->button(__d('Users', 'Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/index.ctp b/src/Template/Users/index.ctp new file mode 100644 index 000000000..500b381a7 --- /dev/null +++ b/src/Template/Users/index.ctp @@ -0,0 +1,55 @@ + +
+

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

Paginator->counter() ?>

+
+
diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp new file mode 100644 index 000000000..591fcc073 --- /dev/null +++ b/src/Template/Users/login.ctp @@ -0,0 +1,51 @@ + +
+ Flash->render('auth') ?> + Form->create() ?> +
+ + Form->input('username', ['required' => true]) ?> + Form->input('password', ['required' => true]) ?> + Form->input(Configure::read('Users.Key.Data.rememberMe'), [ + 'type' => 'checkbox', + 'label' => __d('Users', 'Remember me'), + 'checked' => 'checked' + ]); + } + ?> +

+ Html->link(__d('users', 'Register'), ['action' => 'register']); + } + if (Configure::check('Users.Email.required')) { + echo ' | '; + echo $this->Html->link(__d('users', 'Reset Password'), ['action' => 'requestResetPassword']); + } + ?> +

+
+ + User->facebookLogin(); ?> + User->twitterLogin(); ?> + + Form->button(__d('Users', 'Login')); ?> + Form->end() ?> +
diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp new file mode 100644 index 000000000..46d6e0e6f --- /dev/null +++ b/src/Template/Users/profile.ctp @@ -0,0 +1,72 @@ + +
+

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

+

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

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

username) ?>

+
+

email) ?>

+ social_accounts)): + ?> +
+ + + + + + + + + + social_accounts as $socialAccount): + $linkText = empty(h($socialAccount->username)) ? __d('Users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) + ?> + + + + + + + +
Html->image( + $socialAccount->avatar, + ['width' => '90', 'height' => '90'] + ) ?> + provider) ?>Html->link( + $linkText, + $socialAccount->link, + ['target' => '_blank'] + ) ?>
+ +
+
+
diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp new file mode 100644 index 000000000..6544bb954 --- /dev/null +++ b/src/Template/Users/register.ctp @@ -0,0 +1,28 @@ + +
+ Form->create($user); ?> +
+ + Form->input('username'); + echo $this->Form->input('email'); + echo $this->Form->input('password'); + echo $this->Form->input('password_confirm', ['type' => 'password']); + echo $this->Form->input('first_name'); + echo $this->Form->input('last_name'); + echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); + ?> +
+ Form->button(__d('Users', 'Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/request_reset_password.ctp b/src/Template/Users/request_reset_password.ctp new file mode 100644 index 000000000..c8559a63c --- /dev/null +++ b/src/Template/Users/request_reset_password.ctp @@ -0,0 +1,10 @@ +
+ Flash->render('auth') ?> + Form->create('User') ?> +
+ + Form->input('reference') ?> +
+ Form->button(__d('Users', 'Submit')); ?> + Form->end() ?> +
diff --git a/src/Template/Users/resend_token_validation.ctp b/src/Template/Users/resend_token_validation.ctp new file mode 100644 index 000000000..c64c38684 --- /dev/null +++ b/src/Template/Users/resend_token_validation.ctp @@ -0,0 +1,22 @@ + +
+ Form->create($user); ?> +
+ + Form->input('reference', ['label' => __d('Users', 'Email or username')]); + ?> +
+ Form->button(__d('Users', 'Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp new file mode 100644 index 000000000..c2e29be82 --- /dev/null +++ b/src/Template/Users/social_email.ctp @@ -0,0 +1,21 @@ + +
+ Flash->render('auth') ?> + Form->create('User', ['action' => 'login']) ?> +
+ + Form->input('email') ?> +
+ Form->button(__d('Users', 'Submit')); ?> + Form->end() ?> +
diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp new file mode 100644 index 000000000..17df81728 --- /dev/null +++ b/src/Template/Users/view.ctp @@ -0,0 +1,108 @@ + +
+

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

id) ?>

+
+
+
+

id) ?>

+
+

username) ?>

+
+

email) ?>

+
+

first_name) ?>

+
+

last_name) ?>

+
+

token) ?>

+
+

api_token) ?>

+
+
+
+

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

+
+
+
+

token_expires) ?>

+
+

activation_date) ?>

+
+

tos_date) ?>

+
+

created) ?>

+
+

modified) ?>

+
+
+
+ diff --git a/src/Traits/RandomStringTrait.php b/src/Traits/RandomStringTrait.php new file mode 100644 index 000000000..6e7916729 --- /dev/null +++ b/src/Traits/RandomStringTrait.php @@ -0,0 +1,29 @@ +Html->link($this->Html->tag('i', '', [ + 'class' => 'fa fa-facebook' + ]) . __d('Users', 'Sign in with Facebook'), '/auth/facebook', [ + 'escape' => false, 'class' => 'btn btn-social btn-facebook' + ]); + } + + /** + * Twitter login link + * + * @return string + */ + public function twitterLogin() + { + return $this->Html->link($this->Html->tag('i', '', [ + 'class' => 'fa fa-twitter' + ]) . __d('Users', 'Sign in with Twitter'), '/auth/twitter', [ + 'escape' => false, 'class' => 'btn btn-social btn-twitter' + ]); + } + + /** + * Logout link + * + * @param null $message logout message info. + * @param array $options Array with option data. + * @return string + */ + public function logout($message = null, $options = []) + { + return $this->Html->link(empty($message) ? __d('Users', 'Logout') : $message, [ + 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout' + ], $options); + } + + /** + * Generate a link if the target url is authorized for the logged in user + * + * @param type $title link's title. + * @param type $url url that the user is making request. + * @param array $options Array with option data. + * @return string + */ + public function link($title, $url = null, array $options = []) + { + $event = new Event(UsersAuthComponent::EVENT_IS_AUTHORIZED, $this, ['url' => $url]); + $result = $this->_View->eventManager()->dispatch($event); + if ($result->result) { + $linkOptions = $options; + unset($linkOptions['before'], $linkOptions['after']); + return Hash::get($options, 'before') . $this->Html->link($title, $url, $linkOptions) . Hash::get($options, 'after'); + } + + return false; + } + + /** + * Welcome display + * @return mixed + */ + public function welcome() + { + $userId = $this->request->session()->read('Auth.User.id'); + if (empty($userId)) { + return; + } + + $profileUrl = '/profile/' . $userId; + $label = __d('Users', 'Welcome, {0}', $this->Html->link($this->request->session()->read('Auth.User.first_name'), $profileUrl)); + return $this->Html->tag('span', $label, ['class' => 'welcome']); + } +} diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php new file mode 100644 index 000000000..71ace2aa4 --- /dev/null +++ b/tests/Fixture/SocialAccountsFixture.php @@ -0,0 +1,131 @@ + ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'user_id' => ['type' => 'string', 'length' => 36, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'provider' => ['type' => 'integer', 'length' => 2, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], + 'username' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'reference' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'avatar' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'description' => ['type' => 'text', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'token' => ['type' => 'string', 'length' => 500, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'token_secret' => ['type' => 'string', 'length' => 500, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'token_expires' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'active' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => '1', 'comment' => '', 'precision' => null], + 'data' => ['type' => 'text', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => 1, + 'user_id' => 1, + 'provider' => 1, + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => 0, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => 2, + 'user_id' => 1, + 'provider' => 2, + 'username' => 'user-1-tw', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => 1, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => 3, + 'user_id' => 2, + 'provider' => 1, + 'username' => 'user-2-fb', + 'reference' => 'reference-2-1', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-reference-2-1', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => 1, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => 4, + 'user_id' => 3, + 'provider' => 2, + 'username' => 'user-2-tw', + 'reference' => 'reference-2-2', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-reference-2-2', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => 0, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => 5, + 'user_id' => 4, + 'provider' => 2, + 'username' => 'user-2-tw', + 'reference' => 'reference-2-2', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-reference-2-2', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => 0, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + ]; +} diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php new file mode 100644 index 000000000..145afbc4f --- /dev/null +++ b/tests/Fixture/UsersFixture.php @@ -0,0 +1,243 @@ + ['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], + 'tos_date' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'active' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => '0', 'comment' => '', 'precision' => null], + 'is_superuser' => ['type' => 'integer', 'length' => 1, 'unsigned' => false, 'null' => false, 'default' => '0', 'comment' => '', 'precision' => null, 'autoIncrement' => null], + 'role' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => 'user', 'comment' => '', 'precision' => null, 'fixed' => null], + 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => 1, + 'username' => 'user-1', + 'email' => 'user-1@test.com', + 'password' => '12345', + 'first_name' => 'first1', + 'last_name' => 'last1', + 'token' => 'xxx', + 'token_expires' => '2035-06-24 17:33:54', + 'api_token' => 'yyy', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 0, + 'is_superuser' => 1, + 'role' => 'admin', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 2, + 'username' => 'user-2', + 'email' => 'user-2@test.com', + 'password' => '12345', + 'first_name' => 'user', + 'last_name' => 'second', + 'token' => 'xxx', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'xxx', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 1, + 'is_superuser' => 1, + 'role' => 'admin', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 3, + 'username' => 'user-3', + 'email' => 'user-3@test.com', + 'password' => '12345', + 'first_name' => 'user', + 'last_name' => 'third', + 'token' => 'xxx', + 'token_expires' => '2015-06-20 17:33:54', + 'api_token' => 'xxx', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 0, + 'is_superuser' => 1, + 'role' => 'admin', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 4, + 'username' => 'user-4', + 'email' => '4@example.com', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'FirstName4', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 1, + 'is_superuser' => 4, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 5, + 'username' => 'user-5', + 'email' => 'test@example.com', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'first-user-5', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 0, + 'is_superuser' => 0, + 'role' => 'user', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 6, + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 1, + 'is_superuser' => 6, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 7, + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 1, + 'is_superuser' => 7, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 8, + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 1, + 'is_superuser' => 8, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 9, + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 1, + 'is_superuser' => 9, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => 10, + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'tos_date' => '2015-06-24 17:33:54', + 'active' => 1, + 'is_superuser' => 10, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + ]; +} diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php new file mode 100644 index 000000000..d3311ff44 --- /dev/null +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -0,0 +1,190 @@ +controller = $this->getMock( + 'Cake\Controller\Controller', + null, + [$request, $response] + ); + $registry = new ComponentRegistry($this->controller); + $this->rememberMe = new RememberMeAuthenticate($registry); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->rememberMe, $this->controller); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHappy() + { + $request = new Request('/'); + $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('check') + ->with('remember_me') + ->will($this->returnValue(true)); + $mockCookie + ->expects($this->once()) + ->method('read') + ->with('remember_me') + ->will($this->returnValue([ + 'id' => 1, + 'user_agent' => 'user-agent' + ])); + $registry = new ComponentRegistry($this->controller); + $registry->set('Cookie', $mockCookie); + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertEquals('user-1', $result['username']); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateBadUser() + { + $request = new Request('/'); + $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('check') + ->with('remember_me') + ->will($this->returnValue(true)); + $mockCookie + ->expects($this->once()) + ->method('read') + ->with('remember_me') + ->will($this->returnValue([ + 'id' => 'bad-user', + 'user_agent' => 'user-agent' + ])); + $registry = new ComponentRegistry($this->controller); + $registry->set('Cookie', $mockCookie); + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertFalse($result); + } + + + /** + * test + * + * @return void + */ + public function testAuthenticateBadAgent() + { + $request = new Request('/'); + $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('check') + ->with('remember_me') + ->will($this->returnValue(true)); + $mockCookie + ->expects($this->once()) + ->method('read') + ->with('remember_me') + ->will($this->returnValue([ + 'id' => 1, + 'user_agent' => 'bad-agent' + ])); + $registry = new ComponentRegistry($this->controller); + $registry->set('Cookie', $mockCookie); + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateNoCookie() + { + $request = new Request('/'); + $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('check') + ->with('remember_me') + ->will($this->returnValue(false)); + $mockCookie + ->expects($this->never()) + ->method('read'); + + $registry = new ComponentRegistry($this->controller); + $registry->set('Cookie', $mockCookie); + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertFalse($result); + } +} diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php new file mode 100644 index 000000000..90ea87f02 --- /dev/null +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -0,0 +1,565 @@ + 'admin', + 'plugin' => '*', + 'controller' => '*', + 'action' => '*', + ], + //specific actions allowed for the user role in Users plugin + [ + 'role' => 'user', + 'plugin' => 'Users', + 'controller' => 'Users', + 'action' => ['profile', 'logout'], + ], + //all roles allowed to Pages/display + [ + 'role' => '*', + 'plugin' => null, + 'controller' => ['Pages'], + 'action' => ['display'], + ], + ]; + + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + public function setUp() + { + $request = new Request(); + $response = new Response(); + + $this->controller = $this->getMock( + 'Cake\Controller\Controller', + null, + [$request, $response] + ); + $this->registry = new ComponentRegistry($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->simpleRbacAuthorize, $this->controller); + } + + /** + * @covers Users\Auth\SimpleRbacAuthorize::__construct + */ + public function testConstruct() + { + //don't autoload config + $this->simpleRbacAuthorize = new SimpleRbacAuthorize($this->registry, ['autoload_config' => false]); + $this->assertEmpty($this->simpleRbacAuthorize->config('permissions')); + } + + /** + * test + * + * @return void + */ + public function testLoadPermissions() + { + $this->simpleRbacAuthorize = $this->getMockBuilder('Users\Auth\SimpleRbacAuthorize') + ->disableOriginalConstructor() + ->getMock(); + $reflectedClass = new ReflectionClass($this->simpleRbacAuthorize); + $loadPermissions = $reflectedClass->getMethod('_loadPermissions'); + $loadPermissions->setAccessible(true); + $permissions = $loadPermissions->invoke($this->simpleRbacAuthorize, 'missing'); + $this->assertEquals($this->defaultPermissions, $permissions); + } + + /** + * @covers Users\Auth\SimpleRbacAuthorize::__construct + */ + public function testConstructMissingPermissionsFile() + { + $this->simpleRbacAuthorize = $this->getMock( + 'Users\Auth\SimpleRbacAuthorize', + null, + [$this->registry, ['autoload_config' => 'does-not-exist']] + ); + //we should have the default permissions + $this->assertEquals($this->defaultPermissions, $this->simpleRbacAuthorize->config('permissions')); + } + + protected function assertConstructorPermissions($instance, $config, $permissions) + { + $reflectedClass = new ReflectionClass($instance); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($this->simpleRbacAuthorize, $this->registry, $config); + + //we should have the default permissions + $resultPermissions = $this->simpleRbacAuthorize->config('permissions'); + $this->assertEquals($permissions, $resultPermissions); + } + + /** + * @covers Users\Auth\SimpleRbacAuthorize::__construct + */ + public function testConstructPermissionsFileHappy() + { + $permissions = [[ + 'controller' => 'Test', + 'action' => 'test' + ]]; + $className = 'Users\Auth\SimpleRbacAuthorize'; + $this->simpleRbacAuthorize = $this->getMockBuilder($className) + ->setMethods(['_loadPermissions']) + ->disableOriginalConstructor() + ->getMock(); + $this->simpleRbacAuthorize + ->expects($this->once()) + ->method('_loadPermissions') + ->with('permissions-happy') + ->will($this->returnValue($permissions)); + $this->assertConstructorPermissions($className, ['autoload_config' => 'permissions-happy'], $permissions); + } + + protected function preparePermissions($permissions) + { + $className = 'Users\Auth\SimpleRbacAuthorize'; + $simpleRbacAuthorize = $this->getMockBuilder($className) + ->setMethods(['_loadPermissions']) + ->disableOriginalConstructor() + ->getMock(); + $simpleRbacAuthorize->config('permissions', $permissions); + return $simpleRbacAuthorize; + } + + /** + * @dataProvider providerAuthorize + */ + public function testAuthorize($permissions, $user, $requestParams, $expected, $msg = null) + { + $this->simpleRbacAuthorize = $this->preparePermissions($permissions); + $request = new Request(); + $request->plugin = Hash::get($requestParams, 'plugin'); + $request->controller = $requestParams['controller']; + $request->action = $requestParams['action']; + + $result = $this->simpleRbacAuthorize->authorize($user, $request); + $this->assertSame($expected, $result, $msg); + } + + public function providerAuthorize() + { + return [ + 'happy-strict-all' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + 'allowed' => true, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-strict-all-deny' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + false + ], + 'happy-plugin-null-allowed-null' => [ + //permissions + [[ + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => null, + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-plugin-asterisk' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Any', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-plugin-asterisk-main-app' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => null, + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-role-asterisk' => [ + //permissions + [[ + 'role' => '*', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'any-role', + ], + //request + [ + 'plugin' => null, + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-controller-asterisk' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => '*', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-action-asterisk' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => '*', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'any' + ], + //expected + true + ], + 'happy-some-asterisk-allowed' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => '*', + 'action' => '*', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'any' + ], + //expected + true + ], + 'happy-some-asterisk-deny' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => '*', + 'action' => '*', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'any' + ], + //expected + false + ], + 'all-deny' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => '*', + 'controller' => '*', + 'action' => '*', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Any', + 'controller' => 'Any', + 'action' => 'any' + ], + //expected + false + ], + 'dasherized' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'TestTests', + 'action' => 'TestAction', + 'allowed' => true, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'tests', + 'controller' => 'test-tests', + 'action' => 'test-action' + ], + //expected + true + ], + 'happy-array' => [ + //permissions + [[ + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'happy-array' => [ + //permissions + [[ + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'three' + ], + //expected + false + ], + 'happy-callback-check-params' => [ + //permissions + [[ + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + 'allowed' => function ($user, $role, $request) { + return $user['id'] === 1 && $role = 'test' && $request->plugin == 'Tests'; + } + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'happy-callback-deny' => [ + //permissions + [[ + 'plugin' => ['*'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + 'allowed' => function ($user, $role, $request) { + return false; + } + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + ]; + } +} diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php new file mode 100644 index 000000000..234112a23 --- /dev/null +++ b/tests/TestCase/Auth/SuperuserAuthorizeTest.php @@ -0,0 +1,93 @@ +controller = $this->getMock( + 'Cake\Controller\Controller', + null, + [$request, $response] + ); + $registry = new ComponentRegistry($this->controller); + $this->superuserAuthorize = new SuperuserAuthorize($registry); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->superuserAuthorize, $this->controller); + } + + /** + * @covers Users\Auth\SuperuserAuthorize::authorize + */ + public function testAuthorizeIsSuperuser() + { + $user = [ + 'is_superuser' => true, + ]; + $request = new Request(); + $result = $this->superuserAuthorize->authorize($user, $request); + $this->assertTrue($result); + } + + /** + * @covers Users\Auth\SuperuserAuthorize::authorize + */ + public function testAuthorizeIsNotSuperuser() + { + $user = [ + 'is_superuser' => false, + ]; + $request = new Request(); + $result = $this->superuserAuthorize->authorize($user, $request); + $this->assertFalse($result); + } + + /** + * @covers Users\Auth\SuperuserAuthorize::authorize + */ + public function testAuthorizeWeirdUser() + { + $request = new Request(); + $user = 'non array'; + $result = $this->superuserAuthorize->authorize($user, $request); + $this->assertFalse($result); + } +} diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php new file mode 100644 index 000000000..44ca5bc99 --- /dev/null +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -0,0 +1,196 @@ +request = new Request('controller_posts/index'); + $this->request->params['pass'] = []; + $controller = new Controller($this->request); + $this->registry = new ComponentRegistry($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::salt(); + Security::salt('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::salt($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 Request('/'))->env('HTTP_USER_AGENT', 'user-agent'); + $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->rememberMeComponent->Auth->expects($this->once()) + ->method('redirectUrl') + ->will($this->returnValue('/login')); + $response = $this->rememberMeComponent->beforeFilter($event); + $this->assertSame(Router::url('/login', true), $response->location()); + } + + /** + * Test + * + * @return void + */ + public function testBeforeFilterNotIdentified() + { + $event = new Event('event'); + $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $this->rememberMeComponent->Auth->expects($this->at(0)) + ->method('user'); + $this->rememberMeComponent->Auth->expects($this->at(1)) + ->method('identify'); + + $this->assertNull($this->rememberMeComponent->beforeFilter($event)); + } + + /** + * Test + * + * @return void + */ + public function testBeforeFilterUserLoggedIn() + { + $event = new Event('event'); + $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $this->rememberMeComponent->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue([ + 'id' => 1, + ])); + $this->assertNull($this->rememberMeComponent->beforeFilter($event)); + } +} diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php new file mode 100644 index 000000000..4bd8a1b59 --- /dev/null +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -0,0 +1,126 @@ +backupUsersConfig = Configure::read('Users'); + + Router::scope('/', function ($routes) { + $routes->fallbacks('InflectedRoute'); + }); + + Router::plugin('Users', function ($routes) { + $routes->fallbacks('InflectedRoute'); + }); + + Router::scope('/auth', function ($routes) { + $routes->connect( + '/*', + ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit'] + ); + }); + Router::connect('/a/validate/*', [ + 'admin' => false, + 'plugin' => 'Users', + 'controller' => 'SocialAccounts', + 'action' => 'resendValidation' + ]); + + Security::salt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); + Configure::write('App.namespace', 'Users'); + $this->request = $this->getMock('Cake\Network\Request', ['is', 'method']); + $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); + $this->response = $this->getMock('Cake\Network\Response', ['stop']); + $this->Controller = new Controller($this->request, $this->response); + $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('Users\Controller\Component\UsersAuthComponent', $this->Controller->UsersAuth); + } + + /** + * Test initialize with not rememberMe component needed + * + */ + public function testInitializeNoRequiredRememberMe() + { + Configure::write('Users.RememberMe.active', false); + $class = '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->once()) + ->method('_loadSocialLogin'); + $this->Controller->UsersAuth->expects($this->never()) + ->method('_loadRememberMe'); + $this->Controller->UsersAuth->initialize([]); + } +} diff --git a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php new file mode 100644 index 000000000..8d371c7fd --- /dev/null +++ b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php @@ -0,0 +1,42 @@ +controller = $this->getMock( + 'Cake\Controller\Controller', + ['header', 'redirect', 'render', '_stop'] + ); + $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\CustomUsersTableTrait'); + } + + public function tearDown() + { + parent::tearDown(); + } + + public function testGetUsersTable() + { + $table = $this->controller->Trait->getUsersTable(); + $this->assertEquals('Users.Users', $table->registryAlias()); + $newTable = new Table(); + $this->controller->Trait->setUsersTable($newTable); + $this->assertSame($newTable, $this->controller->Trait->getUsersTable()); + } +} diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php new file mode 100644 index 000000000..86b0b78b5 --- /dev/null +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -0,0 +1,126 @@ +Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') + ->setMethods(['dispatchEvent', 'isStopped', 'redirect']) + ->getMockForTrait(); + $this->Trait->request = $request; + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * mock utility + * + * @return void + */ + protected function _mockDispatchEvent(Event $event) + { + $this->Trait->expects($this->any()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + } + + /** + * test + * + * @return void + */ + public function testLoginHappy() + { + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $user = [ + 'id' => 1, + ]; + $redirectLoginOK = '/'; + $this->Trait->Auth->expects($this->at(0)) + ->method('identify') + ->will($this->returnValue($user)); + $this->Trait->Auth->expects($this->at(1)) + ->method('setUser') + ->with($user); + $this->Trait->Auth->expects($this->at(2)) + ->method('redirectUrl') + ->will($this->returnValue($redirectLoginOK)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with($redirectLoginOK); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testLogout() + { + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['logout']) + ->disableOriginalConstructor() + ->getMock(); + $redirectLogoutOK = '/'; + $this->Trait->Auth->expects($this->once()) + ->method('logout') + ->will($this->returnValue($redirectLogoutOK)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with($redirectLogoutOK); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['success']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('You\'ve successfully logged out'); + $this->Trait->logout(); + } +} diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php new file mode 100644 index 000000000..249265fa6 --- /dev/null +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -0,0 +1,47 @@ +controller = $this->getMock( + 'Cake\Controller\Controller', + ['header', 'redirect', 'render', '_stop'] + ); + $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\PasswordManagementTrait'); + } + + public function tearDown() + { + parent::tearDown(); + } + + public function testChangePassword() + { + $this->markTestIncomplete(); + } + + public function testResetPassword() + { + $this->markTestIncomplete(); + } + + public function testRequestResetPassword() + { + $this->markTestIncomplete(); + } +} diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php new file mode 100644 index 000000000..0df9ee644 --- /dev/null +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -0,0 +1,37 @@ +controller = $this->getMock( + '\Cake\Controller\Controller', + ['header', 'redirect', 'render', '_stop'] + ); + $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\ProfileTrait'); + } + + public function tearDown() + { + parent::tearDown(); + } + + public function testProfile() + { + $this->markTestIncomplete(); + } +} diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php new file mode 100644 index 000000000..00e468bd0 --- /dev/null +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -0,0 +1,47 @@ +controller = $this->getMock( + '\Cake\Controller\Controller', + ['header', 'redirect', 'render', '_stop'] + ); + $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\RegisterTrait'); + } + + public function tearDown() + { + parent::tearDown(); + } + + public function testRegisterTest() + { + $this->markTestIncomplete(); + } + + public function testValidateTest() + { + $this->markTestIncomplete(); + } + + public function testResendTokenValidation() + { + $this->markTestIncomplete(); + } +} diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php new file mode 100644 index 000000000..a7e3708a3 --- /dev/null +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -0,0 +1,128 @@ +controller = $this->getMock( + 'Cake\Controller\Controller', + ['header', 'redirect', 'render', '_stop'] + ); + $this->controller->Trait = $this->getMockForTrait( + 'Users\Controller\Traits\SocialTrait', + [], + '', + true, + true, + true, + ['_getOpauthInstance', 'redirect', '_generateOpauthCompleteUrl'] + ); + } + + public function tearDown() + { + parent::tearDown(); + } + + /** + * Test opauthInit with no callback + * + */ + public function testOpauthInitTest() + { + $Opauth = $this->getMock('Opauth\Opauth\Opauth', ['run'], [], '', false); + $Opauth->expects($this->once()) + ->method('run') + ->will($this->returnValue('response')); + $this->controller->Trait->expects($this->once()) + ->method('_getOpauthInstance') + ->will($this->returnValue($Opauth)); + $this->controller->Trait->opauthInit(); + } + + /** + * Test opauthInit with callback + * + */ + public function testOpauthInitTestCallback() + { + $Opauth = $this->getMock('Opauth\Opauth\Opauth', ['run'], [], '', false); + $Opauth->expects($this->once()) + ->method('run') + ->will($this->returnValue('response')); + $session = $this->getMock('Cake\Network\Session', ['write', 'check']); + $session->expects($this->once()) + ->method('write') + ->with(Configure::read('Users.Key.Session.social'), 'response'); + $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session']); + $this->controller->Trait->request->expects($this->once()) + ->method('session') + ->will($this->returnValue($session)); + $this->controller->Trait->expects($this->once()) + ->method('_getOpauthInstance') + ->will($this->returnValue($Opauth)); + $this->controller->Trait->expects($this->once()) + ->method('_generateOpauthCompleteUrl') + ->will($this->returnValue('url')); + $this->controller->Trait->expects($this->once()) + ->method('redirect') + ->with('url'); + $this->controller->Trait->opauthInit('callback'); + } + + /** + * Test socialEmail + * + */ + public function testSocialEmail() + { + $session = $this->getMock('Cake\Network\Session', ['check']); + $session->expects($this->once()) + ->method('check') + ->with('Users.social') + ->will($this->returnValue('social_key')); + + $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session']); + $this->controller->Trait->request->expects($this->once()) + ->method('session') + ->will($this->returnValue($session)); + + $this->controller->Trait->socialEmail(); + } + + /** + * Test socialEmail + * + * @expectedException \Cake\Network\Exception\NotFoundException + */ + public function testSocialEmailInvalid() + { + $session = $this->getMock('Cake\Network\Session', ['check']); + $session->expects($this->once()) + ->method('check') + ->with('Users.social') + ->will($this->returnValue(null)); + + $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session']); + $this->controller->Trait->request->expects($this->once()) + ->method('session') + ->will($this->returnValue($session)); + + $this->controller->Trait->socialEmail(); + } +} diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php new file mode 100644 index 000000000..f929c563b --- /dev/null +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -0,0 +1,71 @@ +Trait = $this->getMockBuilder('Users\Controller\Traits\UserValidationTrait') + ->setMethods(['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable']) + ->getMockForTrait(); + $this->Trait->request = $request; + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * test + * + * @return void + */ + public function testValidateHappyToken() + { + $usersTableMock = $this->getMockBuilder('Users\Model\Table\UsersTable') + ->setMethods(['validate']) + ->disableOriginalConstructor() + ->getMock(); + $usersTableMock->expects($this->once()) + ->method('validate') + ->with('token', 'activateUser') + ->will($this->returnValue(true)); + $this->Trait->expects($this->once()) + ->method('getUsersTable') + ->will($this->returnValue($usersTableMock)); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['success']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('User account validated successfully'); + $this->Trait->validate('email', 'token'); + } +} diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php new file mode 100644 index 000000000..c594367a2 --- /dev/null +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -0,0 +1,104 @@ +User = new User(); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->User); + + parent::tearDown(); + } + + /** + * Test tokenExpired method + * + * @return void + */ + public function testTokenExpiredEmpty() + { + $this->User->token_expires = null; + $isExpired = $this->User->tokenExpired(); + $this->assertTrue($isExpired); + } + + /** + * Test tokenExpired method + * + * @return void + */ + public function testTokenExpiredNotYet() + { + $this->User->token_expires = '-1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertTrue($isExpired); + } + + /** + * Test tokenExpired method + * + * @return void + */ + public function testTokenExpired() + { + $this->User->token_expires = '+1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertFalse($isExpired); + } + + public function testPasswordsAreEncrypted() + { + $pw = 'password'; + $this->User->password = $pw; + $this->assertTrue((new DefaultPasswordHasher)->check($pw, $this->User->password)); + } + + public function testConfirmPasswordsAreEncrypted() + { + $pw = 'password'; + $this->User->confirm_password = $pw; + $this->assertTrue((new DefaultPasswordHasher)->check($pw, $this->User->confirm_password)); + } + + public function testCheckPassword() + { + $pw = 'password'; + $this->assertTrue($this->User->checkPassword($pw, (new DefaultPasswordHasher)->hash($pw))); + $this->assertFalse($this->User->checkPassword($pw, 'fail')); + } + + public function testGetAvatar() + { + $this->assertNull($this->User->avatar); + $avatar = 'first-avatar'; + $this->User->social_accounts = [ + ['avatar' => 'first-avatar'], + ['avatar' => 'second-avatar'] + ]; + $this->assertSame($avatar, $this->User->avatar); + } +} diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php new file mode 100644 index 000000000..09c70e944 --- /dev/null +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -0,0 +1,198 @@ + 'Users\Model\Table\SocialAccountsTable' + ]; + $this->SocialAccounts = TableRegistry::get('SocialAccounts', $config); + $this->fullBaseBackup = Router::fullBaseUrl(); + Router::fullBaseUrl('http://users.test'); + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->SocialAccounts); + Router::fullBaseUrl($this->fullBaseBackup); + Email::dropTransport('test'); + + parent::tearDown(); + } + + /** + * Test validateEmail method + * + * @return void + */ + public function testValidateEmail() + { + $token = 'token-1234'; + $result = $this->SocialAccounts->validateAccount(1, 'reference-1-1234', $token); + $this->assertTrue($result->active); + $this->assertEquals($token, $result->token); + } + + /** + * Test validateEmail method + * + * @expectedException \Cake\Datasource\Exception\RecordNotFoundException + */ + public function testValidateEmailInvalidToken() + { + $this->SocialAccounts->validateAccount(1, 'reference-1234', 'invalid-token'); + } + + /** + * Test validateEmail method + * + * @expectedException \Cake\Datasource\Exception\RecordNotFoundException + */ + public function testValidateEmailInvalidUser() + { + $this->SocialAccounts->validateAccount(1, 'invalid-user', 'token-1234'); + } + + /** + * Test validateEmail method + * + * @expectedException \Users\Exception\AccountAlreadyActiveException + */ + public function testValidateEmailActiveAccount() + { + $this->SocialAccounts->validateAccount(2, 'reference-1-1234', 'token-1234'); + } + + /** + * testAfterSaveSocialNotActiveUserNotActive + * don't send email, user is not active + * + * @return void + */ + public function testAfterSaveSocialNotActiveUserNotActive() + { + $event = new Event('eventName'); + $entity = $this->SocialAccounts->find()->first(); + $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); + } + + /** + * testAfterSaveSocialNotActiveUserActive + * send email here, social account is not active, + * and user is active we need to link the account + * + * @return void + */ + public function testAfterSaveSocialNotActiveUserActive() + { + $event = new Event('eventName'); + $entity = $this->SocialAccounts->findById(5)->first(); + $this->SocialAccounts->Users = $this->getMockForModel('Users.Users', ['getEmailInstance']); + $this->SocialAccounts->Users->expects($this->once()) + ->method('getEmailInstance') + ->will($this->returnValue($this->Email)); + $result = $this->SocialAccounts->afterSave($event, $entity, []); + $this->assertTextContains('Subject: FirstName4, Your social account validation link', $result['headers']); + unset($this->SocialAccounts->Users); + } + + /** + * testAfterSaveSocialActiveUserNotActive + * social account is active, don't send email + * + * @return void + */ + public function testAfterSaveSocialActiveUserNotActive() + { + $event = new Event('eventName'); + $entity = $this->SocialAccounts->findById(2)->first(); + $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); + } + + /** + * testAfterSaveSocialActiveUserActive + * social account is active, don't send email + * + * @return void + */ + public function testAfterSaveSocialActiveUserActive() + { + $event = new Event('eventName'); + $entity = $this->SocialAccounts->findById(3)->first(); + $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); + } + + /** + * Test sendSocialValidationEmail method + * + * @return void + */ + public function testSendSocialValidationEmail() + { + $user = $this->SocialAccounts->find()->contain('Users')->first(); + $this->Email->emailFormat('both'); + $result = $this->SocialAccounts->sendSocialValidationEmail($user, $user->user, $this->Email); + $this->assertTextContains('From: test@example.com', $result['headers']); + $this->assertTextContains('To: user-1@test.com', $result['headers']); + $this->assertTextContains('Subject: first1, Your social account validation link', $result['headers']); + $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Hi first1, + +Please copy the following address in your web browser to activate your social login http://users.test/users/social-accounts/validate-account/1/reference-1-1234/token-1234 +Thank you, +', $result['message']); + $this->assertTextContains('Hi first1,', $result['message']); + $this->assertTextContains('Activate your social login here', $result['message']); + $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/1/reference-1-1234/token-1234', $result['message']); + } +} diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php new file mode 100644 index 000000000..4885b27a7 --- /dev/null +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -0,0 +1,467 @@ +Users = TableRegistry::get('Users.Users'); + $this->fullBaseBackup = Router::fullBaseUrl(); + Router::fullBaseUrl('http://users.test'); + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->Users); + Router::fullBaseUrl($this->fullBaseBackup); + Email::dropTransport('test'); + + parent::tearDown(); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterNoValidateEmail() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); + $this->assertTrue($result->active); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterEmptyUser() + { + $user = []; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertFalse($result); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterValidateEmail() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertNotEmpty($result); + $this->assertFalse($result->active); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testValidateRegisterTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + } + + /** + * Test register method + testValidateRegisterValidateEmail */ + public function testValidateRegisterNoTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); + $this->assertNotEmpty($result); + } + + /** + * Test ActivateUser method + * + * @return void + */ + public function testActivateUser() + { + $user = $this->Users->find()->where(['id' => 1])->first(); + $result = $this->Users->activateUser($user); + $this->assertTrue($result->active); + } + + /** + * Test resetToken + * + */ + public function testResetToken() + { + $user = $this->Users->findAllByUsername('user-1')->first(); + $result = $this->Users->resetToken('user-1', [ + 'expiration' => 3600, + 'checkActive' => true, + ]); + $this->assertNotEmpty($result->token); + $this->assertNotEquals($user->token, $result->token); + $this->assertNotEmpty($result->token_expires); + $this->assertEmpty($result->activation_date); + $this->assertFalse($result->active); + } + + /** + * Test resetToken + * + * @expectedException InvalidArgumentException + */ + public function testResetTokenWithNullParams() + { + $this->Users->resetToken(null); + } + + /** + * Test resetToken + * + * @expectedException \Users\Exception\UserNotFoundException + */ + public function testResetTokenNonExistentUser() + { + $this->Users->resetToken('user-not-found', [ + 'expiration' => 3600 + ]); + } + + /** + * Test resetToken + * + * @expectedException \Users\Exception\UserAlreadyActiveException + */ + public function testResetTokenUserAlreadyActive() + { + $this->Users->resetToken('user-4', [ + 'expiration' => 3600, + 'checkActive' => true, + ]); + } + + public function testSocialLogin() + { + $raw = [ + 'id' => 'reference-2-1', + 'first_name' => 'User 2', + 'gender' => 'female', + 'verified' => 1, + 'user_email' => 'hello@test.com', + ]; + $data = new Response(SocialAccountsTable::PROVIDER_FACEBOOK, $raw); + $data->setData('uid', 'id'); + $options = [ + 'use_email' => 1, + 'validate_email' => 1, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertEquals('user-2@test.com', $result->email); + $this->assertTrue($result->active); + } + + /** + * Test socialLogin + * + * @expectedException \Users\Exception\AccountNotActiveException + */ + public function testSocialLoginInactiveAccount() + { + $raw = [ + 'id' => 'reference-2-2', + 'first_name' => 'User 2', + 'gender' => 'female', + 'verified' => 1, + 'user_email' => 'hello@test.com', + ]; + $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); + $data->setData('uid', 'id'); + $options = [ + 'use_email' => 1, + 'validate_email' => 1, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertEquals('user-2@test.com', $result->email); + $this->assertFalse($result->active); + } + + /** + * Test socialLogin + * + * @expectedException InvalidArgumentException + */ + public function testSocialLoginddCreateNewAccountWithNoCredentials() + { + $raw = [ + 'id' => 'reference-not-existing', + 'first_name' => 'Not existing user', + 'gender' => 'male', + 'user_email' => 'user@test.com', + ]; + $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); + $data->setData('uid', 'id'); + $options = [ + 'use_email' => 0, + 'validate_email' => 1, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertFalse($result); + } + + /** + * Test socialLogin + * + */ + public function testSocialLoginCreateNewAccount() + { + $raw = [ + 'id' => 'no-existing-reference', + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'gender' => 'male', + 'user_email' => 'user@test.com', + ]; + + $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); + $data->setData('uid', 'id'); + $data->setData('info.first_name', 'first_name'); + $data->setData('info.last_name', 'last_name'); + $data->email = 'username@test.com'; + $data->credentials = [ + 'token' => 'token', + 'token_secret' => 'secret', + 'token_expires' => '' + ]; + $options = [ + 'use_email' => 0, + 'validate_email' => 0, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertNotEmpty($result); + $this->assertEquals('no-existing-reference', $result->social_accounts[0]->reference); + $this->assertEquals(1, count($result->social_accounts)); + $this->assertEquals('username', $result->username); + $this->assertEquals('First Name', $result->first_name); + $this->assertEquals('Last Name', $result->last_name); + } + + /** + * Test sendValidationEmail method + * + * @return void + */ + public function testSendValidationEmail() + { + $user = $this->Users->newEntity([ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]); + $this->Email->template('Users.validation') + ->emailFormat('both'); + + $result = $this->Users->sendValidationEmail($user, $this->Email); + $this->assertTextContains('From: test@example.com', $result['headers']); + $this->assertTextContains('To: test@example.com', $result['headers']); + $this->assertTextContains('Subject: FirstName, Your account validation link', $result['headers']); + $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Hi FirstName, + +Please copy the following address in your web browser http://users.test/users/users/activate/12345 +Thank you, +', $result['message']); + $this->assertTextContains('Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + + + + Email/html + + +

+Hi FirstName, +

+

+ Activate your account here +

+

+ If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/activate/12345

+

+ Thank you, +

+ + +', $result['message']); + } + + /** + * Test method + * + * @return void + */ + public function testSendResetPasswordEmail() + { + $user = $this->Users->newEntity([ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]); + $this->Email->template('Users.reset_password') + ->emailFormat('both'); + + $result = $this->Users->sendResetPasswordEmail($user, $this->Email); + $this->assertTextContains('From: test@example.com', $result['headers']); + $this->assertTextContains('To: test@example.com', $result['headers']); + $this->assertTextContains('Subject: FirstName, Your reset password link', $result['headers']); + $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Hi FirstName, + +Please copy the following address in your web browser http://users.test/users/users/activate/12345 +Thank you, +', $result['message']); + $this->assertTextContains('Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + + + + Email/html + + +

+Hi FirstName, +

+

+ Reset your password here +

+

+ If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/activate/12345

+

+ Thank you, +

+ + +', $result['message']); + } + + /** + * testGetEmailInstance + * + * @return void + */ + public function testGetEmailInstance() + { + $email = $this->Users->getEmailInstance(); + $this->assertInstanceOf('Cake\Network\Email\Email', $email); + $this->assertEquals([ + 'template' => 'Users.validation', + 'layout' => 'default' + ], $email->template()); + } + + /** + * testGetEmailInstanceOverrideEmail + * + * @return void + */ + public function testGetEmailInstanceOverrideEmail() + { + $email = new Email(); + $email->template('another_template'); + $email = $this->Users->getEmailInstance($email); + $this->assertInstanceOf('Cake\Network\Email\Email', $email); + $this->assertEquals([ + 'template' => 'another_template', + 'layout' => 'default' + ], $email->template()); + } +} diff --git a/tests/TestCase/Traits/RandomStringTraitTest.php b/tests/TestCase/Traits/RandomStringTraitTest.php new file mode 100644 index 000000000..eaeb3596c --- /dev/null +++ b/tests/TestCase/Traits/RandomStringTraitTest.php @@ -0,0 +1,43 @@ +Trait = $this->getMockForTrait('Users\Traits\RandomStringTrait'); + } + + public function tearDown() + { + parent::tearDown(); + } + + public function testRandomString() + { + $result = $this->Trait->randomString(); + $this->assertEquals(10, strlen($result)); + + $result = $this->Trait->randomString(30); + $this->assertEquals(30, strlen($result)); + + $result = $this->Trait->randomString('-300'); + $this->assertEquals(10, strlen($result)); + + $result = $this->Trait->randomString('text'); + $this->assertEquals(10, strlen($result)); + } +} diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php new file mode 100644 index 000000000..9026a346f --- /dev/null +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -0,0 +1,195 @@ +User = new UserHelper($view); + $this->request = new \Cake\Network\Request(); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->User); + + parent::tearDown(); + } + + /** + * Test facebookLogin + * + * @return void + */ + public function testFacebookLogin() + { + $result = $this->User->facebookLogin(); + $expected = 'Sign in with Facebook'; + $this->assertEquals($expected, $result); + } + + /** + * Test twitterLogin + * + * @return void + */ + public function testTwitterLoginEnabled() + { + $result = $this->User->twitterLogin(); + $expected = 'Sign in with Twitter'; + $this->assertEquals($expected, $result); + } + + /** + * Test twitterLogin + * + * @return void + */ + public function testLogout() + { + $result = $this->User->logout(); + $expected = 'Logout'; + $this->assertEquals($expected, $result); + } + + /** + * Test twitterLogin + * + * @return void + */ + public function testLogoutDifferentMessage() + { + $result = $this->User->logout('Sign Out'); + $expected = 'Sign Out'; + $this->assertEquals($expected, $result); + } + + /** + * Test twitterLogin + * + * @return void + */ + public function testLogoutWithOptions() + { + $result = $this->User->logout('Sign Out', ['class' => 'logout']); + $expected = 'Sign Out'; + $this->assertEquals($expected, $result); + } + + /** + * Test link + * + * @return void + */ + public function testLinkFalse() + { + $link = $this->User->link('title', ['controller' => 'noaccess']); + $this->assertSame(false, $link); + } + + /** + * Test link + * + * @return void + */ + public function testLinkAuthorized() + { + $view = new View(); + $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') + ->setMethods(['dispatch']) + ->getMock(); + $view->eventManager($eventManagerMock); + $this->User = new UserHelper($view); + $result = new Event('dispatch-result'); + $result->result = true; + $eventManagerMock->expects($this->once()) + ->method('dispatch') + ->will($this->returnValue($result)); + + $link = $this->User->link('title', '/', ['before' => 'before_', 'after' => '_after', 'class' => 'link-class']); + $this->assertSame('before_title_after', $link); + } + + /** + * Test link + * + * @return void + */ + public function testWelcome() + { + $session = $this->getMock('Cake\Network\Session', ['read']); + $session->expects($this->at(0)) + ->method('read') + ->with('Auth.User.id') + ->will($this->returnValue(2)); + + $session->expects($this->at(1)) + ->method('read') + ->with('Auth.User.first_name') + ->will($this->returnValue('david')); + + $this->User->request = $this->getMock('Cake\Network\Request', ['session']); + $this->User->request->expects($this->any()) + ->method('session') + ->will($this->returnValue($session)); + + $expected = 'Welcome, david'; + $result = $this->User->welcome(); + $this->assertEquals($expected, $result); + } + + /** + * Test link + * + * @return void + */ + public function testWelcomeNotLoggedInUser() + { + $session = $this->getMock('Cake\Network\Session', ['read']); + $session->expects($this->at(0)) + ->method('read') + ->with('Auth.User.id') + ->will($this->returnValue(null)); + + $this->User->request = $this->getMock('Cake\Network\Request', ['session']); + $this->User->request->expects($this->any()) + ->method('session') + ->will($this->returnValue($session)); + + $result = $this->User->welcome(); + $this->assertEmpty($result); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 000000000..a5151b4d1 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,30 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0 class loader + * + * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-0 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 000000000..7a91153b0 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + array($baseDir . '/tests/Fixture'), + 'Users\\Test\\' => array($baseDir . '/tests'), + 'Users\\' => array($baseDir . '/src'), + 'Cake\\Test\\' => array($vendorDir . '/cakephp/cakephp/tests'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 000000000..013eec028 --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,50 @@ + $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + return $loader; + } +} + +function composerRequirecba08b9a106a578f9888716a0bffe4ed($file) +{ + require $file; +} diff --git a/webroot/empty b/webroot/empty new file mode 100644 index 000000000..e69de29bb diff --git a/webroot/img/avatar_placeholder.png b/webroot/img/avatar_placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..5a29e1a2db3f5977b3f36c5ca633d9608db66288 GIT binary patch literal 4015 zcmXAsc{J2(7{}cTLe^9mKN`ES59wy#3M0b|)%yd$9v9mzTfY8&U4=PkN5ec+E|BzQ4ej_m$u{k~u!a*yFH1Tg+Es_d2+|g#YxF`f+Sz%R)#6p%ZX8bWg1qb0wZ;`q2%7&$E9CTJKnC5Sv|abh@|Aj%43YMQb+5Q5Swqf<7gbi{eDj`IUSQ6g=WOspr$8gzbJ z^AVhsD0|m-6EeLnU!xSA1-pi#lAQZ^c4;1~M#~*`3Bx)=uhnYg7MAV9AT}r$)E`)Y zGvkltPCL&>an-Fkj)&hD#sTA$!3*d43=b{vy1CSdfkS)?In+f9GM;!+%L1A@U*ERt z2@UuW*1$Sf*tM!Ex0wO?%Hw~BZgpBZV zO2g^HlVo0K%{u~(XLejlWy}Jp{?2`%o;I<)ZuwkIWi#MNFjp%=!cH_8{dQ(sLq(Xo zxjo{_0~K0|iCdA$<;i?pt{_|f4DSXc>Ck+J@6V;YrhtnPw)oNZ1#2MYlJ5LeB&Vgw zND4b5!U946PLFmuZg6ek_)Fp|8xDeiRp@sCk1kWU`*I2qEo=4KuRMph6%wciy<6gH z4@;EUaYlQX*O1Qug^C%jC6r7}TdcTFHFTi_L84mU8GI{1J<(LNzSr1yT& zIb@8y&qYL=G@rU~&uqBkNOq73{TUqUuP(M?@#&;iLjGh9SJC>ZYXqyKNeUasoRewF z1~Q-SIWX=#JTWEm=w)wgZ4=@|IeCXW=2$ySo)$^mX`X54skYznaAiJ*Tg4pnE=0`q z2KihU{cc^BK01vknv$fSD}H1?nw6cnbo>2y#hovMweWrSmtpc@fYmC;<=`ZFt0%}C z2v^OIroqMIxjxHoMq^=bso2ra!!~)3EJi8z3Cl;GGP6Xr`xnhZL)es>zpBVlUGbS%=~ zC|cn6DYNTx(czXT1zJ)wJAb;(aO=csX%;iX6ki%4F|vG5-?vitZtMl4`?y#w?F&ZJ z51SBkN14JAAjj9l_N2F;)Lg`(2Qo_xQ6p8xq}Y?^938-s`Pc?v-sC z?Dbs+H0dxGW^#=$truRFS8@NBE|BFS_i|ld<_5 z(5&B5TZ#gFi$$J0TXT0_r5FHVZ0s6hw^y&7b+!X;?Y(37qHH})QOH7P(4U0ru;mPHpW zVnnJ6urwajW>3Z|Qh#+4;&L9F&Dzi#Cm8RTDSi8puHBj0y7yk%pX_YNWpV04Z1UI7 zd-aXURnQn?1wnb1>C8vpE$;p-1?RaKYLswTr6%!woKE~3a6U>ae4JBdj8i<#{ z@|C|bc!K0i7+f9px2}{}Y2=QDcOTtI;yyESO_^x+diI&Gm(+XVm2)OTn}ofM1Y#_0n9k!j~XHl8^j&HOWR(`TtJ3u_s=X!$oq9?g5DyfG!Rjs40` z%pf{-Cf27;`vq}a523foAO4&ex)Km$5Tz12KiEQ1X)2%S+^gvAXdu2|pXgfjw06pY zps4!oeXlIu(ewrZa z_o)@_fUfoHE4ytc)P(Ch_i@%tB8Bs&ME1n?&Cr7U-zEikCu@OqLE&w2Z86o%O}|~@ zbJO4_k`vKq_6%Ck1BdP)Y&Jzy%@J|wA5q_KF&*Pp;tKlaThL?a;fdG#be0Y^vTj$v zmv;7L_z?*_a#ZK5znOF5h|T5CEwh1QOyQxzqicTIm$6PHmSd2m4)K(J5w+HQwxoBrTwx3e)$OeZRcu4`2lm*-?)QCe^-Op?+yPI8GoRCl z4zh30cdDTB6q+1;yb{W)?x94=DCG`{Yx12h_IR2|dqL#Cz{yz0-rOda{IfsynlNuZ z-lxNCaWuJ~3ud&p@>Os^V{tLLuw+XcyX z_+tSy&Jz3}*LknxklBuPzLGds{ehSX?{{Ee41VhyV1drurxZ?U9z~V~N;vJCQjKUpN@YX76IQdn}6Kt$FIaeX=h))m9>lvU+RZ~p8 zl+nRv!g52^jY=ZOqQ6F@L4qSV=xvk(AEoO*AX6MANfZ+uWK8aQVP03b3ENo*>Dm(| zKb?zdE(SjY4;`y$q2$$M7LX}v3U_lcCi(CTXGfDE5DZ{lZ@|&#l5?Bf=`?-bAZ_FW zTt{QHGtz(li6>2{--RJ~W3rVjKs(=vDX0byw#4Iovgn3`3LiCSI0SkJ)Lf&}(q?%r z7|sri(@EhdBa*W(>tQ<>{;QNE{-Bu>&t0t~c4o-VKXAa6VQQ!V#OF6t(2Azb@7?g< z=pOf*DJHe2G$eqZYdAW88IE9E6_kN4ILMZC+t6_Ru8e-{WCKhexN=ZRwqV$+W-(W% zXheA7Gka;8L{2lsl)IGlq3^&nS+q2hlmJ4%s<1ka=24v2aE@Z$IKry=Q(QA;!S=8j z0}_SY3D0oG^vI(V+d+q(Qc~u@FbzL`OkS<0oQy(3QxBWVaIWDnp^5*7SVB=qu>y|! zCMmJpD*+^3YQ@h;SRxd5XfvEJ$;gTLs*E-mi%oEHF|EuXdDHh8*@Ne8v(SC?)!%pL&9jvX}7s7I?7G6n?$bmu7b!RN(=W&?Rn-cU4D z3myP4IQyv2oc>n6K2lK$M{ZrLr5%403vm;b=ChmRO8+4`8sg85Pk5CSGOofK%xHPygMlu zPp7DYY%Hcv6N- ztsj59irK^R??xM{IPD#3}KXtn+#iyoin8tglpIwVdH;gfdJzEOLxKu%rvb(gPcT% zPN01Lhs*Y0obpg;l7h+!6VzC7X5L)pzhs(Eo}uZXQfO;)wNb3~_`dNS$9o?$<^Lsd N^UK!8wU;~-{{ee?`}F_- literal 0 HcmV?d00001 From 8b4bbace3091af767ec674754f1469478a38757e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 5 Aug 2015 23:20:25 +0100 Subject: [PATCH 0144/1476] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9ee43700e..126b7bff6 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ CakeDC Users Plugin [![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) +IMPORTANT: 3.x version is ALPHA status now, we are improving and testing it now. + The **Users** plugin is back! It covers the following features: From 2af0e74dbb5079439827680e0500bf8f49010604 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Wed, 5 Aug 2015 17:33:10 -0500 Subject: [PATCH 0145/1476] Update .travis.yml --- .travis.yml | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index f65bc23cc..1aea05fd3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,40 +1,48 @@ language: php php: - - 5.3 - 5.4 - 5.5 + - 5.6 -env: - global: - - PLUGIN_NAME=Users - - DB=mysql - - REQUIRE="phpunit/phpunit:3.7.31" +sudo: false +env: matrix: - - DB=mysql CAKE_VERSION=2.6 + - DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' + - DB=pgsql db_dsn='postgres://postgres@127.0.0.1/cakephp_test' + - DB=sqlite db_dsn='sqlite:///:memory:' + + global: + - DEFAULT=1 matrix: + fast_finish: true + include: - - php: 5.3 - env: - - CAKE_VERSION=2.6 - php: 5.4 - env: - - CAKE_VERSION=2.6 - - php: 5.5 - env: - - CAKE_VERSION=2.6 + env: PHPCS=1 DEFAULT=0 + + - php: 5.4 + env: COVERALLS=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' before_script: - - git clone https://github.com/steinkel/travis.git --depth 1 ../travis - - ../travis/before_script.sh + - composer self-update + - composer install --prefer-dist --no-interaction -script: - - ../travis/script.sh + - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test;'; fi" + - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi" -after_success: - - ../travis/after_success.sh + - sh -c "if [ '$PHPCS' = '1' ]; then composer require cakephp/cakephp-codesniffer:dev-master; fi" + + - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev satooshi/php-coveralls:dev-master; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" + +script: + - sh -c "if [ '$DEFAULT' = '1' ]; then phpunit --stderr; fi" + - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then phpunit --stderr --coverage-clover build/logs/clover.xml; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then php vendor/bin/coveralls -c .coveralls.yml -v; fi" notifications: email: false From 611c112b07a6d8523d29cb36581b319fdfa24b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Ferm=C3=ADn?= Date: Tue, 9 Dec 2014 12:18:46 +0100 Subject: [PATCH 0146/1476] Fixed typo in method name --- Model/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Model/User.php b/Model/User.php index 31f68c685..1b9f48446 100644 --- a/Model/User.php +++ b/Model/User.php @@ -229,7 +229,7 @@ public function confirmEmail($email = null) { * @param string $token * @return array */ - public function checkEmailVerfificationToken($token = null) { + public function checkEmailVerificationToken($token = null) { $result = $this->find('first', array( 'contain' => array(), 'conditions' => array( @@ -255,7 +255,7 @@ public function checkEmailVerfificationToken($token = null) { * @return array On success it returns the user data record */ public function verifyEmail($token = null) { - $user = $this->checkEmailVerfificationToken($token); + $user = $this->checkEmailVerificationToken($token); if ($user === false) { throw new RuntimeException(__d('users', 'Invalid token, please check the email you were sent, and retry the verification link.')); From 360a107202c092fc70f5a4ce15194694945cb2a8 Mon Sep 17 00:00:00 2001 From: Toni Almeida Date: Sat, 31 Jan 2015 17:30:19 +0000 Subject: [PATCH 0147/1476] Added Portuguese translation (por) --- Locale/por/LC_MESSAGES/users.po | 722 ++++++++++++++++++++++++++++++++ 1 file changed, 722 insertions(+) create mode 100644 Locale/por/LC_MESSAGES/users.po diff --git a/Locale/por/LC_MESSAGES/users.po b/Locale/por/LC_MESSAGES/users.po new file mode 100644 index 000000000..fa6a94689 --- /dev/null +++ b/Locale/por/LC_MESSAGES/users.po @@ -0,0 +1,722 @@ +# LANGUAGE translation of the CakePHP Users plugin +# +# Copyright 2010, Cake Development Corporation (http://cakedc.com) +# +# Licensed under The MIT License +# Redistributions of files must retain the above copyright notice. +# +# @copyright Copyright 2010, Cake Development Corporation (http://cakedc.com) +# @license MIT License (http://www.opensource.org/licenses/mit-license.php) +# +msgid "" +msgstr "" +"Project-Id-Version: CakePHP Users Plugin\n" +"POT-Creation-Date: 2015-01-31 17:20+0000\n" +"PO-Revision-Date: 2015-01-31 17:20+0000\n" +"Last-Translator: Toni Almeida \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=2;plural=n>1;\n" +"X-Poedit-Language: Portuguese\n" +"X-Poedit-Country: PORTUGAL\n" + +#: /controllers/details_controller.php:57;138 +msgid "Invalid Detail." +msgstr "Detalhe inválido." + +#: /controllers/details_controller.php:78 +msgid "Saved" +msgstr "Guardado" + +#: /controllers/details_controller.php:96 +msgid "%s details saved" +msgstr "%s detalhe guardado" + +#: /controllers/details_controller.php:113;196 +msgid "Invalid id for Detail" +msgstr "ID inválido para Detalhe" + +#: /controllers/details_controller.php:117;200 +msgid "Detail deleted" +msgstr "Detalhe removido" + +#: /controllers/details_controller.php:152;175 +msgid "The Detail has been saved" +msgstr "O Detalhe foi guardado" + +#: /controllers/details_controller.php:155;178 +msgid "The Detail could not be saved. Please, try again." +msgstr "O Detalhe não pode ser guardado. Por favor, tente novamente." + +#: /controllers/details_controller.php:170 +msgid "Invalid Detail" +msgstr "Detalhe inválido" + +#: /controllers/users_controller.php:157 +msgid "Profile saved." +msgstr "Perfil guardado." + +#: /controllers/users_controller.php:159 +msgid "Could not save your profile." +msgstr "Não foi possível salvar o perfil." + +#: /controllers/users_controller.php:193 +msgid "Invalid User." +msgstr "utilizador inválido." + +#: /controllers/users_controller.php:207 +msgid "The User has been saved" +msgstr "O utilizador foi guardado" + +#: /controllers/users_controller.php:223 +msgid "User saved" +msgstr "utilizador guardado" + +#: /controllers/users_controller.php:247 +msgid "User deleted" +msgstr "utilizador removido" + +#: /controllers/users_controller.php:249 +#: /models/user.php:703 +msgid "Invalid User" +msgstr "Utilizador inválido" + +#: /controllers/users_controller.php:273 +msgid "You are already registered and logged in!" +msgstr "Já está registado e com sessão iniciada!" + +#: /controllers/users_controller.php:282 +#: /tests/cases/controllers/users_controller.test.php:194 +msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." +msgstr "A sua conta foi criada. Vai receber um e-mail de confirmação. Assim que a sua conta for validada já poderá iniciar sessão." + +#: /controllers/users_controller.php:287 +#: /tests/cases/controllers/users_controller.test.php:205 +msgid "Your account could not be created. Please, try again." +msgstr "A sua conta não pôde ser criada. Por favor, tente novamente." + +#: /controllers/users_controller.php:309 +msgid "%s you have successfully logged in" +msgstr "%s, iniciou sessão com sucesso" + +#: /controllers/users_controller.php:383 +msgid "%s you have successfully logged out" +msgstr "%s, saiu com sucesso" + +#: /controllers/users_controller.php:409 +msgid "There url you accessed is not longer valid" +msgstr "O endereço a que tentou aceder já não está disponível" + +#: /controllers/users_controller.php:432;545 +msgid "Password Reset" +msgstr "Redefinir password" + +#: /controllers/users_controller.php:434 +msgid "Your password has been reset" +msgstr "A sua password foi redefinida" + +#: /controllers/users_controller.php:435 +msgid "Please login using this password and change your password" +msgstr "Por favor inicie sessão usando esta password e altere-a o assim que possível" + +#: /controllers/users_controller.php:438 +msgid "Your password was sent to your registered email account" +msgstr "A sua password foi enviada para o seu e-mail" + +#: /controllers/users_controller.php:444 +#: /tests/cases/controllers/users_controller.test.php:219 +msgid "Your e-mail has been validated!" +msgstr "O seu e-mail foi validado!" + +#: /controllers/users_controller.php:448 +msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." +msgstr "Houve um erro ao tentar validar o seu endereço de e-mail. Por favor, valide o seu e-mail a partir do URL que recebeu no seu e-mail." + +#: /controllers/users_controller.php:452 +#: /tests/cases/controllers/users_controller.test.php:224 +msgid "The url you accessed is not longer valid" +msgstr "O endereço URL a que tentou aceder já não é válido" + +#: /controllers/users_controller.php:467 +msgid "Password changed." +msgstr "Password alterada." + +#: /controllers/users_controller.php:521 +msgid "Account verification" +msgstr "Verificação de conta" + +#: /controllers/users_controller.php:563 +msgid "%s has been sent an email with instruction to reset their password." +msgstr "%s foi enviado um email com instruções para redefinir a sua password." + +#: /controllers/users_controller.php:567 +msgid "You should receive an email with further instructions shortly" +msgstr "Deverá receber um email com mais instruções em breve" + +#: /controllers/users_controller.php:571 +msgid "No user was found with that email." +msgstr "Não foi encontrado nenhum utilizador com esse e-mail." + +#: /controllers/users_controller.php:588 +msgid "Invalid password reset token, try again." +msgstr "Token para redefinição de password inválido, tente novamente." + +#: /controllers/users_controller.php:594 +msgid "Password changed, you can now login with your new password." +msgstr "Password alterada, pode agora entrar com a sua nova password." + +#: /models/user.php:102 +msgid "Please enter a username" +msgstr "Por favor introduza o nome de utilizador" + +#: /models/user.php:105 +msgid "The username must be alphanumeric" +msgstr "O nome de utilizador deve ser alfanumérico" + +#: /models/user.php:108 +msgid "This username is already in use." +msgstr "Esse nome de utilizador já está em uso." + +#: /models/user.php:111 +msgid "The username must have at least 3 characters." +msgstr "O nome de utilizador deve ter no mínimo 3 caracteres." + +#: /models/user.php:116 +msgid "Please enter a valid email address." +msgstr "Por favor introduza um endereço de e-mail válido." + +#: /models/user.php:119 +msgid "This email is already in use." +msgstr "Esse e-mail já está em uso." + +#: /models/user.php:123 +msgid "The password must have at least 8 characters." +msgstr "A password deve ter no mínimo 8 caracteres." + +#: /models/user.php:126 +msgid "Please enter a password." +msgstr "Por favor introduza a sua password." + +#: /models/user.php:129 +msgid "The passwords are not equal, please try again." +msgstr "As passwords devem ser iguais, por favor tente novamente." + +#: /models/user.php:132 +msgid "You must agree to the terms of use." +msgstr "Deve aceitar os termos de utilização." + +#: /models/user.php:137;357 +msgid "The passwords are not equal." +msgstr "As passwords não são iguais." + +#: /models/user.php:139 +msgid "Invalid password." +msgstr "Password inválida." + +#: /models/user.php:150 +msgid "Invalid date" +msgstr "Data inválida" + +#: /models/user.php:315 +msgid "This Email Address exists but was never validated." +msgstr "Esse endereço de e-mail existe mas nunca foi validado." + +#: /models/user.php:317 +msgid "This Email Address does not exist in the system." +msgstr "Esse endereço de e-mail não existe no sistema." + +#: /models/user.php:406 +msgid "$this->data['" +msgstr "$this->data['" + +#: /models/user.php:460 +msgid "The user does not exist." +msgstr "O utilizador não existe." + +#: /models/user.php:505 +msgid "Please enter your email address." +msgstr "Por favor introduza o seu endereço de e-mail." + +#: /models/user.php:515 +msgid "The email address does not exist in the system" +msgstr "O endereço de e-mail não existe no sistema" + +#: /models/user.php:520 +msgid "Your account is already authenticated." +msgstr "A sua conta já está autenticada." + +#: /models/user.php:525 +msgid "Your account is disabled." +msgstr "A sua conta foi desativada." + +#: /tests/cases/controllers/users_controller.test.php:34 +msgid "Sorry, but you need to login to access this location." +msgstr "Desculpe, mas precisa de iniciar sessão para aceder a este local." + +#: /tests/cases/controllers/users_controller.test.php:35;174 +msgid "Invalid e-mail / password combination. Please try again" +msgstr "Combinação de e-mail/password inválida. Por favor tente novamente." + +#: /tests/cases/controllers/users_controller.test.php:168 +msgid "testuser you have successfully logged in" +msgstr "Iniciou sessão de teste com sucesso" + +#: /tests/cases/controllers/users_controller.test.php:237 +msgid "floriank you have successfully logged out" +msgstr "floriank saiu com sucesso" + +#: /views/details/add.ctp:4 +#: /views/details/admin_add.ctp:4 +msgid "Add Detail" +msgstr "Adicionar Detalhe" + +#: /views/details/add.ctp:17 +#: /views/details/admin_add.ctp:17 +#: /views/details/admin_edit.ctp:19 +#: /views/details/admin_view.ctp:45 +#: /views/details/view.ctp:45 +msgid "List Details" +msgstr "Listar Detalhes" + +#: /views/details/add.ctp:18 +#: /views/details/admin_add.ctp:18 +#: /views/details/admin_edit.ctp:20 +#: /views/details/admin_index.ctp:67 +#: /views/details/admin_view.ctp:47 +#: /views/details/view.ctp:47 +#: /views/users/add.ctp:15 +#: /views/users/admin_add.ctp:13 +#: /views/users/admin_edit.ctp:15 +#: /views/users/admin_view.ctp:25 +msgid "List Users" +msgstr "Listar utilizadores" + +#: /views/details/add.ctp:19 +#: /views/details/admin_add.ctp:19 +#: /views/details/admin_edit.ctp:21 +#: /views/details/admin_index.ctp:68 +#: /views/details/admin_view.ctp:48 +#: /views/details/view.ctp:48 +#: /views/users/admin_view.ctp:26 +#: /views/users/index.ctp:46 +msgid "New User" +msgstr "Novo utilizador" + +#: /views/details/add.ctp:20 +#: /views/details/admin_add.ctp:20 +#: /views/details/admin_edit.ctp:22 +#: /views/details/admin_index.ctp:69 +#: /views/details/admin_view.ctp:49 +#: /views/details/view.ctp:49 +msgid "List Groups" +msgstr "Listar Grupos" + +#: /views/details/add.ctp:21 +#: /views/details/admin_add.ctp:21 +#: /views/details/admin_edit.ctp:23 +#: /views/details/admin_index.ctp:70 +#: /views/details/admin_view.ctp:50;95 +#: /views/details/view.ctp:50;95 +msgid "New Group" +msgstr "Novo Grupo" + +#: /views/details/admin_edit.ctp:4 +#: /views/details/admin_view.ctp:43 +#: /views/details/edit.ctp:5 +#: /views/details/view.ctp:43 +msgid "Edit Detail" +msgstr "Editar Detalhe" + +#: /views/details/admin_edit.ctp:18 +#: /views/details/admin_index.ctp:53 +#: /views/details/admin_view.ctp:86 +#: /views/details/view.ctp:86 +#: /views/users/admin_edit.ctp:14 +#: /views/users/admin_index.ctp:47 +#: /views/users/groups.ctp:38 +#: /views/users/index.ctp:33 +msgid "Delete" +msgstr "Remover" + +#: /views/details/admin_edit.ctp:18 +#: /views/details/admin_index.ctp:53 +#: /views/details/admin_view.ctp:44;86 +#: /views/details/view.ctp:44;86 +#: /views/users/admin_edit.ctp:14 +#: /views/users/admin_index.ctp:47 +#: /views/users/admin_view.ctp:24 +#: /views/users/index.ctp:33 +msgid "Are you sure you want to delete # %s?" +msgstr "Tem a certeza que deseja remover # %s?" + +#: /views/details/admin_index.ctp:2 +#: /views/users/register.ctp:4 +msgid "Details" +msgstr "Detalhes" + +#: /views/details/admin_index.ctp:6 +#: /views/users/index.ctp:6 +msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" +msgstr "Página %page% de %pages%, a mostrar %current% resultados de um total de %count%, iniciando em %start%, terminando em %end%" + +#: /views/details/admin_index.ctp:18 +#: /views/details/admin_view.ctp:65 +#: /views/details/view.ctp:65 +#: /views/users/admin_index.ctp:21 +#: /views/users/groups.ctp:15;50 +#: /views/users/index.ctp:13 +msgid "Actions" +msgstr "Ações" + +#: /views/details/admin_index.ctp:51 +#: /views/details/admin_view.ctp:84 +#: /views/details/view.ctp:84 +#: /views/users/admin_index.ctp:45 +#: /views/users/index.ctp:31 +msgid "View" +msgstr "Visualizar" + +#: /views/details/admin_index.ctp:52 +#: /views/details/admin_view.ctp:85 +#: /views/details/view.ctp:85 +#: /views/users/admin_index.ctp:46 +#: /views/users/groups.ctp:33 +#: /views/users/index.ctp:32 +msgid "Edit" +msgstr "Editar" + +#: /views/details/admin_index.ctp:60 +#: /views/users/index.ctp:40 +msgid "previous" +msgstr "anterior" + +#: /views/details/admin_index.ctp:62 +#: /views/users/index.ctp:42 +msgid "next" +msgstr "próximo" + +#: /views/details/admin_index.ctp:66 +#: /views/details/admin_view.ctp:46 +#: /views/details/view.ctp:46 +msgid "New Detail" +msgstr "Novo Detalhe" + +#: /views/details/admin_view.ctp:2 +#: /views/details/view.ctp:2 +msgid "Detail" +msgstr "Detalhe" + +#: /views/details/admin_view.ctp:4;58 +#: /views/details/view.ctp:4;58 +msgid "Id" +msgstr "Id" + +#: /views/details/admin_view.ctp:9 +#: /views/details/view.ctp:9 +#: /views/users/admin_view.ctp:2 +#: /views/users/view.ctp:2 +msgid "User" +msgstr "utilizador" + +#: /views/details/admin_view.ctp:14 +#: /views/details/view.ctp:14 +msgid "Position" +msgstr "Posição" + +#: /views/details/admin_view.ctp:19 +#: /views/details/view.ctp:19 +msgid "Field" +msgstr "Campo" + +#: /views/details/admin_view.ctp:24 +#: /views/details/view.ctp:24 +msgid "Value" +msgstr "Valor" + +#: /views/details/admin_view.ctp:29;63 +#: /views/details/view.ctp:29;63 +#: /views/users/admin_view.ctp:9 +#: /views/users/view.ctp:9 +msgid "Created" +msgstr "Criação" + +#: /views/details/admin_view.ctp:34;64 +#: /views/details/view.ctp:34;64 +#: /views/users/admin_view.ctp:14 +msgid "Modified" +msgstr "Atualização" + +#: /views/details/admin_view.ctp:44 +#: /views/details/view.ctp:44 +msgid "Delete Detail" +msgstr "Remover Detalhe" + +#: /views/details/admin_view.ctp:54 +#: /views/details/view.ctp:54 +msgid "Related Groups" +msgstr "Grupos relacionados" + +#: /views/details/admin_view.ctp:59 +#: /views/details/view.ctp:59 +msgid "User Id" +msgstr "Id de utilizador" + +#: /views/details/admin_view.ctp:60 +#: /views/details/view.ctp:60 +msgid "Is Public" +msgstr "Público" + +#: /views/details/admin_view.ctp:61 +#: /views/details/view.ctp:61 +#: /views/users/groups.ctp:13;47 +#: /views/users/search.ctp:9 +msgid "Name" +msgstr "Nome" + +#: /views/details/admin_view.ctp:62 +#: /views/details/view.ctp:62 +#: /views/users/groups.ctp:48 +msgid "Description" +msgstr "Descrição" + +#: /views/details/index.ctp:17 +#: /views/users/change_password.ctp:16 +#: /views/users/login.ctp:13 +#: /views/users/register.ctp:33;89 +#: /views/users/request_password_change.ctp:12 +#: /views/users/reset_password.ctp:14 +msgid "Submit" +msgstr "Enviar" + +#: /views/elements/login.ctp:11 +#: /views/users/admin_index.ctp:10 +#: /views/users/login.ctp:8 +#: /views/users/register.ctp:71;78 +#: /views/users/search.ctp:7 +msgid "Email" +msgstr "E-mail" + +#: /views/elements/login.ctp:13 +#: /views/users/login.ctp:10 +#: /views/users/register.ctp:19 +msgid "Password" +msgstr "Password" + +#: /views/elements/login.ctp:15 +#: /views/users/login.ctp:1;3 +msgid "Login" +msgstr "Entrar" + +#: /views/elements/email/text/account_verification.ctp:2 +msgid "Hello %s," +msgstr "Olá %s," + +#: /views/elements/email/text/account_verification.ctp:4 +msgid "to validate your account, you must visit the URL below within 24 hours" +msgstr "para validar a sua conta, deve aceder ao URL abaixo, dentro das próximas 24 horas" + +#: /views/elements/email/text/password_reset_request.ctp:2 +msgid "A request to reset your password was sent. To change your password click the link below." +msgstr "A solicitação para redefinir a sua password foi enviada. Para alterar a password, clique no link abaixo." + +#: /views/users/add.ctp:4 +#: /views/users/admin_add.ctp:4 +msgid "Add User" +msgstr "Adicionar utilizador" + +#: /views/users/admin_edit.ctp:4 +#: /views/users/admin_view.ctp:23 +#: /views/users/edit.ctp:3 +msgid "Edit User" +msgstr "Editar utilizador" + +#: /views/users/admin_index.ctp:2 +#: /views/users/index.ctp:2 +msgid "Users" +msgstr "Utilizadores" + +#: /views/users/admin_index.ctp:4 +msgid "Filter" +msgstr "Filtro" + +#: /views/users/admin_index.ctp:8 +#: /views/users/admin_view.ctp:4 +#: /views/users/register.ctp:57;63 +#: /views/users/search.ctp:5 +#: /views/users/view.ctp:4 +msgid "Username" +msgstr "Nome de utilizador" + +#: /views/users/admin_index.ctp:11 +#: /views/users/search.ctp:10 +msgid "Search" +msgstr "Pesquisar" + +#: /views/users/admin_view.ctp:24 +msgid "Delete User" +msgstr "Remover utilizador" + +#: /views/users/change_password.ctp:1 +msgid "Change your password" +msgstr "Altere a sua password" + +#: /views/users/change_password.ctp:3 +msgid "Please enter your old password because of security reasons and then your new password twice." +msgstr "Por favor insira a sua password antiga por razões de segurança e depois a sua nova password duas vezes." + +#: /views/users/change_password.ctp:8 +msgid "Old Password" +msgstr "Password antiga" + +#: /views/users/change_password.ctp:11 +#: /views/users/reset_password.ctp:9 +msgid "New Password" +msgstr "Nova password" + +#: /views/users/change_password.ctp:14 +#: /views/users/reset_password.ctp:12 +msgid "Confirm" +msgstr "Confirmar" + +#: /views/users/dashboard.ctp:2 +msgid "Welcome" +msgstr "Bem-vindo(a)" + +#: /views/users/dashboard.ctp:3 +msgid "Recent broadcasts" +msgstr "Atualizações recentes" + +#: /views/users/groups.ctp:2 +msgid "My Groups" +msgstr "Os meus Grupos" + +#: /views/users/groups.ctp:5 +msgid "Create a new group" +msgstr "Criar um novo grupo" + +#: /views/users/groups.ctp:6 +msgid "Invite a user" +msgstr "Convide um utilizador" + +#: /views/users/groups.ctp:7 +msgid "Requests to join" +msgstr "Convites para participar" + +#: /views/users/groups.ctp:10 +msgid "My own groups" +msgstr "Os meus próprios grupos" + +#: /views/users/groups.ctp:14;49 +msgid "Members" +msgstr "Membros" + +#: /views/users/groups.ctp:34 +msgid "Invite user" +msgstr "Convide um utilizador" + +#: /views/users/groups.ctp:35 +msgid "Manage Broadcast Scope" +msgstr "Gerir atualizações" + +#: /views/users/groups.ctp:36 +msgid "Access" +msgstr "Acesso" + +#: /views/users/groups.ctp:37 +msgid "Addons" +msgstr "Módulos" + +#: /views/users/groups.ctp:44 +msgid "Groups im a member in" +msgstr "Grupos em que sou membro" + +#: /views/users/groups.ctp:68 +msgid "Leave group" +msgstr "Deixar o grupo" + +#: /views/users/login.ctp:11 +msgid "Remember Me" +msgstr "Lembrar-me" + +#: /views/users/register.ctp:2 +msgid "Account registration" +msgstr "Registo de conta" + +#: /views/users/register.ctp:10 +msgid "Please select a username that is not already in use" +msgstr "Por favor selecione um nome de utilizador que ainda não seja utilizado" + +#: /views/users/register.ctp:11 +msgid "Must be at least 3 characters" +msgstr "Tem que ter no mínimo 3 caracteres" + +#: /views/users/register.ctp:12 +msgid "Username must contain numbers and letters only" +msgstr "Nome de utilizador deve conter apenas números e letras" + +#: /views/users/register.ctp:13 +msgid "Please choose username" +msgstr "Por favor escolha o nome de utilizador" + +#: /views/users/register.ctp:15 +msgid "E-mail (used as login)" +msgstr "E-mail (usado para entrar)" + +#: /views/users/register.ctp:16 +msgid "Must be a valid email address" +msgstr "O e-mail deve ser um endereço válido" + +#: /views/users/register.ctp:17 +msgid "An account with that email already exists" +msgstr "Já existe uma conta com esse e-mail" + +#: /views/users/register.ctp:21 +msgid "Must be at least 5 characters long" +msgstr "Deve ter pelo menos 5 caracteres" + +#: /views/users/register.ctp:23 +msgid "Password (confirm)" +msgstr "Confirme a password" + +#: /views/users/register.ctp:25 +msgid "Passwords must match" +msgstr "As passwords devem ser iguais" + +#: /views/users/register.ctp:29;85 +msgid "I have read and agreed to " +msgstr "Eu li e concordo com " + +#: /views/users/register.ctp:29;85 +msgid "Terms of Service" +msgstr "Termos de Serviço" + +#: /views/users/register.ctp:30;86 +msgid "You must verify you have read the Terms of Service" +msgstr "Deve verificar se leu os Termos de Serviços" + +#: /views/users/register.ctp:46 +msgid "Openid Identifier" +msgstr "Identificador OpenId" + +#: /views/users/request_password_change.ctp:1 +msgid "Forgot your password?" +msgstr "Esqueceu-se da password?" + +#: /views/users/request_password_change.ctp:3 +msgid "Please enter the email you used for registration and you'll get an email with further instructions." +msgstr "Por favor entre com o e-mail usado no registro e você irá receber um e-mail com mais instruções." + +#: /views/users/request_password_change.ctp:11 +msgid "Your Email" +msgstr "O seu e-mail" + +#: /views/users/reset_password.ctp:1 +msgid "Reset your password" +msgstr "Redefinir password" + +#: /views/users/search.ctp:1 +msgid "Search for users" +msgstr "Procurar por utilizadores" + From b7e59dac03c4d6477a7f7f8351374565f99db3d9 Mon Sep 17 00:00:00 2001 From: Zachary Wilson Date: Mon, 21 Apr 2014 16:33:11 -0500 Subject: [PATCH 0148/1476] refs #208 fix conflict --- Model/User.php | 4 ++-- Test/Case/Model/UserTest.php | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Model/User.php b/Model/User.php index 1b9f48446..3273d9984 100644 --- a/Model/User.php +++ b/Model/User.php @@ -854,8 +854,8 @@ public function edit($userId = null, $postData = null) { if (!empty($postData)) { $this->set($postData); if ($this->validates()) { - if (!empty($this->data[$this->alias]['password'])) { - $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['password'], 'sha1', true); + if(isset($postData[$this->alias]['password'])) { + $this->data[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); } $result = $this->save(null, false); if ($result) { diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index dd8185d69..ac5750bd7 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -428,14 +428,21 @@ public function testEdit() { **/ public function testEditPassword() { $userId = '1'; - $data = $this->User->read(null, $userId); - $data['User']['email'] = 'anotherNewEmail@anothernewemail.com'; - $data['User']['password'] = 'anotherNewPassword'; - $data['User']['temppassword'] = 'anotherNewPassword'; - $result = $this->User->edit(1, $data); + $data1 = $this->User->read(null, $userId); + + $data['User']['email'] = 'emailUpdate@anotheremail.com'; + $result = $this->User->edit($userId, $data); + $this->assertTrue($result); + $this->assertEquals($this->User->data['User']['password'], $data1['User']['password']); + + $data1['User']['email'] = 'anotherNewEmail@anothernewemail.com'; + $data1['User']['password'] = 'anotherNewPassword'; + $data1['User']['temppassword'] = 'anotherNewPassword'; + + $result = $this->User->edit($userId, $data1); - $hashPassword = $this->User->hash($data['User']['password'], 'sha1', true); + $hashPassword = $this->User->hash($data1['User']['password'], 'sha1', true); $this->assertTrue($result); $this->assertEquals($this->User->data['User']['password'], $hashPassword); From cea0f79746ac025fbf5dc06d03bff2f7cd225239 Mon Sep 17 00:00:00 2001 From: zmonteca Date: Wed, 25 Mar 2015 14:19:33 -0500 Subject: [PATCH 0149/1476] added Enable / Disable callbacks parameter. Can be use when subclassing to ensure callbacks run. --- Model/User.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Model/User.php b/Model/User.php index 1b9f48446..c8d459f00 100644 --- a/Model/User.php +++ b/Model/User.php @@ -70,6 +70,14 @@ class User extends UsersAppModel { */ public $validationDomain = 'users'; +/** + * Enable / Disable callbacks parameter. + * Can be use when subclassing to ensure callbacks run. + * + * @var boolean + */ + public $enableCallbacks = false; + /** * Validation parameters * @@ -273,7 +281,7 @@ public function verifyEmail($token = null) { $user = $this->save($user, array( 'validate' => false, - 'callbacks' => false + 'callbacks' => $this->enableCallbacks )); $this->data = $user; return $user; @@ -380,7 +388,7 @@ public function resetPassword($postData = array()) { $this->data[$this->alias]['password_token'] = null; $result = $this->save($this->data, array( 'validate' => false, - 'callbacks' => false) + 'callbacks' => $this->enableCallbacks) ); } @@ -402,7 +410,7 @@ public function changePassword($postData = array()) { $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['new_password'], null, true); $this->save($postData, array( 'validate' => false, - 'callbacks' => false)); + 'callbacks' => $this->enableCallbacks)); return true; } return false; @@ -516,7 +524,7 @@ public function checkEmailVerification($postData = array(), $renew = true) { $user[$this->alias]['email_token_expires'] = $this->emailTokenExpirationTime(); $this->save($user, array( 'validate' => false, - 'callbacks' => false, + 'callbacks' => $this->enableCallbacks, )); } $this->data = $user; From a77679251148f1f420b4382864e235253411e4b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 6 Aug 2015 09:35:19 +0100 Subject: [PATCH 0150/1476] refs #travis-update-2.7 update travis to check 2.7 --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index f65bc23cc..e542016f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,12 +19,21 @@ matrix: - php: 5.3 env: - CAKE_VERSION=2.6 + - php: 5.3 + env: + - CAKE_VERSION=2.7 - php: 5.4 env: - CAKE_VERSION=2.6 + - php: 5.4 + env: + - CAKE_VERSION=2.7 - php: 5.5 env: - CAKE_VERSION=2.6 + - php: 5.5 + env: + - CAKE_VERSION=2.7 before_script: - git clone https://github.com/steinkel/travis.git --depth 1 ../travis From 755bc43c0be2c84ada937c4b7757626734a8e87d Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Thu, 6 Aug 2015 08:39:57 -0500 Subject: [PATCH 0151/1476] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 84c5e08fe..7ca37d52c 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ CakeDC Users Plugin [![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) +**IMPORTANT: 3.x version is ALPHA status now and you can check it out from [CakeDC Users Plugin for CakePHP 3.x](https://github.com/cakedc/users/tree/3.x)!, we are constantly improving and testing it now.** + The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. The plugin is thought as a base to extend your app specific users controller and model from. From 459dd6925283e655652186c42db3d70feddf4a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 8 Aug 2015 17:42:18 +0100 Subject: [PATCH 0152/1476] refs # fix validateAccount method name, fix non related unit test after routes change --- src/Controller/SocialAccountsController.php | 2 +- tests/TestCase/View/Helper/UserHelperTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 5f3957b99..4f9d147c7 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -44,7 +44,7 @@ public function initialize() * @param string $token token * @return Response */ - public function validate($provider, $reference, $token) + public function validateAccount($provider, $reference, $token) { try { $result = $this->SocialAccounts->validateAccount($provider, $reference, $token); diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 9026a346f..3c775e3f7 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -166,7 +166,7 @@ public function testWelcome() ->method('session') ->will($this->returnValue($session)); - $expected = 'Welcome, david'; + $expected = 'Welcome, david'; $result = $this->User->welcome(); $this->assertEquals($expected, $result); } From c4125fd9a712c6d3a6c25fb9e00b28295296a7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 10 Aug 2015 08:52:48 +0100 Subject: [PATCH 0153/1476] refs #refactor-behavior add gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..61ead8666 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor From 997a474ac016634e83d3183b32c0c0fcc65e7863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 10 Aug 2015 09:34:10 +0100 Subject: [PATCH 0154/1476] add new traits --- src/Model/Entity/User.php | 16 + .../Table/Traits/PasswordManagementTrait.php | 105 +++++ src/Model/Table/Traits/RegisterTrait.php | 177 +++++++ src/Model/Table/Traits/SocialTrait.php | 185 ++++++++ src/Model/Table/UsersTable.php | 433 +----------------- 5 files changed, 489 insertions(+), 427 deletions(-) create mode 100644 src/Model/Table/Traits/PasswordManagementTrait.php create mode 100644 src/Model/Table/Traits/RegisterTrait.php create mode 100644 src/Model/Table/Traits/SocialTrait.php diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index f1c00f924..dde309c96 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -13,6 +13,8 @@ use Cake\Auth\DefaultPasswordHasher; use Cake\ORM\Entity; +use Cake\Utility\Text; +use DateTime; /** * User Entity. @@ -95,4 +97,18 @@ protected function _getAvatar() } return $avatar; } + + /** + * Generate token_expires and token in a user + * @param string $tokenExpiration new token_expires user. + * + * @return void + */ + public function updateToken($tokenExpiration) + { + $expires = new DateTime(); + $expires->modify(sprintf('+ {0} secs', $tokenExpiration)); + $this->token_expires = $expires; + $this->token = str_replace('-', '', Text::uuid()); + } } diff --git a/src/Model/Table/Traits/PasswordManagementTrait.php b/src/Model/Table/Traits/PasswordManagementTrait.php new file mode 100644 index 000000000..957d625e4 --- /dev/null +++ b/src/Model/Table/Traits/PasswordManagementTrait.php @@ -0,0 +1,105 @@ +findAllByUsernameOrEmail($reference, $reference)->first(); + + if (empty($user)) { + throw new UserNotFoundException(__d('Users', "User not found")); + } + if (Hash::get($options, 'checkActive')) { + if ($user->active) { + throw new UserAlreadyActiveException("User account already validated"); + } + $user->active = false; + $user->activation_date = null; + } + $user->updateToken(Hash::get($options, 'expiration')); + $saveResult = $this->save($user); + if (Hash::get($options, 'sendEmail')) { + $this->sendResetPasswordEmail($saveResult); + } + return $saveResult; + } + + /** + * Send the reset password email + * + * @param EntityInterface $user User entity + * @param Email $email instance, if null the default email configuration with the + * Users.validation template will be used, so set a ->template() if you pass an Email + * instance + * @return array email send result + */ + public function sendResetPasswordEmail(EntityInterface $user, Email $email = null) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + $subject = __d('Users', '{0}Your reset password link', $firstName); + return $this->getEmailInstance($email) + ->template('Users.reset_password') + ->to($user['email']) + ->subject($subject) + ->viewVars($user->toArray()) + ->send(); + } + + /** + * Change password method + * + * @param EntityInterface $user user data. + * @return mixed + */ + public function changePassword(EntityInterface $user) + { + $currentUser = $this->get($user->id, [ + 'contain' => [] + ]); + + if (!empty($user->current_password)) { + if (!$user->checkPassword($user->current_password, $currentUser->password)) { + throw new WrongPasswordException(__d('Users', 'The old password does not match')); + } + } + $user = $this->save($user); + if (!empty($user)) { + $user = $this->_removesValidationToken($user); + } + return $user; + } +} diff --git a/src/Model/Table/Traits/RegisterTrait.php b/src/Model/Table/Traits/RegisterTrait.php new file mode 100644 index 000000000..3cf8352b9 --- /dev/null +++ b/src/Model/Table/Traits/RegisterTrait.php @@ -0,0 +1,177 @@ +patchEntity($user, $data, ['validate' => $validator]); + + $tokenExpiration = Hash::get($options, 'token_expiration'); + $useTos = Hash::get($options, 'use_tos'); + if ($useTos && !$user->tos) { + throw new InvalidArgumentException(__d('Users', 'The "tos" property is not present')); + } + + if (!empty($user['tos'])) { + $user->tos_date = new DateTime(); + } + $user->validated = false; + //@todo mov updateActive to afterSave? + $this->_updateActive($user, $validateEmail, $tokenExpiration); + $this->isValidateEmail = $validateEmail; + $userSaved = $this->save($user); + if ($userSaved && $validateEmail) { + $this->sendValidationEmail($user); + } + return $userSaved; + } + + /** + * DRY for update active and token based on validateEmail flag + * + * @param type $user Reference of user to be updated. + * @param type $validateEmail email user to validate. + * @param type $tokenExpiration token to be updated. + * @return void + */ + protected function _updateActive(&$user, $validateEmail, $tokenExpiration) + { + $emailValidated = $user['validated']; + if (!$emailValidated && $validateEmail) { + $user['active'] = false; + $user->updateToken($tokenExpiration); + } else { + $user['active'] = true; + $user['activation_date'] = new DateTime(); + } + } + + /** + * Send the validation email to the newly registered user + * + * @param EntityInterface $user User entity + * @param Email $email instance, if null the default email configuration with the + * Users.validation template will be used, so set a ->template() if you pass an Email + * instance + * @return array email send result + */ + public function sendValidationEmail(EntityInterface $user, Email $email = null) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + $subject = __d('Users', '{0}Your account validation link', $firstName); + return $this->getEmailInstance($email) + ->to($user['email']) + ->subject($subject) + ->viewVars($user->toArray()) + ->send(); + } + + /** + * Validates token and return user + * + * @param type $token toke to be validated. + * @param null $callback function that will be returned. + * @throws TokenExpiredException when token has expired. + * @throws UserNotFoundException when user isn't found. + * @return User $user + */ + public function validate($token, $callback = null) + { + $user = $this->find() + ->select(['token_expires', 'id', 'active', 'token']) + ->where(['token' => $token]) + ->first(); + if (!empty($user)) { + if (!$user->tokenExpired()) { + if (!empty($callback) && method_exists($this, $callback)) { + return $this->{$callback}($user); + } else { + return $user; + } + } else { + throw new TokenExpiredException(__d('Users', "Token has already expired user with no token")); + } + } else { + throw new UserNotFoundException(__d('Users', "User not found for the given token and email.")); + } + } + + /** + * Activates an user + * + * @param EntityInterface $user user object. + * @return mixed User entity or bool false if the user could not be activated + * @throws UserAlreadyActiveException + * @todo: move into new behavior + */ + public function activateUser(EntityInterface $user) + { + if ($user->active) { + throw new UserAlreadyActiveException(__d('Users', "User account already validated")); + } + $user = $this->_removesValidationToken($user); + $user->activation_date = new DateTime(); + $user->active = true; + $result = $this->save($user); + + return $result; + } + + /** + * Removes user token for validation + * + * @param User $user user object. + * @return User + * + * @todo: move into new behavior + */ + protected function _removesValidationToken(EntityInterface $user) + { + $user->token = null; + $user->token_expires = null; + $result = $this->save($user); + + return $result; + } +} diff --git a/src/Model/Table/Traits/SocialTrait.php b/src/Model/Table/Traits/SocialTrait.php new file mode 100644 index 000000000..219106817 --- /dev/null +++ b/src/Model/Table/Traits/SocialTrait.php @@ -0,0 +1,185 @@ +provider; + $reference = $data->uid; + $existingAccount = $this->SocialAccounts->find() + ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $provider]) + ->contain(['Users']) + ->first(); + if (empty($existingAccount->user)) { + $user = $this->_createSocialUser($data, $options); + if (!empty($user->social_accounts[0])) { + $existingAccount = $user->social_accounts[0]; + } else { + //@todo: what if we don't have a social account after createSocialUser? + throw new InvalidArgumentException(__d('Users', 'Unable to login user with reference {0}', $reference)); + } + } else { + $user = $existingAccount->user; + } + if (!empty($existingAccount)) { + if ($existingAccount->active) { + return $user; + } else { + throw new AccountNotActiveException([ + $existingAccount->provider, + $existingAccount->reference + ]); + } + } + return false; + } + + /** + * Creates social user, populate the user data based on the social login data first and save it + * + * @param array $data Array social user. + * @param array $options Array option data. + * @return bool|EntityInterface|mixed result of the save operation + */ + protected function _createSocialUser($data, $options = []) + { + $useEmail = Hash::get($options, 'use_email'); + $validateEmail = Hash::get($options, 'validate_email'); + $tokenExpiration = Hash::get($options, 'token_expiration'); + if ($useEmail && empty($data->email)) { + throw new MissingEmailException(__d('Users', 'Email not present')); + } else { + $existingUser = $this->find() + ->where([$this->alias() . '.email' => $data->email]) + ->first(); + } + $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); + $this->isValidateEmail = $validateEmail; + $result = $this->save($user); + return $result; + } + + /** + * Build new user entity either by using an existing user or extracting the data from the social login + * data to create a new one + * + * @param array $data Array social login. + * @param EntityInterface $existingUser user data. + * @param string $useEmail email to use. + * @param string $validateEmail email to validate. + * @param string $tokenExpiration token_expires data. + * @return EntityInterface + */ + protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) + { + $accountData['provider'] = $data->provider; + $accountData['username'] = Hash::get($data->info, 'nickname'); + $accountData['reference'] = $data->uid; + $accountData['avatar'] = Hash::get($data->info, 'image'); + /* @todo make a pull request to Opauth Facebook Strategy because it does not include link on info array */ + if ($data->provider == SocialAccountsTable::PROVIDER_TWITTER) { + $accountData['link'] = Hash::get($data->info, 'urls.twitter'); + } elseif ($data->provider == SocialAccountsTable::PROVIDER_FACEBOOK) { + $accountData['link'] = Hash::get($data->raw, 'link'); + } + $accountData['avatar'] = str_replace('square', 'large', $accountData['avatar']); + $accountData['description'] = Hash::get($data->info, 'description'); + $accountData['token'] = Hash::get((array)$data->credentials, 'token'); + $accountData['token_secret'] = Hash::get((array)$data->credentials, 'secret'); + $accountData['token_expires'] = !empty(Hash::get((array)$data->credentials, 'expires')) ? (new DateTime(Hash::get((array)$data->credentials, 'expires')))->format('Y-m-d H:i:s') : null; + $accountData['data'] = serialize($data->raw); + $accountData['active'] = true; + + if (empty($existingUser)) { + if (!empty($data->info['first_name']) && !empty($data->info['last_name'])) { + $userData['first_name'] = Hash::get($data->info, 'first_name'); + $userData['last_name'] = Hash::get($data->info, 'last_name'); + } else { + $name = explode(' ', $data->name); + $userData['first_name'] = Hash::get($name, 0); + array_shift($name); + $userData['last_name'] = implode(' ', $name); + } + $userData['username'] = Hash::get($data->info, 'nickname'); + if (empty(Hash::get($userData, 'username'))) { + if (!empty($data->email)) { + $email = explode('@', $data->email); + $userData['username'] = Hash::get($email, 0); + } else { + $firstName = Hash::get($userData, 'first_name'); + $lastName = Hash::get($userData, 'last_name'); + $userData['username'] = strtolower($firstName . $lastName); + $userData['username'] = preg_replace('/[^A-Za-z0-9]/i', '', Hash::get($userData, 'username')); + } + + } + $userData['username'] = $this->_generateUsername(Hash::get($userData, 'username')); + if ($useEmail) { + $userData['email'] = $data->email; + if (!$data->validated) { + $accountData['active'] = false; + } + } + $userData['password'] = $this->randomString(); + $userData['avatar'] = Hash::get($data->info, 'image'); + $userData['validated'] = $data->validated; + $this->_updateActive($userData, false, $tokenExpiration); + $userData['tos_date'] = date("Y-m-d H:i:s"); + $userData['gender'] = Hash::get($data->raw, 'gender'); + $userData['timezone'] = Hash::get($data->raw, 'timezone'); + $userData['social_accounts'][] = $accountData; + $user = $this->newEntity($userData, ['associated' => ['SocialAccounts']]); + } else { + if ($useEmail && !$data->validated) { + $accountData['active'] = false; + } + $user = $this->patchEntity($existingUser, [ + 'social_accounts' => [$accountData] + ], ['associated' => ['SocialAccounts']]); + } + return $user; + } + + /** + * Checks if username exists and generate a new one + * + * @param string $username username data. + * @return string + */ + protected function _generateUsername($username) + { + $i = 0; + while (true) { + $existingUsername = $this->find()->where([$this->alias() . '.username' => $username])->count(); + if ($existingUsername > 0) { + $username = $username . $i; + $i++; + continue; + } + break; + } + return $username; + } +} diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index c0ac5fd86..0a0cc48c2 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -17,23 +17,21 @@ use Cake\ORM\Table; use Cake\Utility\Hash; use Cake\Validation\Validator; -use DateTime; -use InvalidArgumentException; -use Users\Exception\AccountNotActiveException; -use Users\Exception\MissingEmailException; -use Users\Exception\TokenExpiredException; -use Users\Exception\UserAlreadyActiveException; -use Users\Exception\UserNotFoundException; use Users\Exception\WrongPasswordException; use Users\Model\Entity\User; -use Users\Traits\RandomStringTrait; +use Users\Model\Table\Traits\RegisterTrait; +use Users\Model\Table\Traits\SocialTrait; /** * Users Model */ class UsersTable extends Table { + + use PasswordManagementTrait; use RandomStringTrait; + use RegisterTrait; + use SocialTrait; /** * Flag to set email check in buildRules or not @@ -188,425 +186,6 @@ public function buildRules(RulesChecker $rules) return $rules; } - /** - * Registers an user. - * - * @param EntityInterface $user User information - * @param array $data User information - * @param array $options ['tokenExpiration] - * @return bool|EntityInterface - * @throws InvalidArgumentException - * @todo: move into new behavior - */ - public function register($user, $data, $options) - { - $validateEmail = Hash::get($options, 'validate_email'); - $validator = Hash::get($options, 'validator') ?: 'register'; - if ($validateEmail) { - $validator = 'email'; - } - $user = $this->patchEntity($user, $data, ['validate' => $validator]); - - $tokenExpiration = Hash::get($options, 'token_expiration'); - $useTos = Hash::get($options, 'use_tos'); - if ($useTos && !$user->tos) { - throw new InvalidArgumentException(__d('Users', 'The "tos" property is not present')); - } - - if (!empty($user['tos'])) { - $user->tos_date = new DateTime(); - } - $user->validated = false; - $this->_updateActive($user, $validateEmail, $tokenExpiration); - $this->isValidateEmail = $validateEmail; - $userSaved = $this->save($user); - if ($userSaved && $validateEmail) { - $this->sendValidationEmail($user); - } - return $userSaved; - } - - /** - * DRY for update active and token based on validateEmail flag - * - * @param type $user Reference of user to be updated. - * @param type $validateEmail email user to validate. - * @param type $tokenExpiration token to be updated. - * @return void - */ - protected function _updateActive(&$user, $validateEmail, $tokenExpiration) - { - $emailValidated = $user['validated']; - if (!$emailValidated && $validateEmail) { - $user['active'] = false; - $this->_updateToken($user, $tokenExpiration); - } else { - $user['active'] = true; - $user['activation_date'] = new DateTime(); - } - } - - /** - * Validates token and return user - * - * @param type $token toke to be validated. - * @param null $callback function that will be returned. - * @throws TokenExpiredException when token has expired. - * @throws UserNotFoundException when user isn't found. - * @return User $user - */ - public function validate($token, $callback = null) - { - $user = $this->find() - ->select(['token_expires', 'id', 'active', 'token']) - ->where(['token' => $token]) - ->first(); - if (!empty($user)) { - if (!$user->tokenExpired()) { - if (!empty($callback) && method_exists($this, $callback)) { - return $this->{$callback}($user); - } else { - return $user; - } - } else { - throw new TokenExpiredException(__d('Users', "Token has already expired user with no token")); - } - } else { - throw new UserNotFoundException(__d('Users', "User not found for the given token and email.")); - } - } - - /** - * Removes user token for validation - * - * @param User $user user object. - * @return User - * - * @todo: move into new behavior - */ - protected function _removesValidationToken(User $user) - { - $user->token = null; - $user->token_expires = null; - $result = $this->save($user); - - return $result; - } - - /** - * Activates an user - * - * @param User $user user object. - * @return mixed User entity or bool false if the user could not be activated - * @throws UserAlreadyActiveException - * @todo: move into new behavior - */ - public function activateUser(User $user) - { - if ($user->active) { - throw new UserAlreadyActiveException("User account already validated"); - } - $user = $this->_removesValidationToken($user); - $user->activation_date = new DateTime(); - $user->active = true; - $result = $this->save($user); - - return $result; - } - - /** - * Resets user token - * - * @param string $reference User username or email - * @param array $options checkActive, sendEmail, expiration - * - * @return string - * @throws InvalidArgumentException - * @throws UserNotFoundException - * @throws UserAlreadyActiveException - * @todo: move into new behavior - */ - public function resetToken($reference, array $options = []) - { - if (empty($reference)) { - throw new InvalidArgumentException(sprintf('Reference cannot be null')); - } - - if (empty(Hash::get($options, 'expiration'))) { - throw new InvalidArgumentException(sprintf('Token expiration cannot be null')); - } - - $user = $this->findAllByUsernameOrEmail($reference, $reference)->first(); - - if (empty($user)) { - throw new UserNotFoundException(__d('Users', "User not found")); - } - if (Hash::get($options, 'checkActive')) { - if ($user->active) { - throw new UserAlreadyActiveException("User account already validated"); - } - $user->active = false; - $user->activation_date = null; - } - $this->_updateToken($user, Hash::get($options, 'expiration')); - $saveResult = $this->save($user); - if (Hash::get($options, 'sendEmail')) { - $this->sendResetPasswordEmail($saveResult); - } - return $saveResult; - } - - /** - * Generate token_expires and token in a user - * @param type $user Reference to user. - * @param string $tokenExpiration new token_expires user. - * - * @return type - */ - protected function _updateToken(&$user, $tokenExpiration) - { - $expires = new DateTime(); - $expires->modify(__d('Users', '+ {0} secs', $tokenExpiration)); - $user['token_expires'] = $expires; - $user['token'] = $this->randomString(); - - return $user; - } - - /** - * Checks if username exists and generate a new one - * @param string $username username data. - * @return string - * - * @todo: move into new behavior - */ - protected function _generateUsername($username) - { - $i = 0; - while (true) { - $existingUsername = $this->find()->where([$this->alias() . '.username' => $username])->count(); - if ($existingUsername > 0) { - $username = $username . $i; - $i++; - continue; - } - break; - } - return $username; - } - - /** - * Performs social login - * @param array $data Array social login. - * @param array $options Array option data. - * @return bool|EntityInterface|mixed - * - * @todo: move into new behavior - * @todo: Improve docblock - */ - public function socialLogin($data, $options = []) - { - $provider = $data->provider; - $reference = $data->uid; - $existingAccount = $this->SocialAccounts->find() - ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $provider]) - ->contain(['Users']) - ->first(); - if (empty($existingAccount->user)) { - $user = $this->_createSocialUser($data, $options); - if (!empty($user->social_accounts[0])) { - $existingAccount = $user->social_accounts[0]; - } else { - //@todo: what if we don't have a social account after createSocialUser? - throw new InvalidArgumentException(__d('Users', 'Unable to login user with reference {0}', $reference)); - } - } else { - $user = $existingAccount->user; - } - if (!empty($existingAccount)) { - if ($existingAccount->active) { - return $user; - } else { - throw new AccountNotActiveException([ - $existingAccount->provider, - $existingAccount->reference - ]); - } - } - return false; - } - - /** - * Creates social user - * @param array $data Array social user. - * @param array $options Array option data. - * @return bool|EntityInterface|mixed - * - * @todo: move into new behavior - * @todo: Improve docblock - */ - protected function _createSocialUser($data, $options = []) - { - $useEmail = Hash::get($options, 'use_email'); - $validateEmail = Hash::get($options, 'validate_email'); - $tokenExpiration = Hash::get($options, 'token_expiration'); - if ($useEmail && empty($data->email)) { - throw new MissingEmailException(__d('Users', 'Email not present')); - } else { - $existingUser = $this->find() - ->where([$this->alias() . '.email' => $data->email]) - ->first(); - } - $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); - $this->isValidateEmail = $validateEmail; - $result = $this->save($user); - return $result; - } - - /** - * @param array $data Array social login. - * @param string $existingUser user data. - * @param string $useEmail email to use. - * @param string $validateEmail email to validate. - * @param string $tokenExpiration token_expires data. - * @return EntityInterface|\Cake\ORM\Entity - */ - protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) - { - $accountData['provider'] = $data->provider; - $accountData['username'] = Hash::get($data->info, 'nickname'); - $accountData['reference'] = $data->uid; - $accountData['avatar'] = Hash::get($data->info, 'image'); - /* @todo make a pull request to Opauth Facebook Strategy because it does not include link on info array */ - if ($data->provider == SocialAccountsTable::PROVIDER_TWITTER) { - $accountData['link'] = Hash::get($data->info, 'urls.twitter'); - } elseif ($data->provider == SocialAccountsTable::PROVIDER_FACEBOOK) { - $accountData['link'] = Hash::get($data->raw, 'link'); - } - $accountData['avatar'] = str_replace('square', 'large', $accountData['avatar']); - $accountData['description'] = Hash::get($data->info, 'description'); - $accountData['token'] = Hash::get((array)$data->credentials, 'token'); - $accountData['token_secret'] = Hash::get((array)$data->credentials, 'secret'); - $accountData['token_expires'] = !empty(Hash::get((array)$data->credentials, 'expires')) ? (new DateTime(Hash::get((array)$data->credentials, 'expires')))->format('Y-m-d H:i:s') : null; - $accountData['data'] = serialize($data->raw); - $accountData['active'] = true; - - if (empty($existingUser)) { - if (!empty($data->info['first_name']) && !empty($data->info['last_name'])) { - $userData['first_name'] = Hash::get($data->info, 'first_name'); - $userData['last_name'] = Hash::get($data->info, 'last_name'); - } else { - $name = explode(' ', $data->name); - $userData['first_name'] = Hash::get($name, 0); - array_shift($name); - $userData['last_name'] = implode(' ', $name); - } - $userData['username'] = Hash::get($data->info, 'nickname'); - if (empty(Hash::get($userData, 'username'))) { - if (!empty($data->email)) { - $email = explode('@', $data->email); - $userData['username'] = Hash::get($email, 0); - } else { - $firstName = Hash::get($userData, 'first_name'); - $lastName = Hash::get($userData, 'last_name'); - $userData['username'] = strtolower($firstName . $lastName); - $userData['username'] = preg_replace('/[^A-Za-z0-9]/i', '', Hash::get($userData, 'username')); - } - - } - $userData['username'] = $this->_generateUsername(Hash::get($userData, 'username')); - if ($useEmail) { - $userData['email'] = $data->email; - if (!$data->validated) { - $accountData['active'] = false; - } - } - $userData['password'] = $this->randomString(); - $userData['avatar'] = Hash::get($data->info, 'image'); - $userData['validated'] = $data->validated; - $this->_updateActive($userData, false, $tokenExpiration); - $userData['tos_date'] = date("Y-m-d H:i:s"); - $userData['gender'] = Hash::get($data->raw, 'gender'); - $userData['timezone'] = Hash::get($data->raw, 'timezone'); - $userData['social_accounts'][] = $accountData; - $user = $this->newEntity($userData, ['associated' => ['SocialAccounts']]); - } else { - if ($useEmail && !$data->validated) { - $accountData['active'] = false; - } - $user = $this->patchEntity($existingUser, [ - 'social_accounts' => [$accountData] - ], ['associated' => ['SocialAccounts']]); - } - return $user; - } - - /** - * Send the validation email to the newly registered user - * - * @param EntityInterface $user User entity - * @param Email $email instance, if null the default email configuration with the - * Users.validation template will be used, so set a ->template() if you pass an Email - * instance - * @return array email send result - */ - public function sendValidationEmail(EntityInterface $user, Email $email = null) - { - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $subject = __d('Users', '{0}Your account validation link', $firstName); - return $this->getEmailInstance($email) - ->to($user['email']) - ->subject($subject) - ->viewVars($user->toArray()) - ->send(); - } - - /** - * Send the reset password email - * - * @param EntityInterface $user User entity - * @param Email $email instance, if null the default email configuration with the - * Users.validation template will be used, so set a ->template() if you pass an Email - * instance - * @return array email send result - */ - public function sendResetPasswordEmail(EntityInterface $user, Email $email = null) - { - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $subject = __d('Users', '{0}Your reset password link', $firstName); - return $this->getEmailInstance($email) - ->template('Users.reset_password') - ->to($user['email']) - ->subject($subject) - ->viewVars($user->toArray()) - ->send(); - } - - /** - * Change password method - * - * @param User $user user data. - * @return mixed - * @internal param $data - */ - public function changePassword($user) - { - $currentUser = $this->get($user->id, [ - 'contain' => [] - ]); - - if (!empty($user->current_password)) { - if (!$user->checkPassword($user->current_password, $currentUser->password)) { - throw new WrongPasswordException(__d('Users', 'The old password does not match')); - } - } - $user = $this->save($user); - if (!empty($user)) { - $user = $this->_removesValidationToken($user); - } - return $user; - } - /** * Get or initialize the email instance. Used for mocking. * From 9164c87e3eab380fac302c6e0d1380908268e8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2015 11:25:35 +0100 Subject: [PATCH 0155/1476] fix validate email link typo --- src/Controller/Component/UsersAuthComponent.php | 2 +- src/Model/Entity/User.php | 2 +- src/Template/Email/html/reset_password.ctp | 2 +- src/Template/Email/html/validation.ctp | 2 +- src/Template/Email/text/reset_password.ctp | 2 +- src/Template/Email/text/validation.ctp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index d5aa71a77..12c98bdb5 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -102,7 +102,7 @@ protected function _initAuth() $this->_registry->getController()->Auth->allow([ 'register', - 'validate', + 'validateEmail', 'resendTokenValidation', 'login', 'socialEmail', diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index dde309c96..4d8b7d7e9 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -107,7 +107,7 @@ protected function _getAvatar() public function updateToken($tokenExpiration) { $expires = new DateTime(); - $expires->modify(sprintf('+ {0} secs', $tokenExpiration)); + $expires->modify("+ $tokenExpiration secs"); $this->token_expires = $expires; $this->token = str_replace('-', '', Text::uuid()); } diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp index 189946af7..d5bf7cc2b 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'resetPassword', isset($token) ? $token : '' ]; ?> diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index 1418f3cdf..af78b62bc 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'validateEmail', isset($token) ? $token : '' ]; ?> diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp index f57f61e1f..79a74e385 100644 --- a/src/Template/Email/text/reset_password.ctp +++ b/src/Template/Email/text/reset_password.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'resetPassword', isset($token) ? $token : '' ]; ?> diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp index f57f61e1f..26503c9cd 100644 --- a/src/Template/Email/text/validation.ctp +++ b/src/Template/Email/text/validation.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'validateEmail', isset($token) ? $token : '' ]; ?> From 05d0a5ffd2c3690450cec12db293793b8274663f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2015 11:25:57 +0100 Subject: [PATCH 0156/1476] refs #refactor-behavior fix uses --- src/Model/Table/UsersTable.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 0a0cc48c2..85e61b7e2 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -19,8 +19,10 @@ use Cake\Validation\Validator; use Users\Exception\WrongPasswordException; use Users\Model\Entity\User; +use Users\Model\Table\Traits\PasswordManagementTrait; use Users\Model\Table\Traits\RegisterTrait; use Users\Model\Table\Traits\SocialTrait; +use Users\Traits\RandomStringTrait; /** * Users Model From d24e6b124d5d8e8b0737bddc9aca92776248e892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2015 11:25:35 +0100 Subject: [PATCH 0157/1476] fix typos in sendEmail and validate function calls --- src/Controller/Component/UsersAuthComponent.php | 2 +- src/Controller/Traits/PasswordManagementTrait.php | 2 +- src/Model/Entity/User.php | 14 ++++++++++++++ src/Template/Email/html/reset_password.ctp | 2 +- src/Template/Email/html/validation.ctp | 2 +- src/Template/Email/text/reset_password.ctp | 2 +- src/Template/Email/text/validation.ctp | 2 +- 7 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index d5aa71a77..12c98bdb5 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -102,7 +102,7 @@ protected function _initAuth() $this->_registry->getController()->Auth->allow([ 'register', - 'validate', + 'validateEmail', 'resendTokenValidation', 'login', 'socialEmail', diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 4968c5fa2..e670b42bf 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -91,7 +91,7 @@ public function requestResetPassword() $resetUser = $this->getUsersTable()->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => false, - 'sendMail' => true, + 'sendEmail' => true, ]); if ($resetUser) { $msg = __d('Users', 'Please check your email to continue with password reset process'); diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index f1c00f924..ba4893b62 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -95,4 +95,18 @@ protected function _getAvatar() } return $avatar; } + + /** + * Generate token_expires and token in a user + * @param string $tokenExpiration new token_expires user. + * + * @return void + */ + public function updateToken($tokenExpiration) + { + $expires = new DateTime(); + $expires->modify("+ $tokenExpiration secs"); + $this->token_expires = $expires; + $this->token = str_replace('-', '', Text::uuid()); + } } diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp index 189946af7..d5bf7cc2b 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'resetPassword', isset($token) ? $token : '' ]; ?> diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index 1418f3cdf..af78b62bc 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'validateEmail', isset($token) ? $token : '' ]; ?> diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp index f57f61e1f..79a74e385 100644 --- a/src/Template/Email/text/reset_password.ctp +++ b/src/Template/Email/text/reset_password.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'resetPassword', isset($token) ? $token : '' ]; ?> diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp index f57f61e1f..26503c9cd 100644 --- a/src/Template/Email/text/validation.ctp +++ b/src/Template/Email/text/validation.ctp @@ -13,7 +13,7 @@ $activationUrl = [ '_full' => true, 'plugin' => 'Users', 'controller' => 'Users', - 'action' => 'activate', + 'action' => 'validateEmail', isset($token) ? $token : '' ]; ?> From cfae01b0af50b4250d4a0c47e83dfbfbba19aab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2015 11:44:28 +0100 Subject: [PATCH 0158/1476] fix unit test --- tests/TestCase/Model/Table/UsersTableTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 4885b27a7..6d135850d 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -353,7 +353,7 @@ public function testSendValidationEmail() Hi FirstName, -Please copy the following address in your web browser http://users.test/users/users/activate/12345 +Please copy the following address in your web browser http://users.test/users/users/validate-email/12345 Thank you, ', $result['message']); $this->assertTextContains('Content-Type: text/html; charset=UTF-8 @@ -369,10 +369,10 @@ public function testSendValidationEmail() Hi FirstName,

- Activate your account here + Activate your account here

- If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/activate/12345

+ If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/validate-email/12345

Thank you,

@@ -405,7 +405,7 @@ public function testSendResetPasswordEmail() Hi FirstName, -Please copy the following address in your web browser http://users.test/users/users/activate/12345 +Please copy the following address in your web browser http://users.test/users/users/reset-password/12345 Thank you, ', $result['message']); $this->assertTextContains('Content-Type: text/html; charset=UTF-8 @@ -421,10 +421,10 @@ public function testSendResetPasswordEmail() Hi FirstName,

- Reset your password here + Reset your password here

- If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/activate/12345

+ If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/reset-password/12345

Thank you,

From 2408a95ac308f4805f0a4b1e21a6a0723bfa5e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2015 11:46:32 +0100 Subject: [PATCH 0159/1476] delete vendor files --- .gitignore | 1 + vendor/autoload.php | 7 - vendor/composer/ClassLoader.php | 413 ------------------------ vendor/composer/autoload_classmap.php | 9 - vendor/composer/autoload_namespaces.php | 9 - vendor/composer/autoload_psr4.php | 13 - vendor/composer/autoload_real.php | 50 --- 7 files changed, 1 insertion(+), 501 deletions(-) create mode 100644 .gitignore delete mode 100644 vendor/autoload.php delete mode 100644 vendor/composer/ClassLoader.php delete mode 100644 vendor/composer/autoload_classmap.php delete mode 100644 vendor/composer/autoload_namespaces.php delete mode 100644 vendor/composer/autoload_psr4.php delete mode 100644 vendor/composer/autoload_real.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..61ead8666 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor diff --git a/vendor/autoload.php b/vendor/autoload.php deleted file mode 100644 index d5769936c..000000000 --- a/vendor/autoload.php +++ /dev/null @@ -1,7 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Autoload; - -/** - * ClassLoader implements a PSR-0 class loader - * - * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md - * - * $loader = new \Composer\Autoload\ClassLoader(); - * - * // register classes with namespaces - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (eg. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * This class is loosely based on the Symfony UniversalClassLoader. - * - * @author Fabien Potencier - * @author Jordi Boggiano - */ -class ClassLoader -{ - // PSR-4 - private $prefixLengthsPsr4 = array(); - private $prefixDirsPsr4 = array(); - private $fallbackDirsPsr4 = array(); - - // PSR-0 - private $prefixesPsr0 = array(); - private $fallbackDirsPsr0 = array(); - - private $useIncludePath = false; - private $classMap = array(); - - private $classMapAuthoritative = false; - - public function getPrefixes() - { - if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); - } - - return array(); - } - - public function getPrefixesPsr4() - { - return $this->prefixDirsPsr4; - } - - public function getFallbackDirs() - { - return $this->fallbackDirsPsr0; - } - - public function getFallbackDirsPsr4() - { - return $this->fallbackDirsPsr4; - } - - public function getClassMap() - { - return $this->classMap; - } - - /** - * @param array $classMap Class to filename map - */ - public function addClassMap(array $classMap) - { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, either - * appending or prepending to the ones previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - */ - public function add($prefix, $paths, $prepend = false) - { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirsPsr0 = array_merge( - (array) $paths, - $this->fallbackDirsPsr0 - ); - } else { - $this->fallbackDirsPsr0 = array_merge( - $this->fallbackDirsPsr0, - (array) $paths - ); - } - - return; - } - - $first = $prefix[0]; - if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; - - return; - } - if ($prepend) { - $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, - $this->prefixesPsr0[$first][$prefix] - ); - } else { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $this->prefixesPsr0[$first][$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, either - * appending or prepending to the ones previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-0 base directories - * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException - */ - public function addPsr4($prefix, $paths, $prepend = false) - { - if (!$prefix) { - // Register directories for the root namespace. - if ($prepend) { - $this->fallbackDirsPsr4 = array_merge( - (array) $paths, - $this->fallbackDirsPsr4 - ); - } else { - $this->fallbackDirsPsr4 = array_merge( - $this->fallbackDirsPsr4, - (array) $paths - ); - } - } elseif (!isset($this->prefixDirsPsr4[$prefix])) { - // Register directories for a new namespace. - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } elseif ($prepend) { - // Prepend directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, - $this->prefixDirsPsr4[$prefix] - ); - } else { - // Append directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $this->prefixDirsPsr4[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, - * replacing any others previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories - */ - public function set($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr0 = (array) $paths; - } else { - $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, - * replacing any others previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException - */ - public function setPsr4($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr4 = (array) $paths; - } else { - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - includeFile($file); - - return true; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|false The path if found, false otherwise - */ - public function findFile($class) - { - // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 - if ('\\' == $class[0]) { - $class = substr($class, 1); - } - - // class map lookup - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - if ($this->classMapAuthoritative) { - return false; - } - - $file = $this->findFileWithExtension($class, '.php'); - - // Search for Hack files if we are running on HHVM - if ($file === null && defined('HHVM_VERSION')) { - $file = $this->findFileWithExtension($class, '.hh'); - } - - if ($file === null) { - // Remember that this class does not exist. - return $this->classMap[$class] = false; - } - - return $file; - } - - private function findFileWithExtension($class, $ext) - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; - - $first = $class[0]; - if (isset($this->prefixLengthsPsr4[$first])) { - foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { - if (0 === strpos($class, $prefix)) { - foreach ($this->prefixDirsPsr4[$prefix] as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { - return $file; - } - } - } - } - } - - // PSR-4 fallback dirs - foreach ($this->fallbackDirsPsr4 as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { - return $file; - } - } - - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; - } - - if (isset($this->prefixesPsr0[$first])) { - foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - - // PSR-0 fallback dirs - foreach ($this->fallbackDirsPsr0 as $dir) { - if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - - // PSR-0 include paths. - if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { - return $file; - } - } -} - -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; -} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php deleted file mode 100644 index 7a91153b0..000000000 --- a/vendor/composer/autoload_classmap.php +++ /dev/null @@ -1,9 +0,0 @@ - array($baseDir . '/tests/Fixture'), - 'Users\\Test\\' => array($baseDir . '/tests'), - 'Users\\' => array($baseDir . '/src'), - 'Cake\\Test\\' => array($vendorDir . '/cakephp/cakephp/tests'), -); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php deleted file mode 100644 index 013eec028..000000000 --- a/vendor/composer/autoload_real.php +++ /dev/null @@ -1,50 +0,0 @@ - $path) { - $loader->set($namespace, $path); - } - - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } - - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - - $loader->register(true); - - return $loader; - } -} - -function composerRequirecba08b9a106a578f9888716a0bffe4ed($file) -{ - require $file; -} From dd3e5e1c1fc3bc8b1b1ff8e0c7243e1068b4806b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 13 Aug 2015 09:08:06 +0100 Subject: [PATCH 0160/1476] refs #refactor-behavior fix uses --- src/Model/Table/Traits/PasswordManagementTrait.php | 8 ++++++++ src/Model/Table/Traits/SocialTrait.php | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/Model/Table/Traits/PasswordManagementTrait.php b/src/Model/Table/Traits/PasswordManagementTrait.php index 957d625e4..d424255bd 100644 --- a/src/Model/Table/Traits/PasswordManagementTrait.php +++ b/src/Model/Table/Traits/PasswordManagementTrait.php @@ -11,6 +11,14 @@ namespace Users\Model\Table\Traits; +use Cake\Datasource\EntityInterface; +use Cake\Network\Email\Email; +use Cake\Utility\Hash; +use InvalidArgumentException; +use Users\Exception\UserAlreadyActiveException; +use Users\Exception\UserNotFoundException; +use Users\Exception\WrongPasswordException; + /** * Password management features * diff --git a/src/Model/Table/Traits/SocialTrait.php b/src/Model/Table/Traits/SocialTrait.php index 219106817..0599ef830 100644 --- a/src/Model/Table/Traits/SocialTrait.php +++ b/src/Model/Table/Traits/SocialTrait.php @@ -11,6 +11,14 @@ namespace Users\Model\Table\Traits; +use Cake\Datasource\EntityInterface; +use Cake\Utility\Hash; +use DateTime; +use InvalidArgumentException; +use Users\Exception\AccountNotActiveException; +use Users\Exception\MissingEmailException; +use Users\Model\Table\SocialAccountsTable; + /** * Covers social features * From 107a139dc2956f9fc82f56af0eadedf50e345288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 13 Aug 2015 10:23:03 +0100 Subject: [PATCH 0161/1476] refs #refactor-behavior moved tests to the trait --- .../Table/Traits/PasswordManagementTrait.php | 13 +- .../Traits/PasswordManagementTraitTest.php | 158 ++++++++++++++++++ tests/TestCase/Model/Table/UsersTableTest.php | 53 ------ 3 files changed, 170 insertions(+), 54 deletions(-) create mode 100644 tests/TestCase/Model/Table/Traits/PasswordManagementTraitTest.php diff --git a/src/Model/Table/Traits/PasswordManagementTrait.php b/src/Model/Table/Traits/PasswordManagementTrait.php index d424255bd..188ac9332 100644 --- a/src/Model/Table/Traits/PasswordManagementTrait.php +++ b/src/Model/Table/Traits/PasswordManagementTrait.php @@ -46,7 +46,7 @@ public function resetToken($reference, array $options = []) throw new InvalidArgumentException(__d('Users', "Token expiration cannot be null")); } - $user = $this->findAllByUsernameOrEmail($reference, $reference)->first(); + $user = $this->_getUser($reference); if (empty($user)) { throw new UserNotFoundException(__d('Users', "User not found")); @@ -66,6 +66,17 @@ public function resetToken($reference, array $options = []) return $saveResult; } + /** + * Get the user by email or username + * + * @param string $reference reference could be either an email or username + * @return mixed user entity if found + */ + protected function _getUser($reference) + { + return $this->findAllByUsernameOrEmail($reference, $reference)->first(); + } + /** * Send the reset password email * diff --git a/tests/TestCase/Model/Table/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Model/Table/Traits/PasswordManagementTraitTest.php new file mode 100644 index 000000000..abdaa8fcc --- /dev/null +++ b/tests/TestCase/Model/Table/Traits/PasswordManagementTraitTest.php @@ -0,0 +1,158 @@ +Trait = $this->getMockBuilder('Users\Model\Table\Traits\PasswordManagementTrait') + ->setMethods(['_getUser', 'save', 'sendResetPasswordEmail']) + ->getMockForTrait(); + $this->user = TableRegistry::get('Users.Users')->findAllByUsername('user-1')->first(); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->Trait, $this->user); + parent::tearDown(); + } + + + /** + * Test resetToken + * + */ + public function testResetToken() + { + $token = $this->user->token; + $this->Trait->expects($this->once()) + ->method('_getUser') + ->with('user-1') + ->will($this->returnValue($this->user)); + $this->Trait->expects($this->once()) + ->method('save') + ->will($this->returnValue($this->user)); + $this->Trait->expects($this->never()) + ->method('sendResetPasswordEmail') + ->with($this->user); + $result = $this->Trait->resetToken('user-1', [ + 'expiration' => 3600, + 'checkActive' => true, + ]); + $this->assertNotEquals($token, $result->token); + $this->assertEmpty($result->activation_date); + $this->assertFalse($result->active); + } + + /** + * Test resetToken + * + */ + public function testResetTokenSendEmail() + { + $token = $this->user->token; + $this->Trait->expects($this->once()) + ->method('_getUser') + ->with('user-1') + ->will($this->returnValue($this->user)); + $this->Trait->expects($this->once()) + ->method('save') + ->will($this->returnValue($this->user)); + $this->Trait->expects($this->once()) + ->method('sendResetPasswordEmail') + ->with($this->user); + $result = $this->Trait->resetToken('user-1', [ + 'expiration' => 3600, + 'checkActive' => true, + 'sendEmail' => true + ]); + $this->assertNotEquals($token, $result->token); + $this->assertEmpty($result->activation_date); + $this->assertFalse($result->active); + } + + /** + * Test resetToken + * + * @expectedException InvalidArgumentException + */ + public function testResetTokenWithNullParams() + { + $this->Trait->resetToken(null); + } + + /** + * Test resetToken + * + * @expectedException Users\Exception\UserNotFoundException + */ + public function testResetTokenNotExistingUser() + { + $this->Trait->resetToken('user-not-found', [ + 'expiration' => 3600 + ]); + } + + /** + * Test resetToken + * + * @expectedException Users\Exception\UserAlreadyActiveException + */ + public function testResetTokenUserAlreadyActive() + { + $activeUser = TableRegistry::get('Users.Users')->findAllByUsername('user-4')->first(); + $this->Trait->expects($this->once()) + ->method('_getUser') + ->with('user-4') + ->will($this->returnValue($activeUser)); + $this->Trait->expects($this->never()) + ->method('save') + ->will($this->returnValue($this->user)); + $this->Trait->expects($this->never()) + ->method('sendResetPasswordEmail') + ->with($this->user); + $this->Trait->resetToken('user-4', [ + 'expiration' => 3600, + 'checkActive' => true, + ]); + } +} diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 6d135850d..41bd1c409 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -167,59 +167,6 @@ public function testActivateUser() $this->assertTrue($result->active); } - /** - * Test resetToken - * - */ - public function testResetToken() - { - $user = $this->Users->findAllByUsername('user-1')->first(); - $result = $this->Users->resetToken('user-1', [ - 'expiration' => 3600, - 'checkActive' => true, - ]); - $this->assertNotEmpty($result->token); - $this->assertNotEquals($user->token, $result->token); - $this->assertNotEmpty($result->token_expires); - $this->assertEmpty($result->activation_date); - $this->assertFalse($result->active); - } - - /** - * Test resetToken - * - * @expectedException InvalidArgumentException - */ - public function testResetTokenWithNullParams() - { - $this->Users->resetToken(null); - } - - /** - * Test resetToken - * - * @expectedException \Users\Exception\UserNotFoundException - */ - public function testResetTokenNonExistentUser() - { - $this->Users->resetToken('user-not-found', [ - 'expiration' => 3600 - ]); - } - - /** - * Test resetToken - * - * @expectedException \Users\Exception\UserAlreadyActiveException - */ - public function testResetTokenUserAlreadyActive() - { - $this->Users->resetToken('user-4', [ - 'expiration' => 3600, - 'checkActive' => true, - ]); - } - public function testSocialLogin() { $raw = [ From 2bae3324c21dad09e7acdb1c5dd33ba59b63c735 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 14 Aug 2015 10:00:37 -0500 Subject: [PATCH 0162/1476] Fix social tests --- tests/Fixture/SocialAccountsFixture.php | 12 ++++++------ .../Model/Table/SocialAccountsTableTest.php | 17 +++++------------ tests/TestCase/Model/Table/UsersTableTest.php | 8 ++++++-- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 71ace2aa4..21d9c3c0a 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -19,7 +19,7 @@ class SocialAccountsFixture extends TestFixture public $fields = [ 'id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'user_id' => ['type' => 'string', 'length' => 36, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'provider' => ['type' => 'integer', 'length' => 2, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => 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], @@ -50,7 +50,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 1, 'user_id' => 1, - 'provider' => 1, + 'provider' => 'Facebook', 'username' => 'user-1-fb', 'reference' => 'reference-1-1234', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -66,7 +66,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 2, 'user_id' => 1, - 'provider' => 2, + 'provider' => 'Twitter', 'username' => 'user-1-tw', 'reference' => 'reference-1-1234', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -82,7 +82,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 3, 'user_id' => 2, - 'provider' => 1, + 'provider' => 'Facebook', 'username' => 'user-2-fb', 'reference' => 'reference-2-1', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -98,7 +98,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 4, 'user_id' => 3, - 'provider' => 2, + 'provider' => 'Twitter', 'username' => 'user-2-tw', 'reference' => 'reference-2-2', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -114,7 +114,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 5, 'user_id' => 4, - 'provider' => 2, + 'provider' => 'Twitter', 'username' => 'user-2-tw', 'reference' => 'reference-2-2', 'avatar' => 'Lorem ipsum dolor sit amet', diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index 09c70e944..a9cf95631 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -16,6 +16,7 @@ use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; +use Users\Model\Table\SocialAccountsTable; use Users\Model\Table\UsersTable; /** @@ -76,7 +77,7 @@ public function tearDown() public function testValidateEmail() { $token = 'token-1234'; - $result = $this->SocialAccounts->validateAccount(1, 'reference-1-1234', $token); + $result = $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_FACEBOOK, 'reference-1-1234', $token); $this->assertTrue($result->active); $this->assertEquals($token, $result->token); } @@ -108,7 +109,7 @@ public function testValidateEmailInvalidUser() */ public function testValidateEmailActiveAccount() { - $this->SocialAccounts->validateAccount(2, 'reference-1-1234', 'token-1234'); + $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); } /** @@ -183,16 +184,8 @@ public function testSendSocialValidationEmail() $this->assertTextContains('From: test@example.com', $result['headers']); $this->assertTextContains('To: user-1@test.com', $result['headers']); $this->assertTextContains('Subject: first1, Your social account validation link', $result['headers']); - $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Hi first1, - -Please copy the following address in your web browser to activate your social login http://users.test/users/social-accounts/validate-account/1/reference-1-1234/token-1234 -Thank you, -', $result['message']); $this->assertTextContains('Hi first1,', $result['message']); - $this->assertTextContains('Activate your social login here', $result['message']); - $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/1/reference-1-1234/token-1234', $result['message']); + $this->assertTextContains('Activate your social login here', $result['message']); + $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234', $result['message']); } } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 41bd1c409..9b419c505 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -167,14 +167,15 @@ public function testActivateUser() $this->assertTrue($result->active); } - public function testSocialLogin() + public function testSocialLoginExistingAccount() { $raw = [ 'id' => 'reference-2-1', 'first_name' => 'User 2', 'gender' => 'female', 'verified' => 1, - 'user_email' => 'hello@test.com', + 'user_email' => 'user-2@test.com', + 'link' => 'link' ]; $data = new Response(SocialAccountsTable::PROVIDER_FACEBOOK, $raw); $data->setData('uid', 'id'); @@ -250,12 +251,15 @@ public function testSocialLoginCreateNewAccount() 'last_name' => 'Last Name', 'gender' => 'male', 'user_email' => 'user@test.com', + 'twitter' => 'link' ]; $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); $data->setData('uid', 'id'); $data->setData('info.first_name', 'first_name'); $data->setData('info.last_name', 'last_name'); + $data->setData('info.urls.twitter', 'twitter'); + $data->email = 'username@test.com'; $data->credentials = [ 'token' => 'token', From 8a275fa1de9b029f75bd76b73fcd71e537a24adc Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 14 Aug 2015 08:29:47 -0500 Subject: [PATCH 0163/1476] Add doc for user helper --- Docs/Documentation/UserHelper.md | 65 ++++++++++++++++++++++++++++++++ Docs/Home.md | 1 + 2 files changed, 66 insertions(+) create mode 100644 Docs/Documentation/UserHelper.md diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md new file mode 100644 index 000000000..9abfce96d --- /dev/null +++ b/Docs/Documentation/UserHelper.md @@ -0,0 +1,65 @@ +UserHelper +============= + +The User Helper has some methods that may be needed if you want to improve your templates and add features to your app in an easy way. + +Setup +--------------- + +The User Helper just need some Configure variables to function properly. + +Social Login +----------------- + +You can use the helper included with the plugin to create Facebook/Twitter buttons: + +In templates +```php +$this->User->facebookLogin(); + +$this->User->twitterLogin(); +``` + +We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. + +Logout link +----------------- + +It allows to add a logout link anywhere in the app. + +```php +$this->User->logout(); +``` + +RBAC link +----------------- + +This function validates if you have access to a link and it displays it based on that. + +```php +$this->User->link(); +``` + +Welcome and profile link +----------------- + +It displays a welcome message for the user including the name and a link to the profile page + +```php +$this->User->welcome(); +``` + +reCAPTCHA +----------------- + +If you have configured reCAPTCHA for registration and have the proper key/secret configured then you will see the reCAPTCHA in registration page automatically. + +You could also use it in another templates with the following methods: + +```php +$this->User->addReCaptchaScript(); + +$this->User->addReCaptcha(); +``` + +Note that the script is added automatically if the feature is enabled in config. \ No newline at end of file diff --git a/Docs/Home.md b/Docs/Home.md index fb4c810d3..f4f35761d 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -26,5 +26,6 @@ Documentation * [SimpleRbacAuthorize](Documentation/SimpleRbacAuthorize.md) * [SuperuserAuthorize](Documentation/SuperuserAuthorize.md) * [SocialAuthenticate](Documentation/SocialAuthenticate.md) +* [UserHelper](Documentation/UserHelper.md) * [Events](Documentation/Events.md) * [Extending the Plugin](Documentation/Extending-the-Plugin.md) From 3c806fa0a01d6ebcc4b1f9b342a8d347c219bd9f Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Thu, 13 Aug 2015 16:53:44 -0500 Subject: [PATCH 0164/1476] Add reCAPTCHA to registration --- Docs/Documentation/Configuration.md | 2 ++ Docs/Documentation/Overview.md | 1 + composer.json | 3 +- config/users.php | 2 ++ src/Controller/Traits/ReCaptchaTrait.php | 42 ++++++++++++++++++++++++ src/Controller/Traits/RegisterTrait.php | 18 ++++++++-- src/Template/Users/register.ctp | 1 + src/View/Helper/UserHelper.php | 28 +++++++++++++++- 8 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 src/Controller/Traits/ReCaptchaTrait.php diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 70b2d96f7..0f301a047 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -74,6 +74,8 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'Registration' => [ //determines if the register is enabled 'active' => true, + //determines if the reCAPTCHA is enabled for registration + 'reCAPTCHA' => true, ], 'Tos' => [ //determines if the user should include tos accepted diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md index 5974a3666..dc6fd1673 100644 --- a/Docs/Documentation/Overview.md +++ b/Docs/Documentation/Overview.md @@ -14,4 +14,5 @@ The plugin itself is already capable of: * Simple roles management * Simple Rbac and SuperUser Authorize * RememberMe using cookie feature +* reCAPTCHA for user registration diff --git a/composer.json b/composer.json index 4cb651e03..d8b5834f6 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "suggest": { "opauth/opauth": "Used for Social Login, if you add Opauth, remember adding at least one strategy too", "opauth/facebook": "Provide Social Login: Facebook Strategy, requires Opauth", - "opauth/twitter": "Provide Social Login: Twitter Strategy, requires Opauth" + "opauth/twitter": "Provide Social Login: Twitter Strategy, requires Opauth", + "google/recaptcha": "Provide reCAPTCHA validation for registration form" }, "autoload": { "psr-4": { diff --git a/config/users.php b/config/users.php index cc73fdc6d..07c362969 100644 --- a/config/users.php +++ b/config/users.php @@ -28,6 +28,8 @@ 'Registration' => [ //determines if the register is enabled 'active' => true, + //determines if the reCAPTCHA is enabled for registration + 'reCAPTCHA' => true, ], 'Tos' => [ //determines if the user should include tos accepted diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php new file mode 100644 index 000000000..9e8e21fff --- /dev/null +++ b/src/Controller/Traits/ReCaptchaTrait.php @@ -0,0 +1,42 @@ +verify($recaptchaResponse, $clientIp); + $validReCaptcha = $response->isSuccess(); + } + return $validReCaptcha; + } +} diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 5fc9f29ef..874dd15e2 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -23,6 +23,7 @@ trait RegisterTrait { use PasswordManagementTrait; + use ReCaptchaTrait; /** * Register a new user @@ -49,6 +50,7 @@ public function register() 'usersTable' => $usersTable, 'options' => $options, ]); + if ($event->result instanceof EntityInterface) { $options['validator'] = 'default'; if ($userSaved = $usersTable->register($user, $event->result->toArray(), $options)) { @@ -60,12 +62,22 @@ public function register() } if ($this->request->is('post')) { - if ($userSaved = $usersTable->register($user, $requestData, $options)) { - return $this->_afterRegister($userSaved); + $validReCaptcha = $this->validateReCaptcha( + $this->request->data('g-recaptcha-response'), + $this->request->clientIp() + ); + if ($validReCaptcha) { + if ($userSaved = $usersTable->register($user, $requestData, $options)) { + return $this->_afterRegister($userSaved); + } else { + $this->Flash->error(__d('Users', 'The user could not be saved')); + } } else { - $this->Flash->error(__d('Users', 'The user could not be saved')); + $this->Flash->error(__d('Users', 'The reCAPTCHA could not be validated')); } } + + $this->set(compact('user')); $this->set('_serialize', ['user']); } diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index 6544bb954..24c62e058 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -21,6 +21,7 @@ echo $this->Form->input('first_name'); echo $this->Form->input('last_name'); echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); + echo $this->User->addReCAPTCHA(); ?> Form->button(__d('Users', 'Submit')) ?> diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index b7610b49c..bc1ef4298 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -11,6 +11,7 @@ namespace Users\View\Helper; +use Cake\Core\Configure; use Cake\Event\Event; use Cake\Utility\Hash; use Cake\View\Helper; @@ -22,7 +23,7 @@ class UserHelper extends Helper { - public $helpers = ['Html']; + public $helpers = ['Html', 'Form']; /** * Default configuration. @@ -109,4 +110,29 @@ public function welcome() $label = __d('Users', 'Welcome, {0}', $this->Html->link($this->request->session()->read('Auth.User.first_name'), $profileUrl)); return $this->Html->tag('span', $label, ['class' => 'welcome']); } + + /** + * Add reCAPTCHA script + * @return mixed + */ + public function addReCAPTCHAScript() + { + return $this->Html->script('https://www.google.com/recaptcha/api.js'); + } + + /** + * Add reCAPTCHA to the form + * @return mixed + */ + public function addReCAPTCHA() + { + if (!Configure::check('Users.Registration.reCAPTCHA')) { + return false; + } + $this->Form->unlockField('g-recaptcha-response'); + return $this->Html->tag('div', '', [ + 'class' => 'g-recaptcha', + 'data-sitekey' => Configure::read('reCAPTCHA.key') + ]); + } } From 6570ea28fb5685d83f80617662d6b204756b4eb5 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 14 Aug 2015 10:00:37 -0500 Subject: [PATCH 0165/1476] Fix social tests --- tests/Fixture/SocialAccountsFixture.php | 12 ++++++------ .../Model/Table/SocialAccountsTableTest.php | 17 +++++------------ tests/TestCase/Model/Table/UsersTableTest.php | 8 ++++++-- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 71ace2aa4..21d9c3c0a 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -19,7 +19,7 @@ class SocialAccountsFixture extends TestFixture public $fields = [ 'id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'user_id' => ['type' => 'string', 'length' => 36, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'provider' => ['type' => 'integer', 'length' => 2, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => 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], @@ -50,7 +50,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 1, 'user_id' => 1, - 'provider' => 1, + 'provider' => 'Facebook', 'username' => 'user-1-fb', 'reference' => 'reference-1-1234', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -66,7 +66,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 2, 'user_id' => 1, - 'provider' => 2, + 'provider' => 'Twitter', 'username' => 'user-1-tw', 'reference' => 'reference-1-1234', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -82,7 +82,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 3, 'user_id' => 2, - 'provider' => 1, + 'provider' => 'Facebook', 'username' => 'user-2-fb', 'reference' => 'reference-2-1', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -98,7 +98,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 4, 'user_id' => 3, - 'provider' => 2, + 'provider' => 'Twitter', 'username' => 'user-2-tw', 'reference' => 'reference-2-2', 'avatar' => 'Lorem ipsum dolor sit amet', @@ -114,7 +114,7 @@ class SocialAccountsFixture extends TestFixture [ 'id' => 5, 'user_id' => 4, - 'provider' => 2, + 'provider' => 'Twitter', 'username' => 'user-2-tw', 'reference' => 'reference-2-2', 'avatar' => 'Lorem ipsum dolor sit amet', diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index 09c70e944..a9cf95631 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -16,6 +16,7 @@ use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; +use Users\Model\Table\SocialAccountsTable; use Users\Model\Table\UsersTable; /** @@ -76,7 +77,7 @@ public function tearDown() public function testValidateEmail() { $token = 'token-1234'; - $result = $this->SocialAccounts->validateAccount(1, 'reference-1-1234', $token); + $result = $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_FACEBOOK, 'reference-1-1234', $token); $this->assertTrue($result->active); $this->assertEquals($token, $result->token); } @@ -108,7 +109,7 @@ public function testValidateEmailInvalidUser() */ public function testValidateEmailActiveAccount() { - $this->SocialAccounts->validateAccount(2, 'reference-1-1234', 'token-1234'); + $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); } /** @@ -183,16 +184,8 @@ public function testSendSocialValidationEmail() $this->assertTextContains('From: test@example.com', $result['headers']); $this->assertTextContains('To: user-1@test.com', $result['headers']); $this->assertTextContains('Subject: first1, Your social account validation link', $result['headers']); - $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Hi first1, - -Please copy the following address in your web browser to activate your social login http://users.test/users/social-accounts/validate-account/1/reference-1-1234/token-1234 -Thank you, -', $result['message']); $this->assertTextContains('Hi first1,', $result['message']); - $this->assertTextContains('Activate your social login here', $result['message']); - $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/1/reference-1-1234/token-1234', $result['message']); + $this->assertTextContains('Activate your social login here', $result['message']); + $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234', $result['message']); } } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 6d135850d..4834186f8 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -220,14 +220,15 @@ public function testResetTokenUserAlreadyActive() ]); } - public function testSocialLogin() + public function testSocialLoginExistingAccount() { $raw = [ 'id' => 'reference-2-1', 'first_name' => 'User 2', 'gender' => 'female', 'verified' => 1, - 'user_email' => 'hello@test.com', + 'user_email' => 'user-2@test.com', + 'link' => 'link' ]; $data = new Response(SocialAccountsTable::PROVIDER_FACEBOOK, $raw); $data->setData('uid', 'id'); @@ -303,12 +304,15 @@ public function testSocialLoginCreateNewAccount() 'last_name' => 'Last Name', 'gender' => 'male', 'user_email' => 'user@test.com', + 'twitter' => 'link' ]; $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); $data->setData('uid', 'id'); $data->setData('info.first_name', 'first_name'); $data->setData('info.last_name', 'last_name'); + $data->setData('info.urls.twitter', 'twitter'); + $data->email = 'username@test.com'; $data->credentials = [ 'token' => 'token', From dd024884afa88dedea1ab8544806779bf579a244 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 14 Aug 2015 10:48:57 -0500 Subject: [PATCH 0166/1476] Unit test for reCaptcha --- .../Controller/Traits/RecaptchaTraitTest.php | 84 +++++++++++++++++++ tests/TestCase/View/Helper/UserHelperTest.php | 29 ++++++- 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/TestCase/Controller/Traits/RecaptchaTraitTest.php diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php new file mode 100644 index 000000000..34c2472b4 --- /dev/null +++ b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php @@ -0,0 +1,84 @@ +Trait = $this->getMockBuilder('Users\Controller\Traits\ReCaptchaTrait') + ->setMethods(['_getReCaptchaInstance']) + ->getMockForTrait(); + } + + /** + * tearDown callback + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * testValidateValidReCaptcha + * + * @return void + */ + public function testValidateValidReCaptcha() + { + $ReCaptcha = $this->getMock('ReCaptcha\ReCaptcha', ['verify'], [], '', false); + $Response = $this->getMock('ReCaptcha\Response', ['isSuccess'], [], '', false); + $Response->expects($this->any()) + ->method('isSuccess') + ->will($this->returnValue(true)); + $ReCaptcha->expects($this->any()) + ->method('verify') + ->with('value') + ->will($this->returnValue($Response)); + $this->Trait->expects($this->any()) + ->method('_getReCaptchaInstance') + ->will($this->returnValue($ReCaptcha)); + $this->Trait->validateReCaptcha('value', '255.255.255.255'); + } + + /** + * testValidateInvalidReCaptcha + * + * @return void + */ + public function testValidateInvalidReCaptcha() + { + $ReCaptcha = $this->getMock('ReCaptcha\ReCaptcha', ['verify'], [], '', false); + $Response = $this->getMock('ReCaptcha\Response', ['isSuccess'], [], '', false); + $Response->expects($this->any()) + ->method('isSuccess') + ->will($this->returnValue(false)); + $ReCaptcha->expects($this->any()) + ->method('verify') + ->with('invalid') + ->will($this->returnValue($Response)); + $this->Trait->expects($this->any()) + ->method('_getReCaptchaInstance') + ->will($this->returnValue($ReCaptcha)); + $this->Trait->validateReCaptcha('invalid', '255.255.255.255'); + } +} diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 3c775e3f7..342d27aea 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -32,8 +32,8 @@ public function setUp() { parent::setUp(); Router::connect(':plugin/:controller/:action'); - $view = new View(); - $this->User = new UserHelper($view); + $this->View = $this->getMock('Cake\View\View', ['append']); + $this->User = new UserHelper($this->View); $this->request = new \Cake\Network\Request(); } @@ -192,4 +192,29 @@ public function testWelcomeNotLoggedInUser() $result = $this->User->welcome(); $this->assertEmpty($result); } + + /** + * Test add ReCaptcha field + * + * @return void + */ + public function testAddReCaptcha() + { + $result = $this->User->addReCaptcha(); + $this->assertEquals('
', $result); + } + + + /** + * Test add ReCaptcha field + * + * @return void + */ + public function testAddReCaptchaScript() + { + $this->View->expects($this->at(0)) + ->method('append') + ->with('script', $this->stringContains('https://www.google.com/recaptcha/api.js')); + $this->User->addReCaptchaScript(); + } } From 5cc343872f66bf8812c75135cc7976c444132afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 14 Aug 2015 14:24:01 +0100 Subject: [PATCH 0167/1476] refs #reCAPTCHA fix helper load --- Docs/Documentation/Configuration.md | 4 ++-- Docs/Documentation/Overview.md | 2 +- config/users.php | 4 ++-- src/Controller/Traits/ReCaptchaTrait.php | 28 ++++++++++++++++------ src/Controller/Traits/RegisterTrait.php | 2 +- src/Template/Users/register.ctp | 2 +- src/View/Helper/UserHelper.php | 30 +++++++++++++++++------- 7 files changed, 50 insertions(+), 22 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 0f301a047..b8b907374 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -74,8 +74,8 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'Registration' => [ //determines if the register is enabled 'active' => true, - //determines if the reCAPTCHA is enabled for registration - 'reCAPTCHA' => true, + //determines if the reCaptcha is enabled for registration + 'reCaptcha' => true, ], 'Tos' => [ //determines if the user should include tos accepted diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md index dc6fd1673..0e98fc30e 100644 --- a/Docs/Documentation/Overview.md +++ b/Docs/Documentation/Overview.md @@ -14,5 +14,5 @@ The plugin itself is already capable of: * Simple roles management * Simple Rbac and SuperUser Authorize * RememberMe using cookie feature -* reCAPTCHA for user registration +* reCaptcha for user registration diff --git a/config/users.php b/config/users.php index 07c362969..6958ea67d 100644 --- a/config/users.php +++ b/config/users.php @@ -28,8 +28,8 @@ 'Registration' => [ //determines if the register is enabled 'active' => true, - //determines if the reCAPTCHA is enabled for registration - 'reCAPTCHA' => true, + //determines if the reCaptcha is enabled for registration + 'reCaptcha' => true, ], 'Tos' => [ //determines if the user should include tos accepted diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php index 9e8e21fff..9970105b2 100644 --- a/src/Controller/Traits/ReCaptchaTrait.php +++ b/src/Controller/Traits/ReCaptchaTrait.php @@ -22,21 +22,35 @@ trait ReCaptchaTrait { /** - * Validates reCAPTCHA response - * @param $recaptchaResponse - * @param $clientIp + * Validates reCaptcha response + * + * @param string $recaptchaResponse response + * @param string $clientIp client ip * @return bool */ public function validateReCaptcha($recaptchaResponse, $clientIp) { $validReCaptcha = true; - $useReCaptcha = (bool)Configure::read('Users.Registration.reCAPTCHA'); - $reCaptchaSecret = Configure::read('reCAPTCHA.secret'); - if ($useReCaptcha && !empty($reCaptchaSecret)) { - $recaptcha = new ReCaptcha($reCaptchaSecret); + $recaptcha = $this->_getReCaptchaInstance(); + if (!empty($recaptcha)) { $response = $recaptcha->verify($recaptchaResponse, $clientIp); $validReCaptcha = $response->isSuccess(); } return $validReCaptcha; } + + /** + * Create reCaptcha instance if enabled in configuration + * + * @return ReCaptcha + */ + protected function _getReCaptchaInstance() + { + $useReCaptcha = (bool)Configure::read('Users.Registration.reCaptcha'); + $reCaptchaSecret = Configure::read('reCaptcha.secret'); + if ($useReCaptcha && !empty($reCaptchaSecret)) { + return new ReCaptcha($reCaptchaSecret); + } + return null; + } } diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 874dd15e2..36d3cdfd6 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -73,7 +73,7 @@ public function register() $this->Flash->error(__d('Users', 'The user could not be saved')); } } else { - $this->Flash->error(__d('Users', 'The reCAPTCHA could not be validated')); + $this->Flash->error(__d('Users', 'The reCaptcha could not be validated')); } } diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index 24c62e058..80b2f1470 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -21,7 +21,7 @@ echo $this->Form->input('first_name'); echo $this->Form->input('last_name'); echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); - echo $this->User->addReCAPTCHA(); + echo $this->User->addReCaptcha(); ?> Form->button(__d('Users', 'Submit')) ?> diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index bc1ef4298..39e26c24e 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -32,6 +32,18 @@ class UserHelper extends Helper */ protected $_defaultConfig = []; + /** + * beforeLayou callback loads reCaptcha if enabled + * + * @param Event $event event + * @return void + */ + public function beforeLayout(Event $event) { + if (Configure::read('Users.Registration.reCaptcha')) { + $this->addReCaptchaScript(); + } + } + /** * Facebook login link * @@ -112,27 +124,29 @@ public function welcome() } /** - * Add reCAPTCHA script - * @return mixed + * Add reCaptcha script + * @return void */ - public function addReCAPTCHAScript() + public function addReCaptchaScript() { - return $this->Html->script('https://www.google.com/recaptcha/api.js'); + $this->Html->script('https://www.google.com/recaptcha/api.js', [ + 'block' => 'script', + ]); } /** - * Add reCAPTCHA to the form + * Add reCaptcha to the form * @return mixed */ - public function addReCAPTCHA() + public function addReCaptcha() { - if (!Configure::check('Users.Registration.reCAPTCHA')) { + if (!Configure::check('Users.Registration.reCaptcha')) { return false; } $this->Form->unlockField('g-recaptcha-response'); return $this->Html->tag('div', '', [ 'class' => 'g-recaptcha', - 'data-sitekey' => Configure::read('reCAPTCHA.key') + 'data-sitekey' => Configure::read('reCaptcha.key') ]); } } From 0c0aa1e09267226605f72782079d2cc411707c0a Mon Sep 17 00:00:00 2001 From: phlyper Date: Fri, 14 Aug 2015 19:56:47 +0100 Subject: [PATCH 0168/1476] Remove table user_details from config --- .../Migration/001_initialize_users_schema.php | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php index f90c981af..4517dfdb4 100644 --- a/Config/Migration/001_initialize_users_schema.php +++ b/Config/Migration/001_initialize_users_schema.php @@ -31,22 +31,6 @@ class M49c3417a54874a9d276811502cedc421 extends CakeMigration { public $migration = array( 'up' => array( 'create_table' => array( - 'user_details' => array( - 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), - 'user_id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36), - 'position' => array('type' => 'float', 'null' => false, 'default' => '1', 'length' => 4), - 'field' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index', 'length' => 60), - 'value' => array('type' => 'text', 'null' => true, 'default' => null), - 'input' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'data_type' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'label' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => 128), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array( - 'PRIMARY' => array('column' => 'id', 'unique' => 1), - 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1) - ) - ), 'users' => array( 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), 'username' => array('type' => 'string', 'null' => false, 'default' => null), @@ -74,8 +58,7 @@ class M49c3417a54874a9d276811502cedc421 extends CakeMigration { ), ), 'down' => array( - 'drop_table' => array( - 'users', 'user_details'), + 'drop_table' => array('users'), ) ); From 4fcc60df826bcff666dcdd0c647e98679d8f78a2 Mon Sep 17 00:00:00 2001 From: phlyper Date: Fri, 14 Aug 2015 19:58:51 +0100 Subject: [PATCH 0169/1476] Remove variable $user_details from schema --- Config/Schema/schema.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php index 827c14344..4dabf4b01 100644 --- a/Config/Schema/schema.php +++ b/Config/Schema/schema.php @@ -25,22 +25,6 @@ public function before($event = array()) { public function after($event = array()) { } - public $user_details = array( - 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), - 'user_id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36), - 'position' => array('type' => 'float', 'null' => false, 'default' => '1'), - 'field' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index'), - 'value' => array('type' => 'text', 'null' => true, 'default' => null), - 'input' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'data_type' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 16), - 'label' => array('type' => 'string', 'null' => false, 'length' => 128), - 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), - 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), - 'UNIQUE_PROFILE_PROPERTY' => array('column' => array('field', 'user_id'), 'unique' => 1) - ) - ); - public $users = array( 'id' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 36, 'key' => 'primary'), 'username' => array('type' => 'string', 'null' => false, 'default' => null, 'key' => 'index'), From c088fd79ca0671f2f62317fde8cdf2de751df33d Mon Sep 17 00:00:00 2001 From: phlyper Date: Fri, 14 Aug 2015 20:00:37 +0100 Subject: [PATCH 0170/1476] update the french file of localisation --- Locale/fra/LC_MESSAGES/users.po | 1017 +++++++++++++++---------------- 1 file changed, 488 insertions(+), 529 deletions(-) diff --git a/Locale/fra/LC_MESSAGES/users.po b/Locale/fra/LC_MESSAGES/users.po index 68c87262c..55263014b 100644 --- a/Locale/fra/LC_MESSAGES/users.po +++ b/Locale/fra/LC_MESSAGES/users.po @@ -1,713 +1,672 @@ msgid "" msgstr "" "Project-Id-Version: CakePHP Users Plugin\n" -"POT-Creation-Date: 2010-09-15 15:48+0200\n" +"POT-Creation-Date: \n" "PO-Revision-Date: \n" -"Last-Translator: Pierre MARTIN \n" +"Last-Translator: phlyper \n" "Language-Team: CakeDC \n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: French\n" +"X-Generator: Poedit 1.8.3\n" -#: /controllers/details_controller.php:57;138 -msgid "Invalid Detail." -msgstr "Détail invalide." - -#: /controllers/details_controller.php:78 -msgid "Saved" -msgstr "Sauvegardé" - -#: /controllers/details_controller.php:96 -msgid "%s details saved" -msgstr "%s détails sauvegardés" - -#: /controllers/details_controller.php:113;196 -msgid "Invalid id for Detail" -msgstr "Id invalide pour le Détail" - -#: /controllers/details_controller.php:117;200 -msgid "Detail deleted" -msgstr "Détail supprimé" - -#: /controllers/details_controller.php:152;175 -msgid "The Detail has been saved" -msgstr "Le Détail a été sauvegardé" - -#: /controllers/details_controller.php:155;178 -msgid "The Detail could not be saved. Please, try again." -msgstr "Le Détail ne peut pas être sauvegardé. Merci de réessayer." - -#: /controllers/details_controller.php:170 -msgid "Invalid Detail" -msgstr "Détail Invalide" - -#: /controllers/users_controller.php:157 -msgid "Profile saved." -msgstr "Profil sauvegardé" - -#: /controllers/users_controller.php:159 -msgid "Could not save your profile." -msgstr "Le profil n'a pas pu être sauvegardé" - -#: /controllers/users_controller.php:193 +#: Controller/UsersController.php:332 msgid "Invalid User." msgstr "Utilisateur invalide." -#: /controllers/users_controller.php:207 +#: Controller/UsersController.php:350 msgid "The User has been saved" msgstr "L'utilisateur a été sauvegardé" -#: /controllers/users_controller.php:223 +#: Controller/UsersController.php:367 msgid "User saved" msgstr "Utilisateur sauvegardé" -#: /controllers/users_controller.php:247 +#: Controller/UsersController.php:393 msgid "User deleted" msgstr "Utilisateur supprimé" -#: /controllers/users_controller.php:249 -#: /models/user.php:703 +#: Controller/UsersController.php:395 Model/User.php:893 msgid "Invalid User" msgstr "Utilisateur invalide" -#: /controllers/users_controller.php:273 +#: Controller/UsersController.php:417 msgid "You are already registered and logged in!" msgstr "Vous êtes déjà enregistré et connecté !" -#: /controllers/users_controller.php:282 -#: /tests/cases/controllers/users_controller.test.php:194 -msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Votre compte a été créé. Vous devriez recevoir un email sous peu pour authentifier votre compte. Une fois le compte validé vous pourrez vous connecter." +#: Controller/UsersController.php:437 +msgid "" +"Your account has been created. You should receive an e-mail shortly to " +"authenticate your account. Once validated you will be able to login." +msgstr "" +"Votre compte a été créé. Vous devriez recevoir un email sous peu pour " +"authentifier votre compte. Une fois le compte validé vous pourrez vous " +"connecter." -#: /controllers/users_controller.php:287 -#: /tests/cases/controllers/users_controller.test.php:205 +#: Controller/UsersController.php:442 msgid "Your account could not be created. Please, try again." msgstr "Votre compte n'a pas pu être créé. Merci de réessayer." -#: /controllers/users_controller.php:309 +#: Controller/UsersController.php:486 msgid "%s you have successfully logged in" msgstr "%s vous êtes désormais connecté" -#: /controllers/users_controller.php:383 +#: Controller/UsersController.php:507 +msgid "Invalid e-mail / password combination. Please try again" +msgstr "" + +#: Controller/UsersController.php:575 msgid "%s you have successfully logged out" msgstr "%s vous avez été déconnecté avec succès" -#: /controllers/users_controller.php:409 -msgid "There url you accessed is not longer valid" -msgstr "L'url à laquelle vous essayez d'accéder n'est plus valide" - -#: /controllers/users_controller.php:432;545 -msgid "Password Reset" -msgstr "Réinitialisation du Mot de passe" - -#: /controllers/users_controller.php:434 -msgid "Your password has been reset" -msgstr "Votre mot de passe a été réinitialisé" - -#: /controllers/users_controller.php:435 -msgid "Please login using this password and change your password" -msgstr "Merci de vous connecter en utilisant ce mot de passe et de le modifier ensuite" +#: Controller/UsersController.php:589 +msgid "The email was resent. Please check your inbox." +msgstr "" -#: /controllers/users_controller.php:438 -msgid "Your password was sent to your registered email account" -msgstr "Votre mot de passe a été envoyé à l'adresse email associée à votre compte" +#: Controller/UsersController.php:592 +msgid "The email could not be sent. Please check errors." +msgstr "" -#: /controllers/users_controller.php:444 -#: /tests/cases/controllers/users_controller.test.php:219 +#: Controller/UsersController.php:615 msgid "Your e-mail has been validated!" msgstr "Votre e-mail a été validé !" -#: /controllers/users_controller.php:448 -msgid "There was an error trying to validate your e-mail address. Please check your e-mail for the URL you should use to verify your e-mail address." -msgstr "Il y a eu une erreur lors de la validation de votre adresse email. Veuillez vérifier dans vos email que l'URL à utiliser pour valider votre adresse est correcte." - -#: /controllers/users_controller.php:452 -#: /tests/cases/controllers/users_controller.test.php:224 +#: Controller/UsersController.php:638 msgid "The url you accessed is not longer valid" msgstr "L'url à laquelle vous essayez d'accéder n'est plus valide" -#: /controllers/users_controller.php:467 +#: Controller/UsersController.php:644 +msgid "Your password was sent to your registered email account" +msgstr "" +"Votre mot de passe a été envoyé à l'adresse email associée à votre compte" + +#: Controller/UsersController.php:648 +msgid "" +"There was an error verifying your account. Please check the email you were " +"sent, and retry the verification link." +msgstr "" + +#: Controller/UsersController.php:664;774 +msgid "Password Reset" +msgstr "Réinitialisation du Mot de passe" + +#: Controller/UsersController.php:681;846 msgid "Password changed." msgstr "Mot de passe modifé." -#: /controllers/users_controller.php:521 +#: Controller/UsersController.php:742 msgid "Account verification" msgstr "Vérification de compte" -#: /controllers/users_controller.php:563 +#: Controller/UsersController.php:801 msgid "%s has been sent an email with instruction to reset their password." -msgstr "Un email a été envoyé à %s avec les instructions pour mettre à jour le mot de passe." +msgstr "" +"Un email a été envoyé à %s avec les instructions pour mettre à jour le mot " +"de passe." -#: /controllers/users_controller.php:567 +#: Controller/UsersController.php:805 msgid "You should receive an email with further instructions shortly" -msgstr "Vous devriez recevoir un email sous peu avec de plus amples instructions" +msgstr "" +"Vous devriez recevoir un email sous peu avec de plus amples instructions" -#: /controllers/users_controller.php:571 +#: Controller/UsersController.php:809 msgid "No user was found with that email." msgstr "Aucun utilisateur ayant cet adresse email n'a été trouvé." -#: /controllers/users_controller.php:588 +#: Controller/UsersController.php:839 msgid "Invalid password reset token, try again." -msgstr "Jeton de réinitialisation de mot de passe invalide. merci de réessayer." +msgstr "" +"Jeton de réinitialisation de mot de passe invalide. merci de réessayer." -#: /controllers/users_controller.php:594 +#: Controller/UsersController.php:849 msgid "Password changed, you can now login with your new password." -msgstr "Mot de passe changé, vous pouvez désormais vous connecter avec votre nouveau mot de passe." - -#: /models/user.php:102 -msgid "Please enter a username" -msgstr "Veuillez saisir un nom d'utilisateur" - -#: /models/user.php:105 -msgid "The username must be alphanumeric" -msgstr "Le nom d'utilisateur doit être alphanumérique" - -#: /models/user.php:108 -msgid "This username is already in use." -msgstr "Ce nom d'utilisateur est déjà utilisé." - -#: /models/user.php:111 -msgid "The username must have at least 3 characters." -msgstr "Le nom d'utilisateur doit avoir au moins 3 caractères." - -#: /models/user.php:116 -msgid "Please enter a valid email address." -msgstr "Merci de saisir une adresse email valide." - -#: /models/user.php:119 -msgid "This email is already in use." -msgstr "Cet email est déjà utilisé." - -#: /models/user.php:123 -msgid "The password must have at least 8 characters." -msgstr "Le mot de passe doit contenir au moins 8 caractères." - -#: /models/user.php:126 -msgid "Please enter a password." -msgstr "Veuillez entrer un mot de passe." +msgstr "" +"Mot de passe changé, vous pouvez désormais vous connecter avec votre nouveau " +"mot de passe." -#: /models/user.php:129 -msgid "The passwords are not equal, please try again." -msgstr "Les mots de passe ne correspondent pas, merci de réessayer." +#: Controller/Component/RememberMeComponent.php:235 +msgid "Invalid options %s" +msgstr "Options invalide %s" -#: /models/user.php:132 -msgid "You must agree to the terms of use." -msgstr "Vous devez accepter les conditions d'utilisation." +#: Controller/Component/Auth/TokenAuthenticate.php:68 +msgid "You need to specify token parameter and/or header" +msgstr "" -#: /models/user.php:137;357 +#: Model/User.php:173;359 msgid "The passwords are not equal." msgstr "Les mots de passe ne sont pas égaux." -#: /models/user.php:139 +#: Model/User.php:175 msgid "Invalid password." msgstr "Mot de passe invalide." -#: /models/user.php:150 -msgid "Invalid date" -msgstr "Date invalide" +#: Model/User.php:261 +msgid "" +"Invalid token, please check the email you were sent, and retry the " +"verification link." +msgstr "" + +#: Model/User.php:266 +msgid "The token has expired." +msgstr "" -#: /models/user.php:315 +#: Model/User.php:321 msgid "This Email Address exists but was never validated." msgstr "Cette adresse email existe mais n'a jamais été validée." -#: /models/user.php:317 +#: Model/User.php:323 msgid "This Email Address does not exist in the system." msgstr "Cette adresse email n'existe pas dans le système." -#: /models/user.php:406 +#: Model/User.php:421 msgid "$this->data['" msgstr "$this->data['" -#: /models/user.php:460 +#: Model/User.php:467 msgid "The user does not exist." msgstr "L'utilisateur n'existe pas." -#: /models/user.php:505 +#: Model/User.php:505 +msgid "Invalid Email address." +msgstr "Adresse Email invalide" + +#: Model/User.php:510 +msgid "This email is already verified." +msgstr "Cet email est déjà vérifié." + +#: Model/User.php:608 msgid "Please enter your email address." msgstr "Veuillez entrer votre adresse email." -#: /models/user.php:515 +#: Model/User.php:615 msgid "The email address does not exist in the system" msgstr "Cette adresse email n'existe pas dans le système." -#: /models/user.php:520 +#: Model/User.php:620 msgid "Your account is already authenticated." msgstr "Votre compte est déjà authentifié." -#: /models/user.php:525 +#: Model/User.php:625 msgid "Your account is disabled." msgstr "Votre compte est désactivé." -#: /tests/cases/controllers/users_controller.test.php:34 -msgid "Sorry, but you need to login to access this location." -msgstr "Désole, mais vous devez vous connecter pour accéder à cette page." - -#: /tests/cases/controllers/users_controller.test.php:35;174 -msgid "Invalid e-mail / password combination. Please try again" -msgstr "Combinaison e-mail / mot de passe incorrecte. Veuillez réessayer." - -#: /tests/cases/controllers/users_controller.test.php:168 -msgid "testuser you have successfully logged in" -msgstr "testuser you have successfully logged in" - -#: /tests/cases/controllers/users_controller.test.php:237 -msgid "floriank you have successfully logged out" -msgstr "floriank you have successfully logged out" - -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 -msgid "Add Detail" -msgstr "Ajouter un Détail" - -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 -#: /views/details/view.ctp:45 -msgid "List Details" -msgstr "Lister les Détails" - -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 +#: View/Elements/pagination.ctp:14 +msgid "previous" +msgstr "précédent" + +#: View/Elements/pagination.ctp:16 +msgid "next" +msgstr "suivant" + +#: View/Elements/Users/admin_sidebar.ctp:3 View/Elements/Users/sidebar.ctp:9 +msgid "Logout" +msgstr "Se déconnecter" + +#: View/Elements/Users/admin_sidebar.ctp:4 View/Elements/Users/sidebar.ctp:10 +msgid "My Account" +msgstr "Mon Compte" + +#: View/Elements/Users/admin_sidebar.ctp:6 +msgid "Add Users" +msgstr "" + +#: View/Elements/Users/admin_sidebar.ctp:7 View/Elements/Users/sidebar.ctp:15 msgid "List Users" msgstr "Lister les Utilisateurs" -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 -msgid "New User" -msgstr "Nouvel Utilisateur" - -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 -msgid "List Groups" -msgstr "Lister les Groupes" - -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 -msgid "New Group" -msgstr "Nouveau Groupe" - -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 -msgid "Edit Detail" -msgstr "Modifier le Détail" - -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 -msgid "Delete" -msgstr "Effacer" +#: View/Elements/Users/admin_sidebar.ctp:9 +msgid "Frontend" +msgstr "" -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 -msgid "Are you sure you want to delete # %s?" -msgstr "Etes-vous sûr de vouloir supprimer # %s ?" +#: View/Elements/Users/sidebar.ctp:4 View/Users/login.ctp:13 +msgid "Login" +msgstr "Identifiant" -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 -msgid "Details" -msgstr "Détails" - -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 -msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "Page %page% sur %pages%, affiche %current% enregistrements sur un total de %count%, commençant à l'enregistrement %start%, s'arrêtant au %end%" - -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 -msgid "Actions" -msgstr "Actions" +#: View/Elements/Users/sidebar.ctp:6 +msgid "Register an account" +msgstr "Créer un compte" -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 -#: /views/users/index.ctp:31 -msgid "View" -msgstr "Voir" +#: View/Elements/Users/sidebar.ctp:11 +msgid "Change password" +msgstr "Changer le mot de passe" -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 -msgid "Edit" -msgstr "Modifier" +#: View/Emails/text/account_verification.ctp:12 +msgid "Hello %s," +msgstr "Bonjour %s," -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 -msgid "previous" -msgstr "précédent" +#: View/Emails/text/account_verification.ctp:14 +msgid "to validate your account, you must visit the URL below within 24 hours" +msgstr "" +"pour valider votre compte, vous devez visiter l'URL ci-dessous sous 24 heures" -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 -msgid "next" -msgstr "suivant" +#: View/Emails/text/new_password.ctp:12 +msgid "Your password has been reset" +msgstr "Votre mot de passe a été réinitialisé" -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 -#: /views/details/view.ctp:46 -msgid "New Detail" -msgstr "Nouveau Détail" - -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 -msgid "Detail" -msgstr "Détail" - -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 -msgid "Id" -msgstr "Id" - -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 -msgid "User" -msgstr "Utilisateur" +#: View/Emails/text/new_password.ctp:13 +msgid "Please login using this password and change your password" +msgstr "" +"Merci de vous connecter en utilisant ce mot de passe et de le modifier " +"ensuite" -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 -msgid "Position" -msgstr "Position" - -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 -msgid "Field" -msgstr "Champ" - -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 -msgid "Value" -msgstr "Valeur" - -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 -msgid "Created" -msgstr "Créé" +#: View/Emails/text/new_password.ctp:15 +msgid "Your new password is: %s" +msgstr "Votre nouveau mot de passe est : %s" -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 -#: /views/users/admin_view.ctp:14 -msgid "Modified" -msgstr "Modifié" +#: View/Emails/text/password_reset_request.ctp:12 +msgid "" +"A request to reset your password was sent. To change your password click the " +"link below." +msgstr "" +"Une requête de réinitialisation de mot de passe a été envoyée. Pour modifier " +"votre mot de passe cliquez sur le lien ci-dessous." -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 -msgid "Delete Detail" -msgstr "Supprimer le Détail" - -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 -msgid "Related Groups" -msgstr "Groupes liés" - -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 -msgid "User Id" -msgstr "Id d'Utilisateur" - -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 -msgid "Is Public" -msgstr "Est Public" - -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 -msgid "Name" -msgstr "Nom" +#: View/Users/add.ctp:13 View/Users/admin_add.ctp:15 +msgid "Add User" +msgstr "Ajouter un Utilisateur" -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 -#: /views/users/groups.ctp:48 -msgid "Description" -msgstr "Description" - -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 -#: /views/users/request_password_change.ctp:12 -#: /views/users/reset_password.ctp:14 -msgid "Submit" -msgstr "Envoyer" +#: View/Users/add.ctp:18 View/Users/admin_add.ctp:18 +#: View/Users/admin_edit.ctp:19 View/Users/admin_index.ctp:19 +#: View/Users/admin_view.ctp:15 View/Users/search.ctp:18 View/Users/view.ctp:15 +msgid "Username" +msgstr "Nom d'utilisateur" -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 -#: /views/users/search.ctp:7 -msgid "Email" -msgstr "Email" +#: View/Users/add.ctp:20 View/Users/admin_add.ctp:20 +msgid "E-mail (used as login)" +msgstr "Email (utilisé comme identifiant)" + +#: View/Users/add.ctp:21 View/Users/admin_add.ctp:21 +msgid "Must be a valid email address" +msgstr "Doit être une adresse email valide" -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 -#: /views/users/register.ctp:19 +#: View/Users/add.ctp:22 View/Users/admin_add.ctp:22 +msgid "An account with that email already exists" +msgstr "Un compte avec cette adresse email existe déjà" + +#: View/Users/add.ctp:24 View/Users/admin_add.ctp:24 View/Users/login.ctp:23 msgid "Password" msgstr "Mot de passe" -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 -msgid "Login" -msgstr "Identifiant" +#: View/Users/add.ctp:27 View/Users/admin_add.ctp:27 +msgid "Password (confirm)" +msgstr "Mot de passe (confirmation)" -#: /views/elements/email/text/account_verification.ctp:2 -msgid "Hello %s," -msgstr "Bonjour %s," +#: View/Users/add.ctp:29 +msgid "Terms of Service" +msgstr "Conditions d'utilisation" -#: /views/elements/email/text/account_verification.ctp:4 -msgid "to validate your account, you must visit the URL below within 24 hours" -msgstr "pour valider votre compte, vous devez visiter l'URL ci-dessous sous 24 heures" +#: View/Users/add.ctp:31 +msgid "I have read and agreed to " +msgstr "J'ai lu et accepte les " + +#: View/Users/add.ctp:32 View/Users/change_password.ctp:26 +#: View/Users/edit.ctp:20 View/Users/login.ctp:30 +#: View/Users/request_password_change.ctp:22 +#: View/Users/resend_verification.ctp:22 View/Users/reset_password.ctp:14 +msgid "Submit" +msgstr "Envoyer" -#: /views/elements/email/text/password_reset_request.ctp:2 -msgid "A request to reset your password was sent. To change your password click the link below." -msgstr "Une requête de réinitialisation de mot de passe a été envoyée. Pour modifier votre mot de passe cliquez sur le lien ci-dessous." +#: View/Users/admin_add.ctp:31 View/Users/admin_edit.ctp:24 +msgid "Role" +msgstr "Rôle" -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 -msgid "Add User" -msgstr "Ajouter un Utilisateur" +#: View/Users/admin_add.ctp:34 View/Users/admin_edit.ctp:27 +msgid "Is Admin" +msgstr "Est un administrateur" -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 -#: /views/users/edit.ctp:3 +#: View/Users/admin_add.ctp:36 View/Users/admin_edit.ctp:29 +msgid "Active" +msgstr "" + +#: View/Users/admin_edit.ctp:15 View/Users/edit.ctp:15 msgid "Edit User" msgstr "Modifier un Utilisateur" -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 +#: View/Users/admin_edit.ctp:21 View/Users/admin_index.ctp:20 +#: View/Users/login.ctp:21 View/Users/search.ctp:20 +msgid "Email" +msgstr "Email" + +#: View/Users/admin_index.ctp:13 View/Users/index.ctp:13 +#: View/Users/search.ctp:13 msgid "Users" msgstr "Utilisateurs" -#: /views/users/admin_index.ctp:4 +#: View/Users/admin_index.ctp:17 msgid "Filter" msgstr "Filtre" -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 -#: /views/users/view.ctp:4 -msgid "Username" -msgstr "Nom d'utilisateur" - -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 +#: View/Users/admin_index.ctp:21 View/Users/search.ctp:23 msgid "Search" msgstr "Recherche" -#: /views/users/admin_view.ctp:24 -msgid "Delete User" -msgstr "Supprimer l'utilisateur" +#: View/Users/admin_index.ctp:34 View/Users/index.ctp:25 +#: View/Users/search.ctp:35 +msgid "Actions" +msgstr "Actions" + +#: View/Users/admin_index.ctp:52;55 +msgid "Yes" +msgstr "Oui" + +#: View/Users/admin_index.ctp:52;55 +msgid "No" +msgstr "Non" + +#: View/Users/admin_index.ctp:61 View/Users/index.ctp:39 +#: View/Users/search.ctp:49 +msgid "View" +msgstr "Voir" + +#: View/Users/admin_index.ctp:62 View/Users/search.ctp:50 +msgid "Edit" +msgstr "Modifier" + +#: View/Users/admin_index.ctp:63 View/Users/search.ctp:52 +msgid "Delete" +msgstr "Effacer" + +#: View/Users/admin_index.ctp:63 View/Users/search.ctp:55 +msgid "Are you sure you want to delete # %s?" +msgstr "Etes-vous sûr de vouloir supprimer # %s ?" + +#: View/Users/admin_view.ctp:13 View/Users/view.ctp:13 +msgid "User" +msgstr "Utilisateur" + +#: View/Users/admin_view.ctp:20 View/Users/view.ctp:20 +msgid "Created" +msgstr "Créé" + +#: View/Users/admin_view.ctp:25 +msgid "Modified" +msgstr "Modifié" -#: /views/users/change_password.ctp:1 +#: View/Users/change_password.ctp:13 View/Users/edit.ctp:17 msgid "Change your password" msgstr "Modifier votre mot de passe" -#: /views/users/change_password.ctp:3 -msgid "Please enter your old password because of security reasons and then your new password twice." -msgstr "Merci de saisir votre ancien mot de passe pour des raisons de sécurité et ensuite votre nouveau mot de passe deux fois." +#: View/Users/change_password.ctp:14 +msgid "" +"Please enter your old password because of security reasons and then your new " +"password twice." +msgstr "" +"Merci de saisir votre ancien mot de passe pour des raisons de sécurité et " +"ensuite votre nouveau mot de passe deux fois." -#: /views/users/change_password.ctp:8 +#: View/Users/change_password.ctp:18 msgid "Old Password" msgstr "Ancien mot de passe" -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 +#: View/Users/change_password.ctp:21 View/Users/reset_password.ctp:9 msgid "New Password" msgstr "Nouveau mot de passe" -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 +#: View/Users/change_password.ctp:24 View/Users/reset_password.ctp:12 msgid "Confirm" msgstr "Confirmer" -#: /views/users/dashboard.ctp:2 +#: View/Users/dashboard.ctp:13 msgid "Welcome" msgstr "Bienvenue" -#: /views/users/dashboard.ctp:3 +#: View/Users/dashboard.ctp:14 msgid "Recent broadcasts" msgstr "Récents broadcasts" -#: /views/users/groups.ctp:2 -msgid "My Groups" -msgstr "Mes Groupes" +#: View/Users/index.ctp:17 View/Users/search.ctp:27 +msgid "" +"Page %page% of %pages%, showing %current% records out of %count% total, " +"starting on record %start%, ending on %end%" +msgstr "" +"Page %page% sur %pages%, affiche %current% enregistrements sur un total de " +"%count%, commençant à l'enregistrement %start%, s'arrêtant au %end%" -#: /views/users/groups.ctp:5 -msgid "Create a new group" -msgstr "Créer un nouveau groupe" +#: View/Users/login.ctp:25 +msgid "Remember Me" +msgstr "Se rappeler de moi" -#: /views/users/groups.ctp:6 -msgid "Invite a user" -msgstr "Inviter un utilisateur" +#: View/Users/login.ctp:26 +msgid "I forgot my password" +msgstr "Mot de passe oublié" -#: /views/users/groups.ctp:7 -msgid "Requests to join" -msgstr "Requêtes pour joindre" +#: View/Users/request_password_change.ctp:13 +msgid "Forgot your password?" +msgstr "Mot de passe oublié ?" -#: /views/users/groups.ctp:10 -msgid "My own groups" -msgstr "Mes propres groupes" +#: View/Users/request_password_change.ctp:14 +#: View/Users/resend_verification.ctp:14 +msgid "" +"Please enter the email you used for registration and you'll get an email " +"with further instructions." +msgstr "" +"Veuillez saisir l'adresse email utilisée lors de l'inscription afin de " +"recevoir un email contenant les instructions." -#: /views/users/groups.ctp:14;49 -msgid "Members" -msgstr "Membres" +#: View/Users/request_password_change.ctp:21 +#: View/Users/resend_verification.ctp:21 +msgid "Your Email" +msgstr "Votre email" -#: /views/users/groups.ctp:34 -msgid "Invite user" -msgstr "Inviter l'utilisateur" +#: View/Users/resend_verification.ctp:13 +msgid "Resend the Email Verification" +msgstr "Renvoyer le vérification d'email" -#: /views/users/groups.ctp:35 -msgid "Manage Broadcast Scope" -msgstr "Gérer l'étendue du Broadcast" +#: View/Users/reset_password.ctp:2 +msgid "Reset your password" +msgstr "Réinitialiser votre mot de passe" -#: /views/users/groups.ctp:36 -msgid "Access" -msgstr "Accéder" +#: View/Users/search.ctp:22 +msgid "Name" +msgstr "Nom" -#: /views/users/groups.ctp:37 -msgid "Addons" -msgstr "Addons" +#~ msgid "Invalid Detail." +#~ msgstr "Détail invalide." -#: /views/users/groups.ctp:44 -msgid "Groups im a member in" -msgstr "Groupes dont je suis membre" +#~ msgid "Saved" +#~ msgstr "Sauvegardé" -#: /views/users/groups.ctp:68 -msgid "Leave group" -msgstr "Quitter le Groupe" +#~ msgid "%s details saved" +#~ msgstr "%s détails sauvegardés" -#: /views/users/login.ctp:11 -msgid "Remember Me" -msgstr "Se rappeler de moi" +#~ msgid "Invalid id for Detail" +#~ msgstr "Id invalide pour le Détail" -#: /views/users/register.ctp:2 -msgid "Account registration" -msgstr "Création de compte" +#~ msgid "Detail deleted" +#~ msgstr "Détail supprimé" -#: /views/users/register.ctp:10 -msgid "Please select a username that is not already in use" -msgstr "Veuillez sélectionner un nom d'utilisateur qui n'est pas déjà utilisé" +#~ msgid "The Detail has been saved" +#~ msgstr "Le Détail a été sauvegardé" -#: /views/users/register.ctp:11 -msgid "Must be at least 3 characters" -msgstr "Doit avoir au moins 3 caractères" +#~ msgid "The Detail could not be saved. Please, try again." +#~ msgstr "Le Détail ne peut pas être sauvegardé. Merci de réessayer." -#: /views/users/register.ctp:12 -msgid "Username must contain numbers and letters only" -msgstr "Le nom d'utilisateur ne doit contenir que des nombres et lettres" +#~ msgid "Invalid Detail" +#~ msgstr "Détail Invalide" -#: /views/users/register.ctp:13 -msgid "Please choose username" -msgstr "Veuillez choisir un nom d'utilisateur" +#~ msgid "Profile saved." +#~ msgstr "Profil sauvegardé" -#: /views/users/register.ctp:15 -msgid "E-mail (used as login)" -msgstr "Email (utilisé comme identifiant)" +#~ msgid "Could not save your profile." +#~ msgstr "Le profil n'a pas pu être sauvegardé" -#: /views/users/register.ctp:16 -msgid "Must be a valid email address" -msgstr "Doit être une adresse email valide" +#~ msgid "There url you accessed is not longer valid" +#~ msgstr "L'url à laquelle vous essayez d'accéder n'est plus valide" -#: /views/users/register.ctp:17 -msgid "An account with that email already exists" -msgstr "Un compte avec cette adresse email existe déjà" +#~ msgid "" +#~ "There was an error trying to validate your e-mail address. Please check " +#~ "your e-mail for the URL you should use to verify your e-mail address." +#~ msgstr "" +#~ "Il y a eu une erreur lors de la validation de votre adresse email. " +#~ "Veuillez vérifier dans vos email que l'URL à utiliser pour valider votre " +#~ "adresse est correcte." -#: /views/users/register.ctp:21 -msgid "Must be at least 5 characters long" -msgstr "Doit avoir au moins 5 caractères" +#~ msgid "Please enter a username" +#~ msgstr "Veuillez saisir un nom d'utilisateur" -#: /views/users/register.ctp:23 -msgid "Password (confirm)" -msgstr "Mot de passe (confirmation)" +#~ msgid "The username must be alphanumeric" +#~ msgstr "Le nom d'utilisateur doit être alphanumérique" -#: /views/users/register.ctp:25 -msgid "Passwords must match" -msgstr "Les mots de passe doivent correspondre" +#~ msgid "This username is already in use." +#~ msgstr "Ce nom d'utilisateur est déjà utilisé." -#: /views/users/register.ctp:29;85 -msgid "I have read and agreed to " -msgstr "J'ai lu et accepte les " +#~ msgid "The username must have at least 3 characters." +#~ msgstr "Le nom d'utilisateur doit avoir au moins 3 caractères." -#: /views/users/register.ctp:29;85 -msgid "Terms of Service" -msgstr "Conditions d'utilisation" +#~ msgid "Please enter a valid email address." +#~ msgstr "Merci de saisir une adresse email valide." -#: /views/users/register.ctp:30;86 -msgid "You must verify you have read the Terms of Service" -msgstr "Vous devez vérifier que vous ayez lu les Conditions d'utilisation" +#~ msgid "This email is already in use." +#~ msgstr "Cet email est déjà utilisé." -#: /views/users/register.ctp:46 -msgid "Openid Identifier" -msgstr "Identifiant Openid" +#~ msgid "The password must have at least 8 characters." +#~ msgstr "Le mot de passe doit contenir au moins 8 caractères." -#: /views/users/request_password_change.ctp:1 -msgid "Forgot your password?" -msgstr "Mot de passe oublié ?" +#~ msgid "Please enter a password." +#~ msgstr "Veuillez entrer un mot de passe." -#: /views/users/request_password_change.ctp:3 -msgid "Please enter the email you used for registration and you'll get an email with further instructions." -msgstr "Veuillez saisir l'adresse email utilisée lors de l'inscription afin de recevoir un email contenant les instructions." +#~ msgid "The passwords are not equal, please try again." +#~ msgstr "Les mots de passe ne correspondent pas, merci de réessayer." -#: /views/users/request_password_change.ctp:11 -msgid "Your Email" -msgstr "Votre email" +#~ msgid "You must agree to the terms of use." +#~ msgstr "Vous devez accepter les conditions d'utilisation." -#: /views/users/reset_password.ctp:1 -msgid "Reset your password" -msgstr "Réinitialiser votre mot de passe" +#~ msgid "Invalid date" +#~ msgstr "Date invalide" -#: /views/users/search.ctp:1 -msgid "Search for users" -msgstr "Rechercher des utilisateurs" +#~ msgid "Sorry, but you need to login to access this location." +#~ msgstr "Désole, mais vous devez vous connecter pour accéder à cette page." -#: View/Users/login.ctp:26 -msgid "I forgot my password" -msgstr "Mot de passe oublié" \ No newline at end of file +#~ msgid "Invalid e-mail / password combination. Please try again" +#~ msgstr "Combinaison e-mail / mot de passe incorrecte. Veuillez réessayer." + +#~ msgid "testuser you have successfully logged in" +#~ msgstr "testuser you have successfully logged in" + +#~ msgid "floriank you have successfully logged out" +#~ msgstr "floriank you have successfully logged out" + +#~ msgid "Add Detail" +#~ msgstr "Ajouter un Détail" + +#~ msgid "List Details" +#~ msgstr "Lister les Détails" + +#~ msgid "New User" +#~ msgstr "Nouvel Utilisateur" + +#~ msgid "List Groups" +#~ msgstr "Lister les Groupes" + +#~ msgid "New Group" +#~ msgstr "Nouveau Groupe" + +#~ msgid "Edit Detail" +#~ msgstr "Modifier le Détail" + +#~ msgid "Details" +#~ msgstr "Détails" + +#~ msgid "New Detail" +#~ msgstr "Nouveau Détail" + +#~ msgid "Detail" +#~ msgstr "Détail" + +#~ msgid "Id" +#~ msgstr "Id" + +#~ msgid "Position" +#~ msgstr "Position" + +#~ msgid "Field" +#~ msgstr "Champ" + +#~ msgid "Value" +#~ msgstr "Valeur" + +#~ msgid "Delete Detail" +#~ msgstr "Supprimer le Détail" + +#~ msgid "Related Groups" +#~ msgstr "Groupes liés" + +#~ msgid "User Id" +#~ msgstr "Id d'Utilisateur" + +#~ msgid "Is Public" +#~ msgstr "Est Public" + +#~ msgid "Description" +#~ msgstr "Description" + +#~ msgid "Delete User" +#~ msgstr "Supprimer l'utilisateur" + +#~ msgid "My Groups" +#~ msgstr "Mes Groupes" + +#~ msgid "Create a new group" +#~ msgstr "Créer un nouveau groupe" + +#~ msgid "Invite a user" +#~ msgstr "Inviter un utilisateur" + +#~ msgid "Requests to join" +#~ msgstr "Requêtes pour joindre" + +#~ msgid "My own groups" +#~ msgstr "Mes propres groupes" + +#~ msgid "Members" +#~ msgstr "Membres" + +#~ msgid "Invite user" +#~ msgstr "Inviter l'utilisateur" + +#~ msgid "Manage Broadcast Scope" +#~ msgstr "Gérer l'étendue du Broadcast" + +#~ msgid "Access" +#~ msgstr "Accéder" + +#~ msgid "Addons" +#~ msgstr "Addons" + +#~ msgid "Groups im a member in" +#~ msgstr "Groupes dont je suis membre" + +#~ msgid "Leave group" +#~ msgstr "Quitter le Groupe" + +#~ msgid "Account registration" +#~ msgstr "Création de compte" + +#~ msgid "Please select a username that is not already in use" +#~ msgstr "" +#~ "Veuillez sélectionner un nom d'utilisateur qui n'est pas déjà utilisé" + +#~ msgid "Must be at least 3 characters" +#~ msgstr "Doit avoir au moins 3 caractères" + +#~ msgid "Username must contain numbers and letters only" +#~ msgstr "Le nom d'utilisateur ne doit contenir que des nombres et lettres" + +#~ msgid "Please choose username" +#~ msgstr "Veuillez choisir un nom d'utilisateur" + +#~ msgid "Must be at least 5 characters long" +#~ msgstr "Doit avoir au moins 5 caractères" + +#~ msgid "Passwords must match" +#~ msgstr "Les mots de passe doivent correspondre" + +#~ msgid "You must verify you have read the Terms of Service" +#~ msgstr "Vous devez vérifier que vous ayez lu les Conditions d'utilisation" + +#~ msgid "Openid Identifier" +#~ msgstr "Identifiant Openid" + +#~ msgid "Search for users" +#~ msgstr "Rechercher des utilisateurs" From 652c29ccb6fdc1460a5644e9b474cb82112fe4d7 Mon Sep 17 00:00:00 2001 From: phlyper Date: Fri, 14 Aug 2015 20:01:17 +0100 Subject: [PATCH 0171/1476] update the main file of localisation --- Locale/users.pot | 170 ++++++++++++++++------------------------------- 1 file changed, 56 insertions(+), 114 deletions(-) diff --git a/Locale/users.pot b/Locale/users.pot index ca48a99b2..804efcbba 100644 --- a/Locale/users.pot +++ b/Locale/users.pot @@ -5,7 +5,6 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2013-09-18 23:20+0200\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" @@ -14,188 +13,171 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: Controller/UsersController.php:310 +#: Controller/UsersController.php:332 msgid "Invalid User." msgstr "" -#: Controller/UsersController.php:328 +#: Controller/UsersController.php:350 msgid "The User has been saved" msgstr "" -#: Controller/UsersController.php:345 +#: Controller/UsersController.php:367 msgid "User saved" msgstr "" -#: Controller/UsersController.php:369 +#: Controller/UsersController.php:393 msgid "User deleted" msgstr "" -#: Controller/UsersController.php:371 -#: Model/User.php:829;858 +#: Controller/UsersController.php:395 +#: Model/User.php:893 msgid "Invalid User" msgstr "" -#: Controller/UsersController.php:393 +#: Controller/UsersController.php:417 msgid "You are already registered and logged in!" msgstr "" -#: Controller/UsersController.php:413 -#: Test/Case/Controller/UsersControllerTest.php:342 +#: Controller/UsersController.php:437 msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." msgstr "" -#: Controller/UsersController.php:418 -#: Test/Case/Controller/UsersControllerTest.php:357 +#: Controller/UsersController.php:442 msgid "Your account could not be created. Please, try again." msgstr "" -#: Controller/UsersController.php:462 +#: Controller/UsersController.php:486 msgid "%s you have successfully logged in" msgstr "" -#: Controller/UsersController.php:483 -#: Test/Case/Controller/UsersControllerTest.php:316 -msgid "Invalid e-mail / password combination. Please try again" +#: Controller/UsersController.php:507 +msgid "Invalid e-mail / password combination. Please try again" msgstr "" -#: Controller/UsersController.php:549 +#: Controller/UsersController.php:575 msgid "%s you have successfully logged out" msgstr "" -#: Controller/UsersController.php:563 +#: Controller/UsersController.php:589 msgid "The email was resent. Please check your inbox." msgstr "" -#: Controller/UsersController.php:566 +#: Controller/UsersController.php:592 msgid "The email could not be sent. Please check errors." msgstr "" -#: Controller/UsersController.php:589 -#: Test/Case/Controller/UsersControllerTest.php:374 +#: Controller/UsersController.php:615 msgid "Your e-mail has been validated!" msgstr "" -#: Controller/UsersController.php:612 +#: Controller/UsersController.php:638 msgid "The url you accessed is not longer valid" msgstr "" -#: Controller/UsersController.php:618 +#: Controller/UsersController.php:644 msgid "Your password was sent to your registered email account" msgstr "" -#: Controller/UsersController.php:622 +#: Controller/UsersController.php:648 msgid "There was an error verifying your account. Please check the email you were sent, and retry the verification link." msgstr "" -#: Controller/UsersController.php:638;748 +#: Controller/UsersController.php:664;774 msgid "Password Reset" msgstr "" -#: Controller/UsersController.php:655;819 +#: Controller/UsersController.php:681;846 msgid "Password changed." msgstr "" -#: Controller/UsersController.php:716 +#: Controller/UsersController.php:742 msgid "Account verification" msgstr "" -#: Controller/UsersController.php:775 +#: Controller/UsersController.php:801 msgid "%s has been sent an email with instruction to reset their password." msgstr "" -#: Controller/UsersController.php:779 +#: Controller/UsersController.php:805 msgid "You should receive an email with further instructions shortly" msgstr "" -#: Controller/UsersController.php:783 +#: Controller/UsersController.php:809 msgid "No user was found with that email." msgstr "" -#: Controller/UsersController.php:813 +#: Controller/UsersController.php:839 msgid "Invalid password reset token, try again." msgstr "" -#: Controller/UsersController.php:822 +#: Controller/UsersController.php:849 msgid "Password changed, you can now login with your new password." msgstr "" -#: Controller/Component/RememberMeComponent.php:230 +#: Controller/Component/RememberMeComponent.php:235 msgid "Invalid options %s" msgstr "" -#: Controller/Component/Auth/TokenAuthenticate.php:67 +#: Controller/Component/Auth/TokenAuthenticate.php:68 msgid "You need to specify token parameter and/or header" msgstr "" -#: Model/User.php:158;339 +#: Model/User.php:173;359 msgid "The passwords are not equal." msgstr "" -#: Model/User.php:160 +#: Model/User.php:175 msgid "Invalid password." msgstr "" -#: Model/User.php:242 -#: Test/Case/Controller/UsersControllerTest.php:382 +#: Model/User.php:261 msgid "Invalid token, please check the email you were sent, and retry the verification link." msgstr "" -#: Model/User.php:247 +#: Model/User.php:266 msgid "The token has expired." msgstr "" -#: Model/User.php:301 +#: Model/User.php:321 msgid "This Email Address exists but was never validated." msgstr "" -#: Model/User.php:303 +#: Model/User.php:323 msgid "This Email Address does not exist in the system." msgstr "" -#: Model/User.php:397 +#: Model/User.php:421 msgid "$this->data['" msgstr "" -#: Model/User.php:443 +#: Model/User.php:467 msgid "The user does not exist." msgstr "" -#: Model/User.php:481 +#: Model/User.php:505 msgid "Invalid Email address." msgstr "" -#: Model/User.php:486 +#: Model/User.php:510 msgid "This email is already verified." msgstr "" -#: Model/User.php:584 +#: Model/User.php:608 msgid "Please enter your email address." msgstr "" -#: Model/User.php:591 +#: Model/User.php:615 msgid "The email address does not exist in the system" msgstr "" -#: Model/User.php:596 +#: Model/User.php:620 msgid "Your account is already authenticated." msgstr "" -#: Model/User.php:601 +#: Model/User.php:625 msgid "Your account is disabled." msgstr "" -#: Test/Case/Controller/UsersControllerTest.php:55 -msgid "Sorry, but you need to login to access this location." -msgstr "" - -#: Test/Case/Controller/UsersControllerTest.php:275 -msgid "adminuser you have successfully logged in" -msgstr "" - -#: Test/Case/Controller/UsersControllerTest.php:401 -msgid "testuser you have successfully logged out" -msgstr "" - #: View/Elements/pagination.ctp:14 msgid "previous" msgstr "" @@ -272,7 +254,7 @@ msgstr "" #: View/Users/add.ctp:18 #: View/Users/admin_add.ctp:18 #: View/Users/admin_edit.ctp:19 -#: View/Users/admin_index.ctp:18 +#: View/Users/admin_index.ctp:19 #: View/Users/admin_view.ctp:15 #: View/Users/search.ctp:18 #: View/Users/view.ctp:15 @@ -315,7 +297,7 @@ msgstr "" #: View/Users/add.ctp:32 #: View/Users/change_password.ctp:26 -#: View/Users/edit.ctp:25 +#: View/Users/edit.ctp:20 #: View/Users/login.ctp:30 #: View/Users/request_password_change.ctp:22 #: View/Users/resend_verification.ctp:22 @@ -344,7 +326,7 @@ msgid "Edit User" msgstr "" #: View/Users/admin_edit.ctp:21 -#: View/Users/admin_index.ctp:19 +#: View/Users/admin_index.ctp:20 #: View/Users/login.ctp:21 #: View/Users/search.ctp:20 msgid "Email" @@ -356,46 +338,46 @@ msgstr "" msgid "Users" msgstr "" -#: View/Users/admin_index.ctp:15 +#: View/Users/admin_index.ctp:17 msgid "Filter" msgstr "" -#: View/Users/admin_index.ctp:20 +#: View/Users/admin_index.ctp:21 #: View/Users/search.ctp:23 msgid "Search" msgstr "" -#: View/Users/admin_index.ctp:32 +#: View/Users/admin_index.ctp:34 #: View/Users/index.ctp:25 #: View/Users/search.ctp:35 msgid "Actions" msgstr "" -#: View/Users/admin_index.ctp:50;53 +#: View/Users/admin_index.ctp:52;55 msgid "Yes" msgstr "" -#: View/Users/admin_index.ctp:50;53 +#: View/Users/admin_index.ctp:52;55 msgid "No" msgstr "" -#: View/Users/admin_index.ctp:59 +#: View/Users/admin_index.ctp:61 #: View/Users/index.ctp:39 #: View/Users/search.ctp:49 msgid "View" msgstr "" -#: View/Users/admin_index.ctp:60 +#: View/Users/admin_index.ctp:62 #: View/Users/search.ctp:50 msgid "Edit" msgstr "" -#: View/Users/admin_index.ctp:61 +#: View/Users/admin_index.ctp:63 #: View/Users/search.ctp:52 msgid "Delete" msgstr "" -#: View/Users/admin_index.ctp:61 +#: View/Users/admin_index.ctp:63 #: View/Users/search.ctp:55 msgid "Are you sure you want to delete # %s?" msgstr "" @@ -415,7 +397,7 @@ msgid "Modified" msgstr "" #: View/Users/change_password.ctp:13 -#: View/Users/edit.ctp:22 +#: View/Users/edit.ctp:17 msgid "Change your password" msgstr "" @@ -484,43 +466,3 @@ msgstr "" msgid "Name" msgstr "" -#: Plugin/Users/Model/User.php:validation for field username -msgid "Please enter a username." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field username -msgid "The username must be alphanumeric." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field username -msgid "This username is already in use." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field username -msgid "The username must have at least 3 characters." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field email -msgid "Please enter a valid email address." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field email -msgid "This email is already in use." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field password -msgid "The password must have at least 6 characters." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field password -msgid "Please enter a password." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field temppassword -msgid "The passwords are not equal, please try again." -msgstr "" - -#: Plugin/Users/Model/User.php:validation for field tos -msgid "You must agree to the terms of use." -msgstr "" - From 98a4cebb11740f89c6048d91696001cbfa2943f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 15 Aug 2015 16:55:04 +0100 Subject: [PATCH 0172/1476] refs #refactor-behavior improve coverage --- src/Controller/Traits/LoginTrait.php | 1 - .../Controller/Traits/LoginTraitTest.php | 81 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index a1e73baa9..f6654fbee 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -33,7 +33,6 @@ public function login() { $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGIN); if (is_array($event->result)) { - $this->Auth->setUser($event->result); return $this->_afterIdentifyUser($event->result); } if ($event->isStopped()) { diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 86b0b78b5..0881465b5 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -12,10 +12,12 @@ namespace Users\Test\TestCase\Controller\Traits; use Cake\Controller\Controller; +use Cake\Core\Configure; use Cake\Event\Event; use Cake\Network\Request; use Cake\TestSuite\TestCase; use Opauth\Opauth\Response; +use Users\Controller\Component\UsersAuthComponent; use Users\Controller\Traits\LoginTrait; class LoginTraitTest extends TestCase @@ -95,6 +97,85 @@ public function testLoginHappy() $this->Trait->login(); } + /** + * test + * + * @return void + */ + public function testLoginBeforeLoginReturningArray() + { + $user = [ + 'id' => 1 + ]; + $event = new Event('event'); + $event->result = $user; + $this->Trait->expects($this->at(0)) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) + ->will($this->returnValue($event)); + $this->Trait->expects($this->at(1)) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_AFTER_LOGIN) + ->will($this->returnValue(new Event('name'))); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $redirectLoginOK = '/'; + $this->Trait->Auth->expects($this->once()) + ->method('setUser') + ->with($user); + $this->Trait->Auth->expects($this->once()) + ->method('redirectUrl') + ->will($this->returnValue($redirectLoginOK)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with($redirectLoginOK); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testLoginBeforeLoginReturningStoppedEvent() + { + $event = new Event('event'); + $event->result = '/'; + $event->stopPropagation(); + $this->Trait->expects($this->at(0)) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) + ->will($this->returnValue($event)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with('/'); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testLoginGet() + { + $this->_mockDispatchEvent(new Event('event')); + $socialLogin = Configure::read('Users.Social.login'); + Configure::write('Users.Social.login', false); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + $this->Trait->login(); + Configure::write('Users.Social.login', $socialLogin); + } + /** * test * From ffc24c97bb31e9c965dcc02af838576316e23eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 15 Aug 2015 17:06:19 +0100 Subject: [PATCH 0173/1476] refs #refactor-behavior improve coverage --- .../Controller/Traits/LoginTraitTest.php | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 0881465b5..7bb3768d5 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -19,6 +19,8 @@ use Opauth\Opauth\Response; use Users\Controller\Component\UsersAuthComponent; use Users\Controller\Traits\LoginTrait; +use Users\Exception\AccountNotActiveException; +use Users\Exception\MissingEmailException; class LoginTraitTest extends TestCase { @@ -32,7 +34,7 @@ public function setUp() parent::setUp(); $request = new Request(); $this->Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') - ->setMethods(['dispatchEvent', 'isStopped', 'redirect']) + ->setMethods(['dispatchEvent', 'redirect']) ->getMockForTrait(); $this->Trait->request = $request; } @@ -97,6 +99,93 @@ public function testLoginHappy() $this->Trait->login(); } + /** + * test + * + * @return void + */ + public function testLoginAfterIdentifyAccountNotActive() + { + $this->Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') + ->setMethods(['dispatchEvent', 'redirect', '_afterIdentifyUser']) + ->getMockForTrait(); + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['success']) + ->disableOriginalConstructor() + ->getMock(); + $user = [ + 'id' => 1, + ]; + $this->Trait->Auth->expects($this->once()) + ->method('identify') + ->will($this->returnValue($user)); + $this->Trait->expects($this->once()) + ->method('_afterIdentifyUser') + ->with($user, false) + ->will($this->throwException(new AccountNotActiveException(''))); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Your social account has not been validated yet. Please check your inbox for instructions'); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testLoginAfterIdentifyMissingEmailException() + { + $this->Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') + ->setMethods(['dispatchEvent', 'redirect', '_afterIdentifyUser']) + ->getMockForTrait(); + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['success']) + ->disableOriginalConstructor() + ->getMock(); + $user = [ + 'id' => 1, + ]; + $this->Trait->Auth->expects($this->once()) + ->method('identify') + ->will($this->returnValue($user)); + $this->Trait->expects($this->once()) + ->method('_afterIdentifyUser') + ->with($user, false) + ->will($this->throwException(new MissingEmailException(''))); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please enter your email'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['controller' => 'Users', 'action' => 'socialEmail']); + $this->Trait->login(); + } + /** * test * From c860f2256c195ff522feee0d3d9968fcd0b1b433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 15 Aug 2015 17:18:54 +0100 Subject: [PATCH 0174/1476] refs #refactor-behavior improve coverage --- .../Controller/Traits/LoginTraitTest.php | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 7bb3768d5..c15114e1e 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -99,6 +99,79 @@ 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->once()) + ->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 = []; + $redirectLoginOK = '/'; + $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('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->request->expects($this->once()) + ->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 = []; + $redirectLoginOK = '/'; + $this->Trait->Auth->expects($this->once()) + ->method('identify') + ->will($this->returnValue($user)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with([ + 'controller' => 'Users', + 'action' => 'socialEmail' + ]); + $this->Trait->login(); + } + /** * test * From e96bb3ca527d37628a40a3a261619b983176a150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 15 Aug 2015 17:24:46 +0100 Subject: [PATCH 0175/1476] refs #refactor-behavior early return --- src/Controller/Traits/UserValidationTrait.php | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 385c4e843..0d3349358 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -78,27 +78,28 @@ public function validate($type = null, $token = null) */ public function resendTokenValidation() { - if ($this->request->is('post')) { - $reference = $this->request->data('reference'); - try { - if ($this->getUsersTable()->resetToken($reference, [ - 'expiration' => Configure::read('Users.Token.expiration'), - 'checkActive' => true, - ])) { - $this->Flash->success(__d('Users', 'Token has been reset successfully')); - } else { - $this->Flash->error(__d('Users', 'Token could not be reset')); - } - return $this->redirect(['action' => 'login']); - } catch (UserNotFoundException $exception) { - $this->Flash->error(__d('Users', 'User {0} was not found', $reference)); - } catch (UserAlreadyActiveException $exception) { - $this->Flash->error(__d('Users', 'User {0} is already active', $reference)); - } catch (Exception $exception) { + $this->set('user', $this->getUsersTable()->newEntity()); + $this->set('_serialize', ['user']); + if (!$this->request->is('post')) { + return; + } + $reference = $this->request->data('reference'); + try { + if ($this->getUsersTable()->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => true, + ])) { + $this->Flash->success(__d('Users', 'Token has been reset successfully')); + } else { $this->Flash->error(__d('Users', 'Token could not be reset')); } + return $this->redirect(['action' => 'login']); + } catch (UserNotFoundException $exception) { + $this->Flash->error(__d('Users', 'User {0} was not found', $reference)); + } catch (UserAlreadyActiveException $exception) { + $this->Flash->error(__d('Users', 'User {0} is already active', $reference)); + } catch (Exception $exception) { + $this->Flash->error(__d('Users', 'Token could not be reset')); } - $this->set('user', $this->getUsersTable()->newEntity()); - $this->set('_serialize', ['user']); } } From 1f9366e4ebbd4972dba11342caaac1fff253cf8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 15 Aug 2015 18:08:49 +0100 Subject: [PATCH 0176/1476] refs #shell WIP: starting some shell utility tasks --- src/Model/Table/UsersTable.php | 11 ++--- src/Shell/UsersShell.php | 80 ++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 src/Shell/UsersShell.php diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index c0ac5fd86..b3a544b70 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -380,19 +380,20 @@ protected function _updateToken(&$user, $tokenExpiration) * * @todo: move into new behavior */ - protected function _generateUsername($username) + public function generateUniqueUsername($username) { $i = 0; + $checkUsername = $username; while (true) { - $existingUsername = $this->find()->where([$this->alias() . '.username' => $username])->count(); + $existingUsername = $this->find()->where([$this->alias() . '.username' => $checkUsername])->count(); if ($existingUsername > 0) { - $username = $username . $i; + $checkUsername = $username . $i; $i++; continue; } break; } - return $username; + return $checkUsername; } /** @@ -514,7 +515,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail } } - $userData['username'] = $this->_generateUsername(Hash::get($userData, 'username')); + $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); if ($useEmail) { $userData['email'] = $data->email; if (!$data->validated) { diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php new file mode 100644 index 000000000..4fbd6456e --- /dev/null +++ b/src/Shell/UsersShell.php @@ -0,0 +1,80 @@ +loadModel('Users.Users'); + } + + /** + * + * @return OptionParser + */ + public function getOptionParser() + { + $parser = parent::getOptionParser(); + $parser->description(__d('Users', 'Utilities for CakeDC Users Plugin')) + ->addSubcommand('addSuperuser')->description(__d('Users', 'Add a new superadmin user for testing purposes')); + return $parser; + } + + /** + * Add a new superadmin user + * + * @return void + */ + public function addSuperuser() + { + $username = $this->Users->generateUniqueUsername('superadmin'); + $password = str_replace('-', '', \Cake\Utility\Text::uuid()); + $user = [ + 'username' => $username, + 'email' => $username . '@example.com', + 'password' => $password, + 'active' => 1, + ]; + + $userEntity = $this->Users->newEntity($user); + $userEntity->is_superuser = true; + $userEntity->role = 'superuser'; + $savedUser = $this->Users->save($userEntity); + $this->out(__d('Users', 'Superuser added:')); + $this->out(__d('Users', 'Id: {0}', $savedUser->id)); + $this->out(__d('Users', 'Username: {0}', $username)); + $this->out(__d('Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('Users', 'Password: {0}', $password)); + } + + //resetAllPasswords to XXX + //resetPassword user to XXX + //addUser + //changeRole user to XXX + //deleteUser user + //deactivateUser user + //activateUser user + //add filters LIKE in username and email to some tasks + // --force to ignore "you are about to do X to Y users" +} From f22afd496d70e701a826016a54e24a8d92665112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 16 Aug 2015 17:08:03 +0100 Subject: [PATCH 0177/1476] refs #refactor-behavior refactor trait into register behavior --- src/Model/Behavior/Behavior.php | 84 +++++++++++++++++++ .../RegisterBehavior.php} | 76 ++++------------- src/Model/Table/Traits/SocialTrait.php | 2 +- src/Model/Table/UsersTable.php | 19 +---- tests/TestCase/Model/Table/UsersTableTest.php | 1 + 5 files changed, 102 insertions(+), 80 deletions(-) create mode 100644 src/Model/Behavior/Behavior.php rename src/Model/{Table/Traits/RegisterTrait.php => Behavior/RegisterBehavior.php} (61%) diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php new file mode 100644 index 000000000..c9d1681df --- /dev/null +++ b/src/Model/Behavior/Behavior.php @@ -0,0 +1,84 @@ +template() if you pass an Email + * instance + * + * @return array email send result + */ + public function sendEmail(EntityInterface $user, $subject, Email $email = null) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + return $this->getEmailInstance($email) + ->to($user['email']) + ->subject($firstName . $subject) + ->viewVars($user->toArray()) + ->send(); + } + + /** + * Get or initialize the email instance. Used for mocking. + * + * @param Email $email if email provided, we'll use the instance instead of creating a new one + * @return Email + */ + public function getEmailInstance(Email $email = null) + { + if ($email === null) { + $email = new Email('default'); + $email->template('Users.validation') + ->emailFormat('both'); + } + + return $email; + } + + /** + * DRY for update active and token based on validateEmail flag + * + * @param EntityInterface $user User to be updated. + * @param type $validateEmail email user to validate. + * @param type $tokenExpiration token to be updated. + * @return EntityInterface + */ + public function updateActive(EntityInterface $user, $validateEmail, $tokenExpiration) + { + $emailValidated = $user['validated']; + if (!$emailValidated && $validateEmail) { + $user['active'] = false; + $user->updateToken($tokenExpiration); + } else { + $user['active'] = true; + $user['activation_date'] = new Time(); + } + + return $user; + } +} diff --git a/src/Model/Table/Traits/RegisterTrait.php b/src/Model/Behavior/RegisterBehavior.php similarity index 61% rename from src/Model/Table/Traits/RegisterTrait.php rename to src/Model/Behavior/RegisterBehavior.php index 3cf8352b9..36078f301 100644 --- a/src/Model/Table/Traits/RegisterTrait.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -9,25 +9,23 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Model\Table\Traits; +namespace Users\Model\Behavior; use Cake\Datasource\EntityInterface; -use Cake\Network\Email\Email; use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; use Users\Exception\TokenExpiredException; use Users\Exception\UserAlreadyActiveException; use Users\Exception\UserNotFoundException; +use Users\Model\Behavior\Behavior; use Users\Model\Entity\User; /** - * Covers the login, logout and social login - * + * Covers the user registration */ -trait RegisterTrait +class RegisterBehavior extends Behavior { - /** * Registers an user. * @@ -36,7 +34,6 @@ trait RegisterTrait * @param array $options ['tokenExpiration] * @return bool|EntityInterface * @throws InvalidArgumentException - * @todo: move into new behavior */ public function register($user, $data, $options) { @@ -45,7 +42,7 @@ public function register($user, $data, $options) if ($validateEmail) { $validator = 'email'; } - $user = $this->patchEntity($user, $data, ['validate' => $validator]); + $user = $this->_table->patchEntity($user, $data, ['validate' => $validator]); $tokenExpiration = Hash::get($options, 'token_expiration'); $useTos = Hash::get($options, 'use_tos'); @@ -57,56 +54,16 @@ public function register($user, $data, $options) $user->tos_date = new DateTime(); } $user->validated = false; - //@todo mov updateActive to afterSave? - $this->_updateActive($user, $validateEmail, $tokenExpiration); - $this->isValidateEmail = $validateEmail; - $userSaved = $this->save($user); + //@todo move updateActive to afterSave? + $user = $this->updateActive($user, $validateEmail, $tokenExpiration); + $this->_table->isValidateEmail = $validateEmail; + $userSaved = $this->_table->save($user); if ($userSaved && $validateEmail) { - $this->sendValidationEmail($user); + $this->_table->sendEmail($user, __d('Users', 'Your account validation link')); } return $userSaved; } - /** - * DRY for update active and token based on validateEmail flag - * - * @param type $user Reference of user to be updated. - * @param type $validateEmail email user to validate. - * @param type $tokenExpiration token to be updated. - * @return void - */ - protected function _updateActive(&$user, $validateEmail, $tokenExpiration) - { - $emailValidated = $user['validated']; - if (!$emailValidated && $validateEmail) { - $user['active'] = false; - $user->updateToken($tokenExpiration); - } else { - $user['active'] = true; - $user['activation_date'] = new DateTime(); - } - } - - /** - * Send the validation email to the newly registered user - * - * @param EntityInterface $user User entity - * @param Email $email instance, if null the default email configuration with the - * Users.validation template will be used, so set a ->template() if you pass an Email - * instance - * @return array email send result - */ - public function sendValidationEmail(EntityInterface $user, Email $email = null) - { - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $subject = __d('Users', '{0}Your account validation link', $firstName); - return $this->getEmailInstance($email) - ->to($user['email']) - ->subject($subject) - ->viewVars($user->toArray()) - ->send(); - } - /** * Validates token and return user * @@ -118,14 +75,14 @@ public function sendValidationEmail(EntityInterface $user, Email $email = null) */ public function validate($token, $callback = null) { - $user = $this->find() + $user = $this->_table->find() ->select(['token_expires', 'id', 'active', 'token']) ->where(['token' => $token]) ->first(); if (!empty($user)) { if (!$user->tokenExpired()) { if (!empty($callback) && method_exists($this, $callback)) { - return $this->{$callback}($user); + return $this->_table->{$callback}($user); } else { return $user; } @@ -143,7 +100,6 @@ public function validate($token, $callback = null) * @param EntityInterface $user user object. * @return mixed User entity or bool false if the user could not be activated * @throws UserAlreadyActiveException - * @todo: move into new behavior */ public function activateUser(EntityInterface $user) { @@ -153,7 +109,7 @@ public function activateUser(EntityInterface $user) $user = $this->_removesValidationToken($user); $user->activation_date = new DateTime(); $user->active = true; - $result = $this->save($user); + $result = $this->_table->save($user); return $result; } @@ -162,15 +118,13 @@ public function activateUser(EntityInterface $user) * Removes user token for validation * * @param User $user user object. - * @return User - * - * @todo: move into new behavior + * @return EntityInterface */ protected function _removesValidationToken(EntityInterface $user) { $user->token = null; $user->token_expires = null; - $result = $this->save($user); + $result = $this->_table->save($user); return $result; } diff --git a/src/Model/Table/Traits/SocialTrait.php b/src/Model/Table/Traits/SocialTrait.php index 0599ef830..6600319df 100644 --- a/src/Model/Table/Traits/SocialTrait.php +++ b/src/Model/Table/Traits/SocialTrait.php @@ -153,12 +153,12 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['password'] = $this->randomString(); $userData['avatar'] = Hash::get($data->info, 'image'); $userData['validated'] = $data->validated; - $this->_updateActive($userData, false, $tokenExpiration); $userData['tos_date'] = date("Y-m-d H:i:s"); $userData['gender'] = Hash::get($data->raw, 'gender'); $userData['timezone'] = Hash::get($data->raw, 'timezone'); $userData['social_accounts'][] = $accountData; $user = $this->newEntity($userData, ['associated' => ['SocialAccounts']]); + $user = $this->updateActive($user, false, $tokenExpiration); } else { if ($useEmail && !$data->validated) { $accountData['active'] = false; diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 85e61b7e2..cd54c2d2e 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -32,7 +32,6 @@ class UsersTable extends Table use PasswordManagementTrait; use RandomStringTrait; - use RegisterTrait; use SocialTrait; /** @@ -56,6 +55,7 @@ public function initialize(array $config) $this->displayField('id'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); + $this->addBehavior('Users.Register'); $this->hasMany('SocialAccounts', [ 'foreignKey' => 'user_id', 'className' => 'Users.SocialAccounts' @@ -187,21 +187,4 @@ public function buildRules(RulesChecker $rules) return $rules; } - - /** - * Get or initialize the email instance. Used for mocking. - * - * @param Email $email if email provided, we'll use the instance instead of creating a new one - * @return Email - */ - public function getEmailInstance(Email $email = null) - { - if ($email === null) { - $email = new Email('default'); - $email->template('Users.validation') - ->emailFormat('both'); - } - - return $email; - } } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 1298499e0..92237196a 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -287,6 +287,7 @@ public function testSocialLoginCreateNewAccount() */ public function testSendValidationEmail() { + $this->markTestIncomplete('move this unit test to the BehaviorTest class'); $user = $this->Users->newEntity([ 'first_name' => 'FirstName', 'email' => 'test@example.com', From ab95d997a60efe7f037c71287328e4edd46a80d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 16 Aug 2015 17:17:20 +0100 Subject: [PATCH 0178/1476] Check Opauth.path exists before connecting the route --- config/routes.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/config/routes.php b/config/routes.php index 1c5fbf3c8..8ded25646 100644 --- a/config/routes.php +++ b/config/routes.php @@ -9,19 +9,22 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -use Cake\Routing\Router; use Cake\Core\Configure; +use Cake\Routing\Router; Router::plugin('Users', function ($routes) { $routes->fallbacks('DashedRoute'); }); -Router::scope('/auth', function ($routes) { - $routes->connect( - '/*', - Configure::read('Opauth.path') - ); -}); +if (is_array(Configure::read('Opauth.path'))) { + Router::scope('/auth', function ($routes) { + $routes->connect( + '/*', + Configure::read('Opauth.path') + ); + }); +} + Router::connect('/accounts/validate/*', [ 'admin' => false, 'plugin' => 'Users', From 84afb12eb31bfadc69185acd5d17d7b182700916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 16 Aug 2015 18:04:52 +0100 Subject: [PATCH 0179/1476] refs #refactor-behavior WIP: work on moving traits to behaviors and moving tests around --- src/Model/Behavior/Behavior.php | 23 ++- .../PasswordBehavior.php} | 20 +-- src/Model/Behavior/RegisterBehavior.php | 21 +-- src/Model/Behavior/SocialAccountBehavior.php | 154 ++++++++++++++++++ .../SocialBehavior.php} | 26 +-- src/Model/Table/SocialAccountsTable.php | 115 ------------- src/Model/Table/UsersTable.php | 10 +- .../PasswordBehaviorTest.php} | 43 ++--- .../Model/Table/SocialAccountsTableTest.php | 1 + tests/TestCase/Model/Table/UsersTableTest.php | 2 + 10 files changed, 229 insertions(+), 186 deletions(-) rename src/Model/{Table/Traits/PasswordManagementTrait.php => Behavior/PasswordBehavior.php} (87%) create mode 100644 src/Model/Behavior/SocialAccountBehavior.php rename src/Model/{Table/Traits/SocialTrait.php => Behavior/SocialBehavior.php} (89%) rename tests/TestCase/Model/{Table/Traits/PasswordManagementTraitTest.php => Behavior/PasswordBehaviorTest.php} (75%) diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index c9d1681df..dfbd844e8 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -33,10 +33,10 @@ class Behavior extends BaseBehavior * * @return array email send result */ - public function sendEmail(EntityInterface $user, $subject, Email $email = null) + protected function _sendEmail(EntityInterface $user, $subject, Email $email = null) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - return $this->getEmailInstance($email) + return $this->_getEmailInstance($email) ->to($user['email']) ->subject($firstName . $subject) ->viewVars($user->toArray()) @@ -49,7 +49,7 @@ public function sendEmail(EntityInterface $user, $subject, Email $email = null) * @param Email $email if email provided, we'll use the instance instead of creating a new one * @return Email */ - public function getEmailInstance(Email $email = null) + protected function _getEmailInstance(Email $email = null) { if ($email === null) { $email = new Email('default'); @@ -68,7 +68,7 @@ public function getEmailInstance(Email $email = null) * @param type $tokenExpiration token to be updated. * @return EntityInterface */ - public function updateActive(EntityInterface $user, $validateEmail, $tokenExpiration) + protected function _updateActive(EntityInterface $user, $validateEmail, $tokenExpiration) { $emailValidated = $user['validated']; if (!$emailValidated && $validateEmail) { @@ -81,4 +81,19 @@ public function updateActive(EntityInterface $user, $validateEmail, $tokenExpira return $user; } + + /** + * Remove user token for validation + * + * @param User $user user object. + * @return EntityInterface + */ + protected function _removeValidationToken(EntityInterface $user) + { + $user->token = null; + $user->token_expires = null; + $result = $this->_table->save($user); + + return $result; + } } diff --git a/src/Model/Table/Traits/PasswordManagementTrait.php b/src/Model/Behavior/PasswordBehavior.php similarity index 87% rename from src/Model/Table/Traits/PasswordManagementTrait.php rename to src/Model/Behavior/PasswordBehavior.php index 188ac9332..f1f487a08 100644 --- a/src/Model/Table/Traits/PasswordManagementTrait.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Model\Table\Traits; +namespace Users\Model\Behavior; use Cake\Datasource\EntityInterface; use Cake\Network\Email\Email; @@ -18,12 +18,12 @@ use Users\Exception\UserAlreadyActiveException; use Users\Exception\UserNotFoundException; use Users\Exception\WrongPasswordException; +use Users\Model\Behavior\Behavior; /** - * Password management features - * + * Covers the password management features */ -trait PasswordManagementTrait +class PasswordBehavior extends Behavior { /** * Resets user token @@ -59,7 +59,7 @@ public function resetToken($reference, array $options = []) $user->activation_date = null; } $user->updateToken(Hash::get($options, 'expiration')); - $saveResult = $this->save($user); + $saveResult = $this->_table->save($user); if (Hash::get($options, 'sendEmail')) { $this->sendResetPasswordEmail($saveResult); } @@ -74,7 +74,7 @@ public function resetToken($reference, array $options = []) */ protected function _getUser($reference) { - return $this->findAllByUsernameOrEmail($reference, $reference)->first(); + return $this->_table->findAllByUsernameOrEmail($reference, $reference)->first(); } /** @@ -90,7 +90,7 @@ public function sendResetPasswordEmail(EntityInterface $user, Email $email = nul { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $subject = __d('Users', '{0}Your reset password link', $firstName); - return $this->getEmailInstance($email) + return $this->_getEmailInstance($email) ->template('Users.reset_password') ->to($user['email']) ->subject($subject) @@ -106,7 +106,7 @@ public function sendResetPasswordEmail(EntityInterface $user, Email $email = nul */ public function changePassword(EntityInterface $user) { - $currentUser = $this->get($user->id, [ + $currentUser = $this->_table->get($user->id, [ 'contain' => [] ]); @@ -115,9 +115,9 @@ public function changePassword(EntityInterface $user) throw new WrongPasswordException(__d('Users', 'The old password does not match')); } } - $user = $this->save($user); + $user = $this->_table->save($user); if (!empty($user)) { - $user = $this->_removesValidationToken($user); + $user = $this->removeValidationToken($user); } return $user; } diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 36078f301..4e54ba549 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -55,11 +55,11 @@ public function register($user, $data, $options) } $user->validated = false; //@todo move updateActive to afterSave? - $user = $this->updateActive($user, $validateEmail, $tokenExpiration); + $user = $this->_updateActive($user, $validateEmail, $tokenExpiration); $this->_table->isValidateEmail = $validateEmail; $userSaved = $this->_table->save($user); if ($userSaved && $validateEmail) { - $this->_table->sendEmail($user, __d('Users', 'Your account validation link')); + $this->_sendEmail($user, __d('Users', 'Your account validation link')); } return $userSaved; } @@ -106,26 +106,11 @@ public function activateUser(EntityInterface $user) if ($user->active) { throw new UserAlreadyActiveException(__d('Users', "User account already validated")); } - $user = $this->_removesValidationToken($user); + $user = $this->_removeValidationToken($user); $user->activation_date = new DateTime(); $user->active = true; $result = $this->_table->save($user); return $result; } - - /** - * Removes user token for validation - * - * @param User $user user object. - * @return EntityInterface - */ - protected function _removesValidationToken(EntityInterface $user) - { - $user->token = null; - $user->token_expires = null; - $result = $this->_table->save($user); - - return $result; - } } diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php new file mode 100644 index 000000000..549b8d4a9 --- /dev/null +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -0,0 +1,154 @@ +_table->belongsTo('Users', [ + 'foreignKey' => 'user_id', + 'joinType' => 'INNER', + 'className' => Configure::read('Users.table') + ]); + } + + /** + * After save callback + * + * @param Event $event event + * @param Entity $entity entity + * @param ArrayObject $options options + * @return mixed + */ + public function afterSave(Event $event, Entity $entity, $options) + { + if ($entity->active) { + return true; + } + $user = $this->_table->Users->find()->where(['Users.id' => $entity->user_id, 'Users.active' => true])->first(); + if (empty($user)) { + return true; + } + return $this->sendSocialValidationEmail($entity, $user); + } + + /** + * Send social validation email to the user + * + * @param EntityInterface $socialAccount social account + * @param EntityInterface $user user + * @param Email $email Email instance or null to use 'default' configuration + * @return mixed + */ + public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) + { + $email = $this->_getEmailInstance($email); + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + //note: we control the space after the username in the previous line + $subject = __d('Users', '{0}Your social account validation link', $firstName); + return $email + ->to($user['email']) + ->subject($subject) + ->viewVars(compact('user', 'socialAccount')) + ->send(); + } + + /** + * Validates the social account + * + * @param string $provider provider + * @param string $reference reference + * @param string $token token + * @throws RecordNotFoundException + * @throws AccountAlreadyActiveException + * @return User + */ + public function validateAccount($provider, $reference, $token) + { + $socialAccount = $this->_table->find() + ->select(['id', 'provider', 'reference', 'active', 'token']) + ->where(['provider' => $provider, 'reference' => $reference]) + ->first(); + + if (!empty($socialAccount) && $socialAccount->token === $token) { + if ($socialAccount->active) { + throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); + } + } else { + throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); + } + + return $this->_activateAccount($socialAccount); + } + + /** + * Validates the social account + * + * @param string $provider provider + * @param string $reference reference + * @throws RecordNotFoundException + * @throws AccountAlreadyActiveException + * @return User + */ + public function resendValidation($provider, $reference) + { + $socialAccount = $this->_table->find() + ->where(['provider' => $provider, 'reference' => $reference]) + ->contain('Users') + ->first(); + + if (!empty($socialAccount)) { + if ($socialAccount->active) { + throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); + } + } else { + throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); + } + + return $this->sendSocialValidationEmail($socialAccount, $socialAccount->user); + } + + /** + * Activates an account + * + * @param Account $socialAccount social account + * @return Account + */ + protected function _activateAccount($socialAccount) + { + $socialAccount->active = true; + $result = $this->_table->save($socialAccount); + return $result; + } +} diff --git a/src/Model/Table/Traits/SocialTrait.php b/src/Model/Behavior/SocialBehavior.php similarity index 89% rename from src/Model/Table/Traits/SocialTrait.php rename to src/Model/Behavior/SocialBehavior.php index 6600319df..762c67841 100644 --- a/src/Model/Table/Traits/SocialTrait.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Model\Table\Traits; +namespace Users\Model\Behavior; use Cake\Datasource\EntityInterface; use Cake\Utility\Hash; @@ -17,14 +17,18 @@ use InvalidArgumentException; use Users\Exception\AccountNotActiveException; use Users\Exception\MissingEmailException; +use Users\Model\Behavior\Behavior; use Users\Model\Table\SocialAccountsTable; +use Users\Traits\RandomStringTrait; /** * Covers social features * */ -trait SocialTrait +class SocialBehavior extends Behavior { + use RandomStringTrait; + /** * Performs social login * @@ -36,7 +40,7 @@ public function socialLogin($data, $options = []) { $provider = $data->provider; $reference = $data->uid; - $existingAccount = $this->SocialAccounts->find() + $existingAccount = $this->_table->SocialAccounts->find() ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $provider]) ->contain(['Users']) ->first(); @@ -79,13 +83,13 @@ protected function _createSocialUser($data, $options = []) if ($useEmail && empty($data->email)) { throw new MissingEmailException(__d('Users', 'Email not present')); } else { - $existingUser = $this->find() - ->where([$this->alias() . '.email' => $data->email]) + $existingUser = $this->_table->find() + ->where([$this->_table->alias() . '.email' => $data->email]) ->first(); } $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); - $this->isValidateEmail = $validateEmail; - $result = $this->save($user); + $this->_table->isValidateEmail = $validateEmail; + $result = $this->_table->save($user); return $result; } @@ -157,13 +161,13 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['gender'] = Hash::get($data->raw, 'gender'); $userData['timezone'] = Hash::get($data->raw, 'timezone'); $userData['social_accounts'][] = $accountData; - $user = $this->newEntity($userData, ['associated' => ['SocialAccounts']]); - $user = $this->updateActive($user, false, $tokenExpiration); + $user = $this->_table->newEntity($userData, ['associated' => ['SocialAccounts']]); + $user = $this->_updateActive($user, false, $tokenExpiration); } else { if ($useEmail && !$data->validated) { $accountData['active'] = false; } - $user = $this->patchEntity($existingUser, [ + $user = $this->_table->patchEntity($existingUser, [ 'social_accounts' => [$accountData] ], ['associated' => ['SocialAccounts']]); } @@ -180,7 +184,7 @@ protected function _generateUsername($username) { $i = 0; while (true) { - $existingUsername = $this->find()->where([$this->alias() . '.username' => $username])->count(); + $existingUsername = $this->_table->find()->where([$this->_table->alias() . '.username' => $username])->count(); if ($existingUsername > 0) { $username = $username . $i; $i++; diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 807af9296..6298c2a57 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -51,11 +51,6 @@ public function initialize(array $config) $this->displayField('id'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); - $this->belongsTo('Users', [ - 'foreignKey' => 'user_id', - 'joinType' => 'INNER', - 'className' => Configure::read('Users.table') - ]); } /** @@ -127,114 +122,4 @@ public function buildRules(RulesChecker $rules) $rules->add($rules->existsIn(['user_id'], 'Users')); return $rules; } - - /** - * After save callback - * - * @param Event $event event - * @param Entity $entity entity - * @param ArrayObject $options options - * @return mixed - */ - public function afterSave(Event $event, Entity $entity, $options) - { - if ($entity->active) { - return true; - } - $user = $this->Users->find()->where(['Users.id' => $entity->user_id, 'Users.active' => true])->first(); - if (empty($user)) { - return true; - } - return $this->sendSocialValidationEmail($entity, $user); - } - - /** - * Send social validation email to the user - * - * @param EntityInterface $socialAccount social account - * @param EntityInterface $user user - * @param Email $email Email instance or null to use 'default' configuration - * @return mixed - */ - public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) - { - $email = $this->Users->getEmailInstance($email); - $email->template('Users.social_account_validation'); - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - //note: we control the space after the username in the previous line - $subject = __d('Users', '{0}Your social account validation link', $firstName); - return $email - ->to($user['email']) - ->subject($subject) - ->viewVars(compact('user', 'socialAccount')) - ->send(); - } - - /** - * Validates the social account - * - * @param string $provider provider - * @param string $reference reference - * @param string $token token - * @throws RecordNotFoundException - * @throws AccountAlreadyActiveException - * @return User - */ - public function validateAccount($provider, $reference, $token) - { - $socialAccount = $this->find() - ->select(['id', 'provider', 'reference', 'active', 'token']) - ->where(['provider' => $provider, 'reference' => $reference]) - ->first(); - - if (!empty($socialAccount) && $socialAccount->token === $token) { - if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); - } - } else { - throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); - } - - return $this->_activateAccount($socialAccount); - } - - /** - * Validates the social account - * - * @param string $provider provider - * @param string $reference reference - * @throws RecordNotFoundException - * @throws AccountAlreadyActiveException - * @return User - */ - public function resendValidation($provider, $reference) - { - $socialAccount = $this->find() - ->where(['provider' => $provider, 'reference' => $reference]) - ->contain('Users') - ->first(); - - if (!empty($socialAccount)) { - if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); - } - } else { - throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); - } - - return $this->sendSocialValidationEmail($socialAccount, $socialAccount->user); - } - - /** - * Activates an account - * - * @param Account $socialAccount social account - * @return Account - */ - protected function _activateAccount($socialAccount) - { - $socialAccount->active = true; - $result = $this->save($socialAccount); - return $result; - } } diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index cd54c2d2e..91228b5ae 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -19,10 +19,6 @@ use Cake\Validation\Validator; use Users\Exception\WrongPasswordException; use Users\Model\Entity\User; -use Users\Model\Table\Traits\PasswordManagementTrait; -use Users\Model\Table\Traits\RegisterTrait; -use Users\Model\Table\Traits\SocialTrait; -use Users\Traits\RandomStringTrait; /** * Users Model @@ -30,10 +26,6 @@ class UsersTable extends Table { - use PasswordManagementTrait; - use RandomStringTrait; - use SocialTrait; - /** * Flag to set email check in buildRules or not * @@ -56,6 +48,8 @@ public function initialize(array $config) $this->primaryKey('id'); $this->addBehavior('Timestamp'); $this->addBehavior('Users.Register'); + $this->addBehavior('Users.Password'); + $this->addBehavior('Users.Social'); $this->hasMany('SocialAccounts', [ 'foreignKey' => 'user_id', 'className' => 'Users.SocialAccounts' diff --git a/tests/TestCase/Model/Table/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php similarity index 75% rename from tests/TestCase/Model/Table/Traits/PasswordManagementTraitTest.php rename to tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index abdaa8fcc..2eae5ae87 100644 --- a/tests/TestCase/Model/Table/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -15,12 +15,11 @@ use Cake\TestSuite\TestCase; use InvalidArgumentException; use Users\Exception\UserAlreadyActiveException; -use Users\Model\Table\Traits\PasswordManagementTrait; /** * Test Case */ -class PasswordManagementTraitTest extends TestCase +class PasswordBehaviorTest extends TestCase { /** * Fixtures @@ -39,9 +38,13 @@ class PasswordManagementTraitTest extends TestCase public function setUp() { parent::setUp(); - $this->Trait = $this->getMockBuilder('Users\Model\Table\Traits\PasswordManagementTrait') - ->setMethods(['_getUser', 'save', 'sendResetPasswordEmail']) - ->getMockForTrait(); + $this->table = $this->getMockBuilder('Cake\ORM\Table') + ->setMethods(['save']) + ->getMock(); + $this->Behavior = $this->getMockBuilder('Users\Model\Behavior\PasswordBehavior') + ->setMethods(['_getUser']) + ->setConstructorArgs([$this->table]) + ->getMock(); $this->user = TableRegistry::get('Users.Users')->findAllByUsername('user-1')->first(); } @@ -52,7 +55,7 @@ public function setUp() */ public function tearDown() { - unset($this->Trait, $this->user); + unset($this->Behavior, $this->user); parent::tearDown(); } @@ -64,17 +67,17 @@ public function tearDown() public function testResetToken() { $token = $this->user->token; - $this->Trait->expects($this->once()) + $this->Behavior->expects($this->once()) ->method('_getUser') ->with('user-1') ->will($this->returnValue($this->user)); - $this->Trait->expects($this->once()) + $this->table->expects($this->once()) ->method('save') ->will($this->returnValue($this->user)); - $this->Trait->expects($this->never()) + $this->Behavior->expects($this->never()) ->method('sendResetPasswordEmail') ->with($this->user); - $result = $this->Trait->resetToken('user-1', [ + $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, 'checkActive' => true, ]); @@ -90,17 +93,17 @@ public function testResetToken() public function testResetTokenSendEmail() { $token = $this->user->token; - $this->Trait->expects($this->once()) + $this->Behavior->expects($this->once()) ->method('_getUser') ->with('user-1') ->will($this->returnValue($this->user)); - $this->Trait->expects($this->once()) + $this->table->expects($this->once()) ->method('save') ->will($this->returnValue($this->user)); - $this->Trait->expects($this->once()) + $this->Behavior->expects($this->once()) ->method('sendResetPasswordEmail') ->with($this->user); - $result = $this->Trait->resetToken('user-1', [ + $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, 'checkActive' => true, 'sendEmail' => true @@ -117,7 +120,7 @@ public function testResetTokenSendEmail() */ public function testResetTokenWithNullParams() { - $this->Trait->resetToken(null); + $this->Behavior->resetToken(null); } /** @@ -127,7 +130,7 @@ public function testResetTokenWithNullParams() */ public function testResetTokenNotExistingUser() { - $this->Trait->resetToken('user-not-found', [ + $this->Behavior->resetToken('user-not-found', [ 'expiration' => 3600 ]); } @@ -140,17 +143,17 @@ public function testResetTokenNotExistingUser() public function testResetTokenUserAlreadyActive() { $activeUser = TableRegistry::get('Users.Users')->findAllByUsername('user-4')->first(); - $this->Trait->expects($this->once()) + $this->Behavior->expects($this->once()) ->method('_getUser') ->with('user-4') ->will($this->returnValue($activeUser)); - $this->Trait->expects($this->never()) + $this->table->expects($this->never()) ->method('save') ->will($this->returnValue($this->user)); - $this->Trait->expects($this->never()) + $this->Behavior->expects($this->never()) ->method('sendResetPasswordEmail') ->with($this->user); - $this->Trait->resetToken('user-4', [ + $this->Behavior->resetToken('user-4', [ 'expiration' => 3600, 'checkActive' => true, ]); diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index a9cf95631..e6ecafddf 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -134,6 +134,7 @@ public function testAfterSaveSocialNotActiveUserNotActive() */ public function testAfterSaveSocialNotActiveUserActive() { + $this->markTestIncomplete('fix this test after SocialBehavior done'); $event = new Event('eventName'); $entity = $this->SocialAccounts->findById(5)->first(); $this->SocialAccounts->Users = $this->getMockForModel('Users.Users', ['getEmailInstance']); diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 92237196a..54dcc223e 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -392,6 +392,7 @@ public function testSendResetPasswordEmail() */ public function testGetEmailInstance() { + $this->markTestIncomplete('move this test to BehaviorTest class'); $email = $this->Users->getEmailInstance(); $this->assertInstanceOf('Cake\Network\Email\Email', $email); $this->assertEquals([ @@ -407,6 +408,7 @@ public function testGetEmailInstance() */ public function testGetEmailInstanceOverrideEmail() { + $this->markTestIncomplete('move this test to BehaviorTest class'); $email = new Email(); $email->template('another_template'); $email = $this->Users->getEmailInstance($email); From 7bdd4d183e5e18ebd186787e9d35679b89afcfa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 17 Aug 2015 10:15:26 +0100 Subject: [PATCH 0180/1476] refs #refactor-behavior mark tests to move after refactor into behaviors --- src/Model/Behavior/SocialAccountBehavior.php | 14 ++++-- src/Model/Table/SocialAccountsTable.php | 1 + .../Model/Behavior/PasswordBehaviorTest.php | 49 ++++++------------- .../Model/Table/SocialAccountsTableTest.php | 4 ++ 4 files changed, 30 insertions(+), 38 deletions(-) diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 549b8d4a9..ae0f7fd47 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -11,15 +11,19 @@ namespace Users\Model\Behavior; +use ArrayObject; +use Cake\Core\Configure; use Cake\Datasource\EntityInterface; -use Cake\Utility\Hash; -use DateTime; +use Cake\Datasource\Exception\RecordNotFoundException; +use Cake\Event\Event; +use Cake\Network\Email\Email; +use Cake\ORM\Entity; use InvalidArgumentException; +use Users\Exception\AccountAlreadyActiveException; use Users\Exception\AccountNotActiveException; use Users\Exception\MissingEmailException; use Users\Model\Behavior\Behavior; -use Users\Model\Table\SocialAccountsTable; -use Users\Traits\RandomStringTrait; +use Users\Model\Entity\User; /** * Covers social account features @@ -143,7 +147,7 @@ public function resendValidation($provider, $reference) * Activates an account * * @param Account $socialAccount social account - * @return Account + * @return EntityInterface */ protected function _activateAccount($socialAccount) { diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 6298c2a57..a9c200f3e 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -51,6 +51,7 @@ public function initialize(array $config) $this->displayField('id'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); + $this->addBehavior('Users.SocialAccount'); } /** diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 2eae5ae87..095fcfc09 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -15,6 +15,7 @@ use Cake\TestSuite\TestCase; use InvalidArgumentException; use Users\Exception\UserAlreadyActiveException; +use Users\Model\Table\UsersTable; /** * Test Case @@ -38,14 +39,11 @@ class PasswordBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $this->table = $this->getMockBuilder('Cake\ORM\Table') - ->setMethods(['save']) - ->getMock(); + $this->table = TableRegistry::get('Users.Users'); $this->Behavior = $this->getMockBuilder('Users\Model\Behavior\PasswordBehavior') - ->setMethods(['_getUser']) + ->setMethods(['sendResetPasswordEmail']) ->setConstructorArgs([$this->table]) ->getMock(); - $this->user = TableRegistry::get('Users.Users')->findAllByUsername('user-1')->first(); } /** @@ -55,7 +53,7 @@ public function setUp() */ public function tearDown() { - unset($this->Behavior, $this->user); + unset($this->table, $this->Behavior); parent::tearDown(); } @@ -66,17 +64,11 @@ public function tearDown() */ public function testResetToken() { - $token = $this->user->token; - $this->Behavior->expects($this->once()) - ->method('_getUser') - ->with('user-1') - ->will($this->returnValue($this->user)); - $this->table->expects($this->once()) - ->method('save') - ->will($this->returnValue($this->user)); + $user = $this->table->findAllByUsername('user-1')->first(); + $token = $user->token; $this->Behavior->expects($this->never()) ->method('sendResetPasswordEmail') - ->with($this->user); + ->with($user); $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, 'checkActive' => true, @@ -92,23 +84,18 @@ public function testResetToken() */ public function testResetTokenSendEmail() { - $token = $this->user->token; - $this->Behavior->expects($this->once()) - ->method('_getUser') - ->with('user-1') - ->will($this->returnValue($this->user)); - $this->table->expects($this->once()) - ->method('save') - ->will($this->returnValue($this->user)); + $user = $this->table->findAllByUsername('user-1')->first(); + $token = $user->token; + $tokenExpires = $user->token_expires; $this->Behavior->expects($this->once()) - ->method('sendResetPasswordEmail') - ->with($this->user); + ->method('sendResetPasswordEmail'); $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, 'checkActive' => true, 'sendEmail' => true ]); $this->assertNotEquals($token, $result->token); + $this->assertNotEquals($tokenExpires, $result->token_expires); $this->assertEmpty($result->activation_date); $this->assertFalse($result->active); } @@ -143,16 +130,12 @@ public function testResetTokenNotExistingUser() public function testResetTokenUserAlreadyActive() { $activeUser = TableRegistry::get('Users.Users')->findAllByUsername('user-4')->first(); - $this->Behavior->expects($this->once()) - ->method('_getUser') - ->with('user-4') - ->will($this->returnValue($activeUser)); + $this->assertTrue($activeUser->active); + $this->table = $this->getMockForModel('Users.Users', ['save']); $this->table->expects($this->never()) - ->method('save') - ->will($this->returnValue($this->user)); + ->method('save'); $this->Behavior->expects($this->never()) - ->method('sendResetPasswordEmail') - ->with($this->user); + ->method('sendResetPasswordEmail'); $this->Behavior->resetToken('user-4', [ 'expiration' => 3600, 'checkActive' => true, diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index e6ecafddf..734c49209 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -120,6 +120,7 @@ public function testValidateEmailActiveAccount() */ public function testAfterSaveSocialNotActiveUserNotActive() { + $this->markTestIncomplete('move to SocialAccountBehaviorTest'); $event = new Event('eventName'); $entity = $this->SocialAccounts->find()->first(); $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); @@ -154,6 +155,7 @@ public function testAfterSaveSocialNotActiveUserActive() */ public function testAfterSaveSocialActiveUserNotActive() { + $this->markTestIncomplete('move to SocialAccountBehaviorTest'); $event = new Event('eventName'); $entity = $this->SocialAccounts->findById(2)->first(); $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); @@ -167,6 +169,7 @@ public function testAfterSaveSocialActiveUserNotActive() */ public function testAfterSaveSocialActiveUserActive() { + $this->markTestIncomplete('move to SocialAccountBehaviorTest'); $event = new Event('eventName'); $entity = $this->SocialAccounts->findById(3)->first(); $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); @@ -179,6 +182,7 @@ public function testAfterSaveSocialActiveUserActive() */ public function testSendSocialValidationEmail() { + $this->markTestIncomplete('move to SocialAccountBehaviorTest'); $user = $this->SocialAccounts->find()->contain('Users')->first(); $this->Email->emailFormat('both'); $result = $this->SocialAccounts->sendSocialValidationEmail($user, $user->user, $this->Email); From b07eabc1c341b20819aabc3df26e7a8c417a4fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 17 Aug 2015 11:28:38 +0100 Subject: [PATCH 0181/1476] refs #refactor-behavior fix unit tests --- src/Model/Behavior/PasswordBehavior.php | 2 +- .../Traits/PasswordManagementTraitTest.php | 131 +++++++++++++++++- 2 files changed, 125 insertions(+), 8 deletions(-) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index f1f487a08..6249871fc 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -117,7 +117,7 @@ public function changePassword(EntityInterface $user) } $user = $this->_table->save($user); if (!empty($user)) { - $user = $this->removeValidationToken($user); + $user = $this->_removeValidationToken($user); } return $user; } diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 249265fa6..2e99637bf 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -11,28 +11,145 @@ namespace Users\Test\TestCase\Controller\Traits; +use Cake\Auth\PasswordHasherFactory; +use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; class PasswordManagementTraitTest extends TestCase { + /** + * Fixtures + * + * @var array + */ + public $fixtures = [ + 'plugin.users.users', + ]; + public function setUp() { parent::setUp(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - ['header', 'redirect', 'render', '_stop'] - ); - $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\PasswordManagementTrait'); + $this->table = TableRegistry::get('Users.Users'); + $this->Trait = $this->getMockBuilder('Users\Controller\Traits\PasswordManagementTrait') + ->setMethods(['set', 'getUsersTable', 'redirect']) + ->getMockForTrait(); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); } public function tearDown() { + unset($this->table, $this->Trait); parent::tearDown(); } - public function testChangePassword() + protected function _mockRequestGet() { - $this->markTestIncomplete(); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + } + + protected function _mockFlash() + { + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error', 'success']) + ->disableOriginalConstructor() + ->getMock(); + } + + protected function _mockRequestPost() + { + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'data']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + } + + protected function _mockAuthLoggedIn() + { + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $user = [ + 'id' => 1, + '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(1)); + } + + protected function _mockAuth() + { + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + } + + public function testChangePasswordHappy() + { + $this->assertEquals('12345', $this->table->get(1)->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'new', + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['admin' => false, 'plugin' => 'Users', 'controller' => 'users', 'action' => 'profile']); + $this->Trait->Flash->expects($this->any()) + ->method('success') + ->with('Password has been changed successfully'); + $this->Trait->changePassword(); + $hasher = PasswordHasherFactory::build('Default'); + $this->assertTrue($hasher->check('new', $this->table->get(1)->password)); + } + + public function testChangePasswordGetLoggedIn() + { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) { + if ($param1 === 'validatePassword') { + TestCase::assertEquals($param2, true); + } + })); + $this->Trait->changePassword(); + } + + public function testChangePasswordGetNotLoggedIn() + { + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) { + if ($param1 === 'validatePassword') { + TestCase::assertEquals($param2, false); + } + })); + $this->Trait->changePassword(); } public function testResetPassword() From ba4a5811aebe6bed9e99b376d3b3cd3494fd52ad Mon Sep 17 00:00:00 2001 From: Antonis Flangofas Date: Mon, 17 Aug 2015 16:32:12 +0300 Subject: [PATCH 0182/1476] Corrected documentation --- Docs/Documentation/Extending-the-Plugin.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index fc2610c4c..8801dec7f 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -23,6 +23,7 @@ use Users\Model\Table\UsersTable; class MyUsersTable extends UsersTable { } +``` * Create a new Entity under src/Model/Entity/MyUser.php From c1e4235496495a63d3c9a0915c1901b07e43b135 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 17 Aug 2015 09:44:09 -0500 Subject: [PATCH 0183/1476] Update Extending-the-Plugin.md Fixing docs --- 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 8801dec7f..45cff9fdf 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -137,7 +137,7 @@ trait ImpersonateTrait return $this->redirect('/'); } } - +``` Updating the Templates ------------------- From ba6cf5c5d90cfae7d298a4eb52d2aa9b02bd5063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 17 Aug 2015 18:50:26 +0100 Subject: [PATCH 0184/1476] refs #refactor-behavior fix tests --- .../Traits/PasswordManagementTrait.php | 46 ++++---- .../Traits/PasswordManagementTraitTest.php | 100 +++++++++++++++++- 2 files changed, 120 insertions(+), 26 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index e670b42bf..e24ae49c8 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -85,29 +85,31 @@ public function resetPassword($token = null) */ public function requestResetPassword() { - if ($this->request->is('post')) { - $reference = $this->request->data('reference'); - try { - $resetUser = $this->getUsersTable()->resetToken($reference, [ - 'expiration' => Configure::read('Users.Token.expiration'), - 'checkActive' => false, - 'sendEmail' => true, - ]); - if ($resetUser) { - $msg = __d('Users', 'Please check your email to continue with password reset process'); - $this->Flash->success($msg); - } else { - $msg = __d('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('Users', 'User {0} was not found', $reference)); - } catch (Exception $exception) { - $this->Flash->error(__d('Users', 'Token could not be reset')); - } - } $this->set('user', $this->getUsersTable()->newEntity()); $this->set('_serialize', ['user']); + if (!$this->request->is('post')) { + return; + } + + $reference = $this->request->data('reference'); + try { + $resetUser = $this->getUsersTable()->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => false, + 'sendEmail' => true, + ]); + if ($resetUser) { + $msg = __d('Users', 'Please check your email to continue with password reset process'); + $this->Flash->success($msg); + } else { + $msg = __d('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('Users', 'User {0} was not found', $reference)); + } catch (Exception $exception) { + $this->Flash->error(__d('Users', 'Token could not be reset')); + } } } diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 2e99637bf..42f46788e 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -26,24 +26,39 @@ class PasswordManagementTraitTest extends TestCase 'plugin.users.users', ]; + /** + * setUp + * + * @return void + */ public function setUp() { parent::setUp(); $this->table = TableRegistry::get('Users.Users'); $this->Trait = $this->getMockBuilder('Users\Controller\Traits\PasswordManagementTrait') - ->setMethods(['set', 'getUsersTable', 'redirect']) + ->setMethods(['set', 'getUsersTable', 'redirect', 'validate']) ->getMockForTrait(); $this->Trait->expects($this->any()) ->method('getUsersTable') ->will($this->returnValue($this->table)); } + /** + * tearDown + * + * @return void + */ public function tearDown() { unset($this->table, $this->Trait); parent::tearDown(); } + /** + * mock request for GET + * + * @return void + */ protected function _mockRequestGet() { $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') @@ -55,6 +70,11 @@ protected function _mockRequestGet() ->will($this->returnValue(false)); } + /** + * mock Flash Component + * + * @return void + */ protected function _mockFlash() { $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') @@ -63,6 +83,11 @@ protected function _mockFlash() ->getMock(); } + /** + * mock Request for POST + * + * @return void + */ protected function _mockRequestPost() { $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') @@ -74,6 +99,11 @@ protected function _mockRequestPost() ->will($this->returnValue(true)); } + /** + * Mock Auth and retur user id 1 + * + * @return void + */ protected function _mockAuthLoggedIn() { $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') @@ -93,6 +123,11 @@ protected function _mockAuthLoggedIn() ->will($this->returnValue(1)); } + /** + * Mock the Auth component + * + * @return void + */ protected function _mockAuth() { $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') @@ -101,6 +136,11 @@ protected function _mockAuth() ->getMock(); } + /** + * test + * + * @return void + */ public function testChangePasswordHappy() { $this->assertEquals('12345', $this->table->get(1)->password); @@ -124,6 +164,11 @@ public function testChangePasswordHappy() $this->assertTrue($hasher->check('new', $this->table->get(1)->password)); } + /** + * test + * + * @return void + */ public function testChangePasswordGetLoggedIn() { $this->_mockRequestGet(); @@ -138,6 +183,11 @@ public function testChangePasswordGetLoggedIn() $this->Trait->changePassword(); } + /** + * test + * + * @return void + */ public function testChangePasswordGetNotLoggedIn() { $this->_mockRequestGet(); @@ -152,13 +202,55 @@ public function testChangePasswordGetNotLoggedIn() $this->Trait->changePassword(); } + /** + * test + * + * @return void + */ public function testResetPassword() { - $this->markTestIncomplete(); + $token = 'token'; + $this->Trait->expects($this->once()) + ->method('validate') + ->with('password', $token); + $this->Trait->resetPassword($token); + } + + /** + * test + * + * @return void + */ + public function testRequestResetPasswordGet() + { + $this->assertEquals('xxx', $this->table->get(1)->token); + $this->_mockRequestGet(); + $this->_mockFlash(); + $this->Trait->request->expects($this->never()) + ->method('data'); + $this->Trait->requestResetPassword(); } - public function testRequestResetPassword() + /** + * test + * + * @return void + */ + public function testRequestPasswordHappy() { - $this->markTestIncomplete(); + $this->assertEquals('xxx', $this->table->get(1)->token); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $reference = 'user-1'; + $this->Trait->request->expects($this->once()) + ->method('data') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($this->any()) + ->method('success') + ->with('Password has been changed successfully'); + $this->Trait->requestResetPassword(); + $this->assertNotEquals('xxx', $this->table->get(1)->token); } } From 77dad85ebd8789bb343694516cc885a3691d3693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 17 Aug 2015 19:43:08 +0100 Subject: [PATCH 0185/1476] refs #refactor-behavior add base test case for traits, add tests for profile --- src/Controller/Traits/ProfileTrait.php | 9 +- src/Test/BaseTraitTest.php | 99 ++++++++++++++++ .../Traits/PasswordManagementTraitTest.php | 85 +------------- .../Controller/Traits/ProfileTraitTest.php | 109 ++++++++++++++++-- 4 files changed, 207 insertions(+), 95 deletions(-) create mode 100644 src/Test/BaseTraitTest.php diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index be2e4146b..38d34d3d0 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -13,6 +13,7 @@ use Cake\Core\Configure; use Cake\Datasource\Exception\InvalidPrimaryKeyException; +use Cake\Datasource\Exception\RecordNotFoundException; /** * Covers the login, logout and social login, proxy to UsersAuthComponent methods @@ -41,9 +42,11 @@ public function profile($id = null) if ($user->id === $loggedUserId) { $isCurrentUser = true; } - - } catch (InvalidPrimaryKeyException $ipke) { - $this->Flash->error(__d('Users', 'User was not found', $id)); + } catch (RecordNotFoundException $ex) { + $this->Flash->error(__d('Users', 'User was not found')); + return $this->redirect($this->request->referer()); + } catch (InvalidPrimaryKeyException $ex) { + $this->Flash->error(__d('Users', 'Not authorized, please login first')); return $this->redirect($this->request->referer()); } $this->set(compact('user', 'isCurrentUser')); diff --git a/src/Test/BaseTraitTest.php b/src/Test/BaseTraitTest.php new file mode 100644 index 000000000..116353ceb --- /dev/null +++ b/src/Test/BaseTraitTest.php @@ -0,0 +1,99 @@ +Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'referer']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + } + + /** + * mock Flash Component + * + * @return void + */ + protected function _mockFlash() + { + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error', 'success']) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * mock Request for POST + * + * @return void + */ + protected function _mockRequestPost() + { + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'data']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + } + + /** + * Mock Auth and retur user id 1 + * + * @return void + */ + protected function _mockAuthLoggedIn() + { + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $user = [ + 'id' => 1, + '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(1)); + } + + /** + * 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(); + } +} diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 42f46788e..5ad1e9113 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -14,8 +14,9 @@ use Cake\Auth\PasswordHasherFactory; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; +use Users\Test\BaseTraitTest; -class PasswordManagementTraitTest extends TestCase +class PasswordManagementTraitTest extends BaseTraitTest { /** * Fixtures @@ -54,88 +55,6 @@ public function tearDown() parent::tearDown(); } - /** - * mock request for GET - * - * @return void - */ - protected function _mockRequestGet() - { - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); - $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - } - - /** - * mock Flash Component - * - * @return void - */ - protected function _mockFlash() - { - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error', 'success']) - ->disableOriginalConstructor() - ->getMock(); - } - - /** - * mock Request for POST - * - * @return void - */ - protected function _mockRequestPost() - { - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'data']) - ->getMock(); - $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - } - - /** - * Mock Auth and retur user id 1 - * - * @return void - */ - protected function _mockAuthLoggedIn() - { - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => 1, - '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(1)); - } - - /** - * 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(); - } - /** * test * diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index 0df9ee644..ad8f84fb8 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -11,27 +11,118 @@ namespace Users\Test\TestCase\Controller\Traits; -use Cake\TestSuite\TestCase; +use Cake\ORM\TableRegistry; +use Users\Test\BaseTraitTest; -class ProfileTraitTest extends TestCase +class ProfileTraitTest extends BaseTraitTest { + /** + * Fixtures + * + * @var array + */ + public $fixtures = [ + 'plugin.users.users', + 'plugin.users.social_accounts', + ]; + + /** + * setUp + * + * @return void + */ public function setUp() { parent::setUp(); - $this->controller = $this->getMock( - '\Cake\Controller\Controller', - ['header', 'redirect', 'render', '_stop'] - ); - $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\ProfileTrait'); + $this->table = TableRegistry::get('Users.Users'); + $this->Trait = $this->getMockBuilder('Users\Controller\Traits\ProfileTrait') + ->setMethods(['set', 'getUsersTable', 'redirect', 'validate']) + ->getMockForTrait(); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); } + /** + * tearDown + * + * @return void + */ public function tearDown() { + unset($this->table, $this->Trait); parent::tearDown(); } - public function testProfile() + /** + * test + * + * @return void + */ + public function testProfileGetNotLoggedInUserNotFound() + { + $userId = 'not-found'; + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User was not found'); + $this->Trait->profile($userId); + } + + /** + * test + * + * @return void + */ + public function testProfileGetLoggedInUserNotFound() + { + $userId = 'not-found'; + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User was not found'); + $this->Trait->profile($userId); + } + + /** + * test + * + * @return void + */ + public function testProfileGetNotLoggedInEmptyId() + { + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Not authorized, please login first'); + $this->Trait->profile(); + } + + /** + * test + * + * @return void + */ + public function testProfileGetLoggedInMyProfile() { - $this->markTestIncomplete(); + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) { + if ($param1 === 'avatarPlaceholder') { + BaseTraitTest::assertEquals('Users.avatar_placeholder.png', $param2); + } elseif (is_array($param1)) { + BaseTraitTest::assertEquals('user-1', $param1['user']->username); + } + })); + $this->Trait->profile(); } } From eca09ca0b2e60dbf38f62ea297c34b4738549032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 18 Aug 2015 20:09:29 +0100 Subject: [PATCH 0186/1476] refs #refactor-behavior fix generate to public --- 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 762c67841..d506c38df 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -147,7 +147,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail } } - $userData['username'] = $this->_generateUsername(Hash::get($userData, 'username')); + $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); if ($useEmail) { $userData['email'] = $data->email; if (!$data->validated) { @@ -180,7 +180,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail * @param string $username username data. * @return string */ - protected function _generateUsername($username) + public function generateUniqueUsername($username) { $i = 0; while (true) { From 50de90c3f69016ee7176a3b237ed2e8ac95f1cd8 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 18 Aug 2015 19:54:26 -0500 Subject: [PATCH 0187/1476] Implement new features for shell --- config/users.php | 2 + src/Model/Entity/User.php | 37 ++++++++- src/Shell/UsersShell.php | 162 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 192 insertions(+), 9 deletions(-) diff --git a/config/users.php b/config/users.php index 6958ea67d..1cfccc4cb 100644 --- a/config/users.php +++ b/config/users.php @@ -17,6 +17,8 @@ 'table' => 'Users.Users', //configure Auth component 'auth' => true, + //Password Hasher + 'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher', //token expiration, 1 hour 'Token' => ['expiration' => 3600], 'Email' => [ diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 4d8b7d7e9..e84275344 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -12,6 +12,7 @@ namespace Users\Model\Entity; use Cake\Auth\DefaultPasswordHasher; +use Cake\Core\Configure; use Cake\ORM\Entity; use Cake\Utility\Text; use DateTime; @@ -52,7 +53,7 @@ class User extends Entity */ protected function _setPassword($password) { - return (new DefaultPasswordHasher)->hash($password); + return $this->hashPassword($password); } /** @@ -61,18 +62,47 @@ protected function _setPassword($password) */ protected function _setConfirmPassword($password) { - return (new DefaultPasswordHasher)->hash($password); + return $this->hashPassword($password); + } + + /** + * Hash a password using the configured password hasher, + * use DefaultPasswordHasher if no one was configured + * + * @param $password + * @return mixed + */ + public function hashPassword($password) + { + $PasswordHasher = $this->getPasswordHasher(); + return $PasswordHasher->hash($password); + } + + /** + * Return the configured Password Hasher + * + * @return mixed + */ + public function getPasswordHasher() + { + $passwordHasher = Configure::read('Users.passwordHasher'); + if (!class_exists($passwordHasher)) { + $passwordHasher = '\Cake\Auth\DefaultPasswordHasher'; + } + return new $passwordHasher; } /** * Checks if a password is correctly hashed + * * @param string $password password that will be check. * @param string $hashedPassword hash used to check password. * @return bool */ public function checkPassword($password, $hashedPassword) { - return (new DefaultPasswordHasher)->check($password, $hashedPassword); + $PasswordHasher = $this->_getPasswordHasher(); + return $PasswordHasher->check($password, $hashedPassword); } /** @@ -87,6 +117,7 @@ public function tokenExpired() /** * Getter for user avatar + * * @return string|null avatar */ protected function _getAvatar() diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 4fbd6456e..792c07d0b 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -11,10 +11,15 @@ namespace Users\Shell; +use Cake\Auth\DefaultPasswordHasher; use Cake\Console\Shell; +use Cake\Utility\Hash; +use Users\Model\Entity\User; /** * Shell with utilities for the Users Plugin + * + * @property \Users\Model\Table\Users Users */ class UsersShell extends Shell { @@ -37,7 +42,12 @@ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description(__d('Users', 'Utilities for CakeDC Users Plugin')) - ->addSubcommand('addSuperuser')->description(__d('Users', 'Add a new superadmin user for testing purposes')); + ->addSubcommand('addSuperuser')->description(__d('Users', 'Add a new superadmin user for testing purposes')) + ->addSubcommand('changeRole')->description(__d('Users', 'Change the role for an specific user')) + ->addSubcommand('resetAllPasswords')->description(__d('Users', 'Reset the password for all users')) + ->addSubcommand('resetPassword')->description(__d('Users', 'Reset the password for an specific user')) + ->addSubcommand('activateUser')->description(__d('Users', 'Activate an specific user')) + ->addSubcommand('deactivateUser')->description(__d('Users', 'Deactivate an specific user')); return $parser; } @@ -68,13 +78,153 @@ public function addSuperuser() $this->out(__d('Users', 'Password: {0}', $password)); } - //resetAllPasswords to XXX - //resetPassword user to XXX //addUser - //changeRole user to XXX + + /** + * Reset password for all user + * + * Arguments: + * + * - Password to be set + * + * @return void + */ + public function resetAllPasswords() + { + $password = Hash::get($this->args, 0); + if (empty($password)) { + $this->error(__d('Users', 'Please enter a password.')); + } + $hashedPassword = (new User)->hashPassword($password); + $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); + $this->out(__d('Users', 'Password changed for all users')); + $this->out(__d('Users', 'New password: {0}', $password)); + } + + /** + * Reset password for a user + * + * Arguments: + * + * - Username + * - Password to be set + * + * @return void + */ + public function resetPassword() + { + $username = Hash::get($this->args, 0); + $password = Hash::get($this->args, 1); + if (empty($username)) { + $this->error(__d('Users', 'Please enter a username.')); + } + if (empty($password)) { + $this->error(__d('Users', 'Please enter a password.')); + } + $data = [ + 'password' => $password + ]; + $this->_updateUser($username, $data); + $this->out(__d('Users', 'Password changed for user: {0}', $username)); + $this->out(__d('Users', 'New password: {0}', $password)); + } + + /** + * Change role for a user + * + * Arguments: + * + * - Username + * - Role to be set + * + * @return void + */ + public function changeRole() + { + $username = Hash::get($this->args, 0); + $role = Hash::get($this->args, 1); + if (empty($username)) { + $this->error(__d('Users', 'Please enter a username.')); + } + if (empty($role)) { + $this->error(__d('Users', 'Please enter a role.')); + } + $data = [ + 'role' => $role + ]; + $savedUser = $this->_updateUser($username, $data); + $this->out(__d('Users', 'Role changed for user: {0}', $username)); + $this->out(__d('Users', 'New role: {0}', $savedUser->role)); + } + + /** + * Activate an specific user + * + * Arguments: + * + * - Username + * + * @return void + */ + public function activateUser() + { + $user = $this->_changeUserActive(true); + $this->out(__d('Users', 'User was activated: {0}', $user->username)); + + } + + /** + * De-activate an specific user + * + * Arguments: + * + * - Username + * + * @return void + */ + public function deactivateUser() + { + $user = $this->_changeUserActive(false); + $this->out(__d('Users', 'User was de-activated: {0}', $user->username)); + } + + /** + * Change user active field + * + * @param $active + */ + protected function _changeUserActive($active) + { + $username = Hash::get($this->args, 0); + if (empty($username)) { + $this->error(__d('Users', 'Please enter a username.')); + } + $data = [ + 'active' => $active + ]; + return $this->_updateUser($username, $data); + } + + /** + * Update user by username + * + * @param $username + * @param $data + */ + protected function _updateUser($username, $data) + { + /** @var \Users\Model\Entity\User */ + $user = $this->Users->find()->where(['Users.username' => $username])->first(); + if (empty($user)) { + $this->error(__d('Users', 'The user was not found.')); + } + $user = $this->Users->patchEntity($user, $data); + $savedUser = $this->Users->save($user); + return $savedUser; + } + + //deleteUser user - //deactivateUser user - //activateUser user //add filters LIKE in username and email to some tasks // --force to ignore "you are about to do X to Y users" } From 175deb44486927fcfc322461c28d7bd9411feae0 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Wed, 19 Aug 2015 07:05:25 -0500 Subject: [PATCH 0188/1476] Fix change role issue on accessible --- src/Shell/UsersShell.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 792c07d0b..6732a0c52 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -219,6 +219,11 @@ protected function _updateUser($username, $data) $this->error(__d('Users', 'The user was not found.')); } $user = $this->Users->patchEntity($user, $data); + collection($data)->filter(function ($value, $field) use ($user) { + return !$user->accessible($field); + })->each(function ($value, $field) use (&$user) { + $user->{$field} = $value; + }); $savedUser = $this->Users->save($user); return $savedUser; } From 59846ea660c2fe2b9a4bb3dac0f5c4dd6d80c049 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 19 Aug 2015 22:22:44 -0430 Subject: [PATCH 0189/1476] Moving tests from UsersTable to RegisterBehavior and Adding some news in RegisterBehavior --- tests/Fixture/UsersFixture.php | 132 +---------- .../Model/Behavior/RegisterBehaviorTest.php | 219 ++++++++++++++++++ tests/TestCase/Model/Table/UsersTableTest.php | 78 ------- 3 files changed, 222 insertions(+), 207 deletions(-) create mode 100644 tests/TestCase/Model/Behavior/RegisterBehaviorTest.php diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 145afbc4f..2742878d6 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -66,7 +66,7 @@ class UsersFixture extends TestFixture 'password' => '12345', 'first_name' => 'first1', 'last_name' => 'last1', - 'token' => 'xxx', + 'token' => 'ae93ddbe32664ce7927cf0c5c5a5e59d', 'token_expires' => '2035-06-24 17:33:54', 'api_token' => 'yyy', 'activation_date' => '2015-06-24 17:33:54', @@ -84,7 +84,7 @@ class UsersFixture extends TestFixture 'password' => '12345', 'first_name' => 'user', 'last_name' => 'second', - 'token' => 'xxx', + 'token' => '6614f65816754310a5f0553436dd89e9', 'token_expires' => '2015-06-24 17:33:54', 'api_token' => 'xxx', 'activation_date' => '2015-06-24 17:33:54', @@ -102,7 +102,7 @@ class UsersFixture extends TestFixture 'password' => '12345', 'first_name' => 'user', 'last_name' => 'third', - 'token' => 'xxx', + 'token' => '926029fede5b4a28bce4ad5853c43a25', 'token_expires' => '2015-06-20 17:33:54', 'api_token' => 'xxx', 'activation_date' => '2015-06-24 17:33:54', @@ -113,131 +113,5 @@ class UsersFixture extends TestFixture 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54' ], - [ - 'id' => 4, - 'username' => 'user-4', - 'email' => '4@example.com', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'FirstName4', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 4, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => 5, - 'username' => 'user-5', - 'email' => 'test@example.com', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'first-user-5', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'tos_date' => '2015-06-24 17:33:54', - 'active' => 0, - 'is_superuser' => 0, - 'role' => 'user', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => 6, - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 6, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => 7, - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 7, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => 8, - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 8, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => 9, - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 9, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => 10, - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 10, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], ]; } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php new file mode 100644 index 000000000..8069f92e3 --- /dev/null +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -0,0 +1,219 @@ +addBehavior('Users/Register.Register'); + $this->Table = $table; + $this->Behavior = $table->behaviors()->Register; + + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->table, $this->Behavior); + parent::tearDown(); + } + + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterNoValidateEmail() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); + $this->assertTrue($result->active); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterEmptyUser() + { + $user = []; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertFalse($result); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterValidateEmail() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertNotEmpty($result); + $this->assertFalse($result->active); + } + + /** + * Test register method + * + * @expectedException InvalidArgumentException + */ + public function testValidateRegisterTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterNoTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); + $this->assertNotEmpty($result); + } + + /** + * Test ActivateUser method + * + * @return void + */ + public function testActivateUser() + { + $user = $this->Table->find()->where(['id' => 1])->first(); + $result = $this->Table->activateUser($user); + $this->assertTrue($result->active); + } + + /** + * Test Validate method + * + * @return void + */ + public function testValidate() + { + $result = $this->Table->validate('ae93ddbe32664ce7927cf0c5c5a5e59d', 'activateUser'); + $this->assertTrue($result->active); + $this->assertEmpty($result->token_expires); + } + + /** + * Test Validate method + * + * @return void + * @expectedException \Users\Exception\TokenExpiredException + */ + public function testValidateUserWithExpiredToken() + { + $this->Table->validate('926029fede5b4a28bce4ad5853c43a25', 'activateUser'); + } + + /** + * Test Validate method + * + * @return void + * @expectedException \Users\Exception\UserNotFoundException + */ + public function testValidateNotExistingUser() + { + $this->Table->validate('not-existing-token', 'activateUser'); + } + + /** + * Test activateUser method + * + * @return void + */ + public function testActiveUserRemoveValidationToken() + { + $user = $this->Table->find()->where(['id' => 1])->first(); + $this->Behavior = $this->getMockBuilder('Users\Model\Behavior\RegisterBehavior') + ->setMethods(['_removeValidationToken']) + ->setConstructorArgs([$this->Table]) + ->getMock(); + + $resultValidationToken = $user; + $resultValidationToken->token_expires = null; + $resultValidationToken->token = null; + + $this->Behavior->expects($this->once()) + ->method('_removeValidationToken') + ->will($this->returnValue($resultValidationToken)); + + $this->Behavior->activateUser($user); + } + +} diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 54dcc223e..2a45847f4 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -89,84 +89,6 @@ public function testValidateRegisterNoValidateEmail() $this->assertTrue($result->active); } - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterEmptyUser() - { - $user = []; - $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); - $this->assertFalse($result); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterValidateEmail() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); - $this->assertNotEmpty($result); - $this->assertFalse($result->active); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testValidateRegisterTosRequired() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ]; - $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); - } - - /** - * Test register method - testValidateRegisterValidateEmail */ - public function testValidateRegisterNoTosRequired() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ]; - $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); - $this->assertNotEmpty($result); - } - - /** - * Test ActivateUser method - * - * @return void - */ - public function testActivateUser() - { - $user = $this->Users->find()->where(['id' => 1])->first(); - $result = $this->Users->activateUser($user); - $this->assertTrue($result->active); - } - public function testSocialLogin() { $raw = [ From 9f17a946e81c8acdb1681b0b4c1e31f69f63c610 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 19 Aug 2015 23:07:04 -0430 Subject: [PATCH 0190/1476] Adding unit tests to SocialAccountBehavior --- .../Behavior/SocialAccountBehaviorTest.php | 142 ++++++++++++++++++ .../Model/Table/SocialAccountsTableTest.php | 89 +---------- 2 files changed, 144 insertions(+), 87 deletions(-) create mode 100644 tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php new file mode 100644 index 000000000..e321a57de --- /dev/null +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -0,0 +1,142 @@ +addBehavior('Users.SocialAccount'); + $this->Table = $table; + $this->Behavior = $table->behaviors()->SocialAccount; + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->table, $this->Behavior); + parent::tearDown(); + } + + /** + * Test validateEmail method + * + * @return void + */ + public function testValidateEmail() + { + $token = 'token-1234'; + $result = $this->Behavior->validateAccount(SocialAccountsTable::PROVIDER_FACEBOOK, 'reference-1-1234', $token); + $this->assertTrue($result->active); + $this->assertEquals($token, $result->token); + } + + /** + * Test validateEmail method + * + * @expectedException \Cake\Datasource\Exception\RecordNotFoundException + */ + public function testValidateEmailInvalidToken() + { + $this->Behavior->validateAccount(1, 'reference-1234', 'invalid-token'); + } + + /** + * Test validateEmail method + * + * @expectedException \Cake\Datasource\Exception\RecordNotFoundException + */ + public function testValidateEmailInvalidUser() + { + $this->Behavior->validateAccount(1, 'invalid-user', 'token-1234'); + } + + /** + * Test validateEmail method + * + * @expectedException \Users\Exception\AccountAlreadyActiveException + */ + public function testValidateEmailActiveAccount() + { + $this->Behavior->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); + } + + /** + * testAfterSaveSocialNotActiveUserNotActive + * don't send email, user is not active + * + * @return void + */ + public function testAfterSaveSocialNotActiveUserNotActive() + { + $event = new Event('eventName'); + $entity = $this->Table->find()->first(); + $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); + } + + /** + * testAfterSaveSocialActiveUserActive + * social account is active, don't send email + * + * @return void + */ + public function testAfterSaveSocialActiveUserActive() + { + $event = new Event('eventName'); + $entity = $this->Table->findById(3)->first(); + $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); + } + + /** + * testAfterSaveSocialActiveUserNotActive + * social account is active, don't send email + * + * @return void + */ + public function testAfterSaveSocialActiveUserNotActive() + { + $event = new Event('eventName'); + $entity = $this->Table->findById(2)->first(); + $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); + } +} diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index 734c49209..e4be6b2df 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -69,63 +69,6 @@ public function tearDown() parent::tearDown(); } - /** - * Test validateEmail method - * - * @return void - */ - public function testValidateEmail() - { - $token = 'token-1234'; - $result = $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_FACEBOOK, 'reference-1-1234', $token); - $this->assertTrue($result->active); - $this->assertEquals($token, $result->token); - } - - /** - * Test validateEmail method - * - * @expectedException \Cake\Datasource\Exception\RecordNotFoundException - */ - public function testValidateEmailInvalidToken() - { - $this->SocialAccounts->validateAccount(1, 'reference-1234', 'invalid-token'); - } - - /** - * Test validateEmail method - * - * @expectedException \Cake\Datasource\Exception\RecordNotFoundException - */ - public function testValidateEmailInvalidUser() - { - $this->SocialAccounts->validateAccount(1, 'invalid-user', 'token-1234'); - } - - /** - * Test validateEmail method - * - * @expectedException \Users\Exception\AccountAlreadyActiveException - */ - public function testValidateEmailActiveAccount() - { - $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); - } - - /** - * testAfterSaveSocialNotActiveUserNotActive - * don't send email, user is not active - * - * @return void - */ - public function testAfterSaveSocialNotActiveUserNotActive() - { - $this->markTestIncomplete('move to SocialAccountBehaviorTest'); - $event = new Event('eventName'); - $entity = $this->SocialAccounts->find()->first(); - $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); - } - /** * testAfterSaveSocialNotActiveUserActive * send email here, social account is not active, @@ -140,41 +83,13 @@ public function testAfterSaveSocialNotActiveUserActive() $entity = $this->SocialAccounts->findById(5)->first(); $this->SocialAccounts->Users = $this->getMockForModel('Users.Users', ['getEmailInstance']); $this->SocialAccounts->Users->expects($this->once()) - ->method('getEmailInstance') - ->will($this->returnValue($this->Email)); + ->method('getEmailInstance') + ->will($this->returnValue($this->Email)); $result = $this->SocialAccounts->afterSave($event, $entity, []); $this->assertTextContains('Subject: FirstName4, Your social account validation link', $result['headers']); unset($this->SocialAccounts->Users); } - /** - * testAfterSaveSocialActiveUserNotActive - * social account is active, don't send email - * - * @return void - */ - public function testAfterSaveSocialActiveUserNotActive() - { - $this->markTestIncomplete('move to SocialAccountBehaviorTest'); - $event = new Event('eventName'); - $entity = $this->SocialAccounts->findById(2)->first(); - $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); - } - - /** - * testAfterSaveSocialActiveUserActive - * social account is active, don't send email - * - * @return void - */ - public function testAfterSaveSocialActiveUserActive() - { - $this->markTestIncomplete('move to SocialAccountBehaviorTest'); - $event = new Event('eventName'); - $entity = $this->SocialAccounts->findById(3)->first(); - $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); - } - /** * Test sendSocialValidationEmail method * From 76a6bd5160fc5fbb77302f9934718a1edb7ad2f7 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 19 Aug 2015 23:07:37 -0430 Subject: [PATCH 0191/1476] Fixing namespace --- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 095fcfc09..c03fc4a35 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Model\Table\Traits; +namespace Users\Test\TestCase\Model\Behavior; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; From 3277d7f1ecdcc475fa75f45e5c401e4f706caa35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 20 Aug 2015 12:35:02 +0100 Subject: [PATCH 0192/1476] refs #refactor-behavior fix method name after change to public --- src/Model/Entity/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index e84275344..6802f02cb 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -101,7 +101,7 @@ public function getPasswordHasher() */ public function checkPassword($password, $hashedPassword) { - $PasswordHasher = $this->_getPasswordHasher(); + $PasswordHasher = $this->getPasswordHasher(); return $PasswordHasher->check($password, $hashedPassword); } From 998ae35d39bb6627bd9e5a94c8b2a1bcb82bd4c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 20 Aug 2015 12:57:47 +0100 Subject: [PATCH 0193/1476] refs #refactor-behavior fix tests, improving the BaseTraitTest class --- src/Controller/Traits/ProfileTrait.php | 2 +- src/Test/BaseTraitTest.php | 61 ++++++++++++++++++ .../Traits/PasswordManagementTraitTest.php | 10 +-- .../Controller/Traits/ProfileTraitTest.php | 21 +------ .../Controller/Traits/RegisterTraitTest.php | 62 ++++++++++++++----- 5 files changed, 113 insertions(+), 43 deletions(-) diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 38d34d3d0..74a3235c2 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -16,7 +16,7 @@ use Cake\Datasource\Exception\RecordNotFoundException; /** - * Covers the login, logout and social login, proxy to UsersAuthComponent methods + * Covers the profile action * */ trait ProfileTrait diff --git a/src/Test/BaseTraitTest.php b/src/Test/BaseTraitTest.php index 116353ceb..52deaf04e 100644 --- a/src/Test/BaseTraitTest.php +++ b/src/Test/BaseTraitTest.php @@ -11,10 +11,55 @@ namespace Users\Test; +use Cake\Event\Event; +use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; +use PHPUnit_Framework_MockObject_RuntimeException; abstract class BaseTraitTest extends TestCase { + /** + * Classname of the trait we are about to test + * + * @var string + */ + public $traitClassName = ''; + public $traitMockMethods = []; + + /** + * SetUp and create Trait + * + * @return void + */ + public function setUp() + { + parent::setUp(); + $traitMockMethods = array_unique(array_merge(['getUsersTable'], $this->traitMockMethods)); + $this->table = TableRegistry::get('Users.Users'); + try { + $this->Trait = $this->getMockBuilder($this->traitClassName) + ->setMethods($traitMockMethods) + ->getMockForTrait(); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); + } catch (PHPUnit_Framework_MockObject_RuntimeException $ex) { + debug($ex); + $this->fail("Unit tests extending BaseTraitTest should declare the trait class name in the \$traitClassName variable before calling setUp()"); + } + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->table, $this->Trait); + parent::tearDown(); + } + /** * mock request for GET * @@ -96,4 +141,20 @@ protected function _mockAuth() ->disableOriginalConstructor() ->getMock(); } + + /** + * mock utility + * + * @param Event $event event + * @return void + */ + protected function _mockDispatchEvent(Event $event = null) + { + if (is_null($event)) { + $event = new Event('cool-name-here'); + } + $this->Trait->expects($this->any()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + } } diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 5ad1e9113..9322373d7 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -34,14 +34,9 @@ class PasswordManagementTraitTest extends BaseTraitTest */ public function setUp() { + $this->traitClassName = 'Users\Controller\Traits\PasswordManagementTrait'; + $this->traitMockMethods = ['set', 'redirect', 'validate']; parent::setUp(); - $this->table = TableRegistry::get('Users.Users'); - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\PasswordManagementTrait') - ->setMethods(['set', 'getUsersTable', 'redirect', 'validate']) - ->getMockForTrait(); - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($this->table)); } /** @@ -51,7 +46,6 @@ public function setUp() */ public function tearDown() { - unset($this->table, $this->Trait); parent::tearDown(); } diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index ad8f84fb8..503813969 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -12,6 +12,7 @@ namespace Users\Test\TestCase\Controller\Traits; use Cake\ORM\TableRegistry; +use Users\Controller\Traits\ProfileTrait; use Users\Test\BaseTraitTest; class ProfileTraitTest extends BaseTraitTest @@ -33,25 +34,9 @@ class ProfileTraitTest extends BaseTraitTest */ public function setUp() { + $this->traitClassName = 'Users\Controller\Traits\ProfileTrait'; + $this->traitMockMethods = ['set', 'getUsersTable', 'redirect', 'validate']; parent::setUp(); - $this->table = TableRegistry::get('Users.Users'); - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\ProfileTrait') - ->setMethods(['set', 'getUsersTable', 'redirect', 'validate']) - ->getMockForTrait(); - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($this->table)); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->table, $this->Trait); - parent::tearDown(); } /** diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 00e468bd0..cde21897b 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -11,37 +11,67 @@ namespace Users\Test\TestCase\Controller\Traits; -use Cake\TestSuite\TestCase; +use Cake\ORM\TableRegistry; +use Users\Test\BaseTraitTest; -class RegisterTraitTest extends TestCase +class RegisterTraitTest extends BaseTraitTest { + /** + * Fixtures + * + * @var array + */ + public $fixtures = [ + 'plugin.users.users', + ]; + + /** + * setUp + * + * @return void + */ public function setUp() { + $this->traitClassName = 'Users\Controller\Traits\RegisterTrait'; + $this->traitMockMethods = ['validate', 'dispatchEvent', 'set']; parent::setUp(); - $this->controller = $this->getMock( - '\Cake\Controller\Controller', - ['header', 'redirect', 'render', '_stop'] - ); - $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\RegisterTrait'); } + /** + * tearDown + * + * @return void + */ public function tearDown() { parent::tearDown(); } - public function testRegisterTest() - { - $this->markTestIncomplete(); - } - - public function testValidateTest() + /** + * test + * + * @return void + */ + public function testValidateEmail() { - $this->markTestIncomplete(); + $token = 'token'; + $this->Trait->expects($this->once()) + ->method('validate') + ->with('email', $token); + $this->Trait->validateEmail($token); } - public function testResendTokenValidation() + /** + * test + * + * @return void + */ + public function testRegisterHappy() { - $this->markTestIncomplete(); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->register(); } } From eead89f693d8c9bf35357e4628300f9b124fd61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 20 Aug 2015 13:14:15 +0100 Subject: [PATCH 0194/1476] refs #refactor-behavior switch to integration test --- .../Traits/UserValidationTraitTest.php | 50 +++++++------------ 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index f929c563b..e007f61d8 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -12,33 +12,29 @@ namespace Users\Test\TestCase\Controller\Traits; use Cake\Network\Request; -use Cake\TestSuite\TestCase; +use Users\Test\BaseTraitTest; -class UserValidationTraitTest extends TestCase +class UserValidationTraitTest extends BaseTraitTest { /** - * setup + * Fixtures * - * @return void + * @var array */ - public function setUp() - { - parent::setUp(); - $request = new Request(); - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\UserValidationTrait') - ->setMethods(['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable']) - ->getMockForTrait(); - $this->Trait->request = $request; - } + public $fixtures = [ + 'plugin.users.users', + ]; /** - * tearDown + * setup * * @return void */ - public function tearDown() + public function setUp() { - parent::tearDown(); + $this->traitClassName = 'Users\Controller\Traits\UserValidationTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable']; + parent::setUp(); } /** @@ -48,24 +44,14 @@ public function tearDown() */ public function testValidateHappyToken() { - $usersTableMock = $this->getMockBuilder('Users\Model\Table\UsersTable') - ->setMethods(['validate']) - ->disableOriginalConstructor() - ->getMock(); - $usersTableMock->expects($this->once()) - ->method('validate') - ->with('token', 'activateUser') - ->will($this->returnValue(true)); - $this->Trait->expects($this->once()) - ->method('getUsersTable') - ->will($this->returnValue($usersTableMock)); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['success']) - ->disableOriginalConstructor() - ->getMock(); + $this->_mockFlash(); + $user = $this->table->findByToken('xxx')->first(); + $this->assertFalse($user->active); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('User account validated successfully'); - $this->Trait->validate('email', 'token'); + $this->Trait->validate('email', 'xxx'); + $user = $this->table->findById($user->id)->first(); + $this->assertTrue($user->active); } } From 91ca749718499aff8b8b8fdc2a2ef4505c0fff02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 20 Aug 2015 14:37:26 +0100 Subject: [PATCH 0195/1476] refs #refactor-behavior fix tests, early returns --- src/Model/Behavior/RegisterBehavior.php | 20 +++++++------- tests/Fixture/UsersFixture.php | 6 ++--- .../Traits/UserValidationTraitTest.php | 26 ++++++++++++++++--- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 4e54ba549..e6d407d87 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -79,19 +79,17 @@ public function validate($token, $callback = null) ->select(['token_expires', 'id', 'active', 'token']) ->where(['token' => $token]) ->first(); - if (!empty($user)) { - if (!$user->tokenExpired()) { - if (!empty($callback) && method_exists($this, $callback)) { - return $this->_table->{$callback}($user); - } else { - return $user; - } - } else { - throw new TokenExpiredException(__d('Users', "Token has already expired user with no token")); - } - } else { + if (empty($user)) { throw new UserNotFoundException(__d('Users', "User not found for the given token and email.")); } + if ($user->tokenExpired()) { + throw new TokenExpiredException(__d('Users', "Token has already expired user with no token")); + } + if (!method_exists($this, $callback)) { + return $user; + } + + return $this->_table->{$callback}($user); } /** diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 145afbc4f..564926e64 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -102,8 +102,8 @@ class UsersFixture extends TestFixture 'password' => '12345', 'first_name' => 'user', 'last_name' => 'third', - 'token' => 'xxx', - 'token_expires' => '2015-06-20 17:33:54', + 'token' => 'token-3', + 'token_expires' => '2030-06-20 17:33:54', 'api_token' => 'xxx', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', @@ -120,7 +120,7 @@ class UsersFixture extends TestFixture 'password' => 'Lorem ipsum dolor sit amet', 'first_name' => 'FirstName4', 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', + 'token' => 'token-4', 'token_expires' => '2015-06-24 17:33:54', 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index e007f61d8..780fdf7b8 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -42,15 +42,35 @@ public function setUp() * * @return void */ - public function testValidateHappyToken() + public function testValidateHappyEmail() { $this->_mockFlash(); - $user = $this->table->findByToken('xxx')->first(); + $user = $this->table->findByToken('token-3')->first(); $this->assertFalse($user->active); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('User account validated successfully'); - $this->Trait->validate('email', 'xxx'); + $this->Trait->validate('email', 'token-3'); + $user = $this->table->findById($user->id)->first(); + $this->assertTrue($user->active); + } + + /** + * test + * + * @return void + */ + public function testValidateHappyPassword() + { + $this->markTestIncomplete('test is progress now'); + $this->_mockFlash(); + $user = $this->table->findByToken('token-4')->first(); + $this->assertTrue($user->active); + $oldPassword = $user->password; + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Reset password token was validated successfully'); + $this->Trait->validate('password', 'token-4'); $user = $this->table->findById($user->id)->first(); $this->assertTrue($user->active); } From a8906f10c2d5ee0d589821e73db445046b32f51b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Thu, 20 Aug 2015 10:10:30 -0500 Subject: [PATCH 0196/1476] Fix routes. Added more features to shell --- config/users.php | 1 + .../Traits/PasswordManagementTrait.php | 4 +- src/Shell/UsersShell.php | 109 ++++++++++++++++-- src/View/Helper/UserHelper.php | 2 +- 4 files changed, 104 insertions(+), 12 deletions(-) diff --git a/config/users.php b/config/users.php index 1cfccc4cb..de5f827e5 100644 --- a/config/users.php +++ b/config/users.php @@ -44,6 +44,7 @@ 'Profile' => [ //Allow view other users profiles 'viewOthers' => true, + 'route' => '/profile/' ], 'Key' => [ 'Session' => [ diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index e24ae49c8..994936cd5 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -37,12 +37,12 @@ public function changePassword() $user->id = $this->Auth->user('id'); $validatePassword = true; //@todo add to the documentation: list of routes used - $redirect = ['admin' => false, 'plugin' => 'Users', 'controller' => 'users', 'action' => 'profile']; + $redirect = Configure::read('Users.Profile.route'); } else { $user->id = $this->request->session()->read(Configure::read('Users.Key.Session.resetPasswordUserId')); $validatePassword = false; //@todo add to the documentation: list of routes used - $redirect = ['admin' => false, 'plugin' => 'Users', 'controller' => 'users', 'action' => 'login']; + $redirect = $this->Auth->config('loginAction'); } $this->set('validatePassword', $validatePassword); if ($this->request->is('post')) { diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 6732a0c52..ec39faf3b 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -13,6 +13,7 @@ use Cake\Auth\DefaultPasswordHasher; use Cake\Console\Shell; +use Cake\Core\Configure; use Cake\Utility\Hash; use Users\Model\Entity\User; @@ -23,6 +24,14 @@ */ class UsersShell extends Shell { + + /** + * Work as a seed for username generator + * + * @var array + */ + protected $_usernameSeed = ['aayla', 'admiral', 'anakin', 'chewbacca', 'darthvader', 'hansolo', 'luke', 'obiwan', 'leia', 'r2d2']; + /** * initialize callback * @@ -42,15 +51,55 @@ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description(__d('Users', 'Utilities for CakeDC Users Plugin')) - ->addSubcommand('addSuperuser')->description(__d('Users', 'Add a new superadmin user for testing purposes')) - ->addSubcommand('changeRole')->description(__d('Users', 'Change the role for an specific user')) - ->addSubcommand('resetAllPasswords')->description(__d('Users', 'Reset the password for all users')) - ->addSubcommand('resetPassword')->description(__d('Users', 'Reset the password for an specific user')) - ->addSubcommand('activateUser')->description(__d('Users', 'Activate an specific user')) - ->addSubcommand('deactivateUser')->description(__d('Users', 'Deactivate an specific user')); + ->addSubcommand('activateUser')->description(__d('Users', 'Activate an specific user')) + ->addSubcommand('addSuperuser')->description(__d('Users', 'Add a new superadmin user for testing purposes')) + ->addSubcommand('addUser')->description(__d('Users', 'Add a new user')) + ->addSubcommand('changeRole')->description(__d('Users', 'Change the role for an specific user')) + ->addSubcommand('deactivateUser')->description(__d('Users', 'Deactivate an specific user')) + ->addSubcommand('deleteUser')->description(__d('Users', 'Delete an specific user')) + ->addSubcommand('passwordEmail')->description(__d('Users', 'Reset the password via email')) + ->addSubcommand('resetAllPasswords')->description(__d('Users', 'Reset the password for all users')) + ->addSubcommand('resetPassword')->description(__d('Users', 'Reset the password for an specific user')) + ->addOptions([ + 'username' => ['short' => 'u', 'help' => 'The username for the new user'], + 'password' => ['short' => 'p', 'help' => 'The password for the new user'], + 'email' => ['short' => 'e', 'help' => 'The email for the new user'] + ]) + ; return $parser; } + /** + * Add a new user + * + * @return void + */ + public function addUser() + { + $username = (empty($this->params['username']) ? + $this->_usernameSeed[array_rand($this->_usernameSeed)] : $this->params['username']); + $username = $this->Users->generateUniqueUsername($username); + $password = (empty($this->params['password']) ? + str_replace('-', '', \Cake\Utility\Text::uuid()) : $this->params['password']); + $email = (empty($this->params['email']) ? $username . '@example.com' : $this->params['email']); + $user = [ + 'username' => $username, + 'email' => $email, + 'password' => $password, + 'active' => 1, + ]; + + $userEntity = $this->Users->newEntity($user); + $userEntity->is_superuser = true; + $userEntity->role = 'user'; + $savedUser = $this->Users->save($userEntity); + $this->out(__d('Users', 'User added:')); + $this->out(__d('Users', 'Id: {0}', $savedUser->id)); + $this->out(__d('Users', 'Username: {0}', $username)); + $this->out(__d('Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('Users', 'Password: {0}', $password)); + } + /** * Add a new superadmin user * @@ -78,8 +127,6 @@ public function addSuperuser() $this->out(__d('Users', 'Password: {0}', $password)); } - //addUser - /** * Reset password for all user * @@ -188,6 +235,31 @@ public function deactivateUser() $this->out(__d('Users', 'User was de-activated: {0}', $user->username)); } + /** + * Reset password via email for user + * + * @return void + */ + public function passwordEmail() + { + $reference = Hash::get($this->args, 0); + if (empty($reference)) { + $this->error(__d('Users', 'Please enter a username or email.')); + } + $resetUser = $this->Users->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => false, + 'sendEmail' => true, + ]); + if ($resetUser) { + $msg = __d('Users', 'Please ask the user to check the email to continue with password reset process'); + $this->out($msg); + } else { + $msg = __d('Users', 'The password token could not be generated. Please try again'); + $this->error($msg); + } + } + /** * Change user active field * @@ -228,8 +300,27 @@ protected function _updateUser($username, $data) return $savedUser; } + /** + * Delete an specific user and associated social accounts + * + * @return void + */ + public function deleteUser() + { + $username = Hash::get($this->args, 0); + if (empty($username)) { + $this->error(__d('Users', 'Please enter a username.')); + } + $user = $this->Users->find()->where(['Users.username' => $username])->first(); + $deleteAccounts = $this->Users->SocialAccounts->deleteAll(['user_id' => $user->id]); + $deleteUser = $this->Users->delete($user); + if ($deleteAccounts && $deleteUser) { + $this->out(__d('Users', 'The user {0} was deleted successfully', $username)); + } else { + $this->error(__d('Users', 'The user {0} was not deleted. Please try again', $username)); + } + } - //deleteUser user //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 39e26c24e..f51662baf 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -118,7 +118,7 @@ public function welcome() return; } - $profileUrl = '/profile/' . $userId; + $profileUrl = Configure::read('Users.Profile.route') . $userId; $label = __d('Users', 'Welcome, {0}', $this->Html->link($this->request->session()->read('Auth.User.first_name'), $profileUrl)); return $this->Html->tag('span', $label, ['class' => 'welcome']); } From beae313c1aa689d45f7298dd73990aa6491b55e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 20 Aug 2015 17:21:07 +0100 Subject: [PATCH 0197/1476] refs #refactor-behavior fix routes --- config/routes.php | 9 ++++----- config/users.php | 4 ++-- src/Template/Users/profile.ctp | 3 ++- src/View/Helper/UserHelper.php | 5 +++-- .../Controller/Component/UsersAuthComponentTest.php | 1 - .../Controller/Traits/PasswordManagementTraitTest.php | 2 +- tests/TestCase/View/Helper/UserHelperTest.php | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/config/routes.php b/config/routes.php index 1c5fbf3c8..e8a05ecc2 100644 --- a/config/routes.php +++ b/config/routes.php @@ -9,8 +9,8 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -use Cake\Routing\Router; use Cake\Core\Configure; +use Cake\Routing\Router; Router::plugin('Users', function ($routes) { $routes->fallbacks('DashedRoute'); @@ -23,11 +23,10 @@ ); }); Router::connect('/accounts/validate/*', [ - 'admin' => false, 'plugin' => 'Users', 'controller' => 'SocialAccounts', 'action' => 'validate' ]); -Router::connect('/profile/*', ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); -Router::connect('/login', ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); -Router::connect('/logout', ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout']); +Router::connect('/profile/*', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); +Router::connect('/login', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); +Router::connect('/logout', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout']); diff --git a/config/users.php b/config/users.php index de5f827e5..52d48470b 100644 --- a/config/users.php +++ b/config/users.php @@ -44,7 +44,7 @@ 'Profile' => [ //Allow view other users profiles 'viewOthers' => true, - 'route' => '/profile/' + 'route' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile'], ], 'Key' => [ 'Session' => [ @@ -103,7 +103,7 @@ 'Opauth' => [ 'path' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit'], 'callback_param' => 'callback', - 'complete_url' => ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'login'], + 'complete_url' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login'], 'Strategy' => [ 'Facebook' => [ 'scope' => ['public_profile', 'user_friends', 'email'] diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index 46d6e0e6f..5f2382dd8 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -20,7 +20,8 @@ ) ?> - Html->link(__d('Users', 'Change Password'), ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'changePassword']); ?> + + Html->link(__d('Users', 'Change Password'), ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'changePassword']); ?>
diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index f51662baf..2ad9b2f9f 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -38,7 +38,8 @@ class UserHelper extends Helper * @param Event $event event * @return void */ - public function beforeLayout(Event $event) { + public function beforeLayout(Event $event) + { if (Configure::read('Users.Registration.reCaptcha')) { $this->addReCaptchaScript(); } @@ -118,7 +119,7 @@ public function welcome() return; } - $profileUrl = Configure::read('Users.Profile.route') . $userId; + $profileUrl = Configure::read('Users.Profile.route'); $label = __d('Users', 'Welcome, {0}', $this->Html->link($this->request->session()->read('Auth.User.first_name'), $profileUrl)); return $this->Html->tag('span', $label, ['class' => 'welcome']); } diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 4bd8a1b59..73fce1718 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -62,7 +62,6 @@ public function setUp() ); }); Router::connect('/a/validate/*', [ - 'admin' => false, 'plugin' => 'Users', 'controller' => 'SocialAccounts', 'action' => 'resendValidation' diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 9322373d7..990e7ed5e 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -68,7 +68,7 @@ public function testChangePasswordHappy() ])); $this->Trait->expects($this->once()) ->method('redirect') - ->with(['admin' => false, 'plugin' => 'Users', 'controller' => 'users', 'action' => 'profile']); + ->with(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); $this->Trait->Flash->expects($this->any()) ->method('success') ->with('Password has been changed successfully'); diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 4a511e980..739a0c2a0 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -168,7 +168,7 @@ public function testWelcome() ->method('session') ->will($this->returnValue($session)); - $expected = 'Welcome, david'; + $expected = 'Welcome, david'; $result = $this->User->welcome(); $this->assertEquals($expected, $result); } From 58bbf697bee39a374951c52eda65e43851da3c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 20 Aug 2015 17:44:56 +0100 Subject: [PATCH 0198/1476] refs #refactor-behavior fix tokens --- .../Controller/Traits/PasswordManagementTraitTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 990e7ed5e..9aa5582a4 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -136,7 +136,7 @@ public function testResetPassword() */ public function testRequestResetPasswordGet() { - $this->assertEquals('xxx', $this->table->get(1)->token); + $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get(1)->token); $this->_mockRequestGet(); $this->_mockFlash(); $this->Trait->request->expects($this->never()) @@ -151,7 +151,7 @@ public function testRequestResetPasswordGet() */ public function testRequestPasswordHappy() { - $this->assertEquals('xxx', $this->table->get(1)->token); + $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get(1)->token); $this->_mockRequestPost(); $this->_mockAuthLoggedIn(); $this->_mockFlash(); From 6073fd276ffe738c99cc405bd7d16cb37c1a9b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 21 Aug 2015 09:56:50 +0100 Subject: [PATCH 0199/1476] refs #refactor-behavior improve coverage --- src/Controller/Traits/UserValidationTrait.php | 11 +- tests/Fixture/UsersFixture.php | 2 +- .../Traits/UserValidationTraitTest.php | 131 +++++++++++++++++- 3 files changed, 134 insertions(+), 10 deletions(-) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 0d3349358..fa702735f 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -53,21 +53,20 @@ public function validate($type = null, $token = null) if (!empty($result)) { $this->Flash->success(__d('Users', 'Reset password token was validated successfully')); $this->request->session()->write(Configure::read('Users.Key.Session.resetPasswordUserId'), $result->id); - $this->redirect(['action' => 'changePassword']); + return $this->redirect(['action' => 'changePassword']); } else { $this->Flash->error(__d('Users', 'Reset password token could not be validated')); } break; default: - throw new InvalidArgumentException(); + $this->Flash->error(__d('Users', 'Invalid validation type')); } - } catch (UserNotFoundException $exception) { + } catch (UserNotFoundException $ex) { $this->Flash->error(__d('Users', 'Invalid token and/or email')); - } catch (TokenExpiredException $exception) { + } catch (TokenExpiredException $ex) { $this->Flash->error(__d('Users', 'Token already expired')); - } catch (InvalidArgumentException $iae) { - $this->Flash->error(__d('Users', 'Invalid validation type')); } + return $this->redirect(['action' => 'login']); } diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index d8b1d6af7..20f2346dc 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -121,7 +121,7 @@ class UsersFixture extends TestFixture 'first_name' => 'FirstName4', 'last_name' => 'Lorem ipsum dolor sit amet', 'token' => 'token-4', - 'token_expires' => '2015-06-24 17:33:54', + 'token_expires' => '2030-06-24 17:33:54', 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 780fdf7b8..fddd1016a 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -33,7 +33,7 @@ class UserValidationTraitTest extends BaseTraitTest public function setUp() { $this->traitClassName = 'Users\Controller\Traits\UserValidationTrait'; - $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable']; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; parent::setUp(); } @@ -50,11 +50,65 @@ public function testValidateHappyEmail() $this->Trait->Flash->expects($this->once()) ->method('success') ->with('User account validated successfully'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); $this->Trait->validate('email', 'token-3'); $user = $this->table->findById($user->id)->first(); $this->assertTrue($user->active); } + /** + * test + * + * @return void + */ + public function testValidateUserNotFound() + { + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Invalid token and/or email'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->validate('email', 'not-found'); + } + + /** + * test + * + * @return void + */ + public function testValidateTokenExpired() + { + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Token already expired'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->validate('email', '6614f65816754310a5f0553436dd89e9'); + } + + /** + * test + * + * @return void + */ + public function testValidateInvalidOp() + { + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Invalid validation type'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->validate('invalid-op', '6614f65816754310a5f0553436dd89e9'); + } + /** * test * @@ -62,16 +116,87 @@ public function testValidateHappyEmail() */ public function testValidateHappyPassword() { - $this->markTestIncomplete('test is progress now'); + $this->_mockRequestGet(); $this->_mockFlash(); $user = $this->table->findByToken('token-4')->first(); $this->assertTrue($user->active); - $oldPassword = $user->password; $this->Trait->Flash->expects($this->once()) ->method('success') ->with('Reset password token was validated successfully'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'changePassword']); $this->Trait->validate('password', 'token-4'); $user = $this->table->findById($user->id)->first(); $this->assertTrue($user->active); } + + /** + * test + * + * @return void + */ + public function testResendTokenValidationHappy() + { + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->with('reference') + ->will($this->returnValue('user-3')); + + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Token has been reset successfully'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->resendTokenValidation(); + } + + /** + * test + * + * @return void + */ + public function testResendTokenValidationAlreadyActive() + { + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->with('reference') + ->will($this->returnValue('user-4')); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User user-4 is already active'); + $this->Trait->expects($this->never()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->resendTokenValidation(); + } + + /** + * test + * + * @return void + */ + public function testResendTokenValidationNotFound() + { + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->with('reference') + ->will($this->returnValue('not-found')); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User not-found was not found'); + $this->Trait->expects($this->never()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->resendTokenValidation(); + } } From 823b8d819d349c3dba7288f7781ab6132627a048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 21 Aug 2015 11:24:49 +0100 Subject: [PATCH 0200/1476] refs #refactor-behavior improve coverage --- src/Controller/Traits/SimpleCrudTrait.php | 15 +- src/Test/BaseTraitTest.php | 18 +- .../Traits/PasswordManagementTraitTest.php | 9 - .../Controller/Traits/RegisterTraitTest.php | 9 - .../Controller/Traits/SimpleCrudTraitTest.php | 281 ++++++++++++++++++ .../Traits/UserValidationTraitTest.php | 9 - 6 files changed, 304 insertions(+), 37 deletions(-) create mode 100644 tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index 9171ed4df..9bbba9b58 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -71,11 +71,12 @@ public function add() return; } $entity = $table->patchEntity($entity, $this->request->data); + $singular = Inflector::singularize(Inflector::humanize($tableAlias)); if ($table->save($entity)) { - $this->Flash->success(__d('Users', 'The {0} has been saved', Inflector::humanize($tableAlias))); + $this->Flash->success(__d('Users', 'The {0} has been saved', $singular)); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__d('Users', 'The {0} could not be saved', Inflector::humanize($tableAlias))); + $this->Flash->error(__d('Users', 'The {0} could not be saved', $singular)); } /** @@ -99,11 +100,12 @@ public function edit($id = null) return; } $entity = $table->patchEntity($entity, $this->request->data); + $singular = Inflector::singularize(Inflector::humanize($tableAlias)); if ($table->save($entity)) { - $this->Flash->success(__d('Users', 'The {0} has been saved', Inflector::humanize($tableAlias))); + $this->Flash->success(__d('Users', 'The {0} has been saved', $singular)); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__d('Users', 'The {0} could not be saved', Inflector::humanize($tableAlias))); + $this->Flash->error(__d('Users', 'The {0} could not be saved', $singular)); } /** @@ -121,10 +123,11 @@ public function delete($id = null) $entity = $table->get($id, [ 'contain' => [] ]); + $singular = Inflector::singularize(Inflector::humanize($tableAlias)); if ($table->delete($entity)) { - $this->Flash->success(__d('Users', 'The {0} has been deleted', Inflector::humanize($tableAlias))); + $this->Flash->success(__d('Users', 'The {0} has been deleted', $singular)); } else { - $this->Flash->error(__d('Users', 'The {0} could not be deleted', Inflector::humanize($tableAlias))); + $this->Flash->error(__d('Users', 'The {0} could not be deleted', $singular)); } return $this->redirect(['action' => 'index']); } diff --git a/src/Test/BaseTraitTest.php b/src/Test/BaseTraitTest.php index 52deaf04e..faa725cbe 100644 --- a/src/Test/BaseTraitTest.php +++ b/src/Test/BaseTraitTest.php @@ -18,6 +18,15 @@ abstract class BaseTraitTest extends TestCase { + /** + * Fixtures + * + * @var array + */ + public $fixtures = [ + 'plugin.users.users', + ]; + /** * Classname of the trait we are about to test * @@ -90,18 +99,19 @@ protected function _mockFlash() } /** - * mock Request for POST + * mock Request for POST, is and allow methods * + * @param mixed $with used in with * @return void */ - protected function _mockRequestPost() + protected function _mockRequestPost($with = 'post') { $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') ->setMethods(['is', 'data']) ->getMock(); - $this->Trait->request->expects($this->once()) + $this->Trait->request->expects($this->any()) ->method('is') - ->with('post') + ->with($with) ->will($this->returnValue(true)); } diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 9aa5582a4..a5e9d547e 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -18,15 +18,6 @@ class PasswordManagementTraitTest extends BaseTraitTest { - /** - * Fixtures - * - * @var array - */ - public $fixtures = [ - 'plugin.users.users', - ]; - /** * setUp * diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index cde21897b..31a8f544d 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -16,15 +16,6 @@ class RegisterTraitTest extends BaseTraitTest { - /** - * Fixtures - * - * @var array - */ - public $fixtures = [ - 'plugin.users.users', - ]; - /** * setUp * diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php new file mode 100644 index 000000000..17a877a56 --- /dev/null +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -0,0 +1,281 @@ +traitClassName = 'Users\Controller\Traits\SimpleCrudTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set', 'loadModel', 'paginate']; + parent::setUp(); + $viewVarsContainer = $this; + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) use ($viewVarsContainer) { + $viewVarsContainer->viewVars[$param1] = $param2; + })); + $this->Trait->expects($this->once()) + ->method('loadModel') + ->will($this->returnValue($this->table)); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + $this->viewVars = null; + parent::tearDown(); + } + + /** + * test + * + * @return void + */ + public function testIndex() + { + $this->Trait->expects($this->once()) + ->method('paginate') + ->with($this->table) + ->will($this->returnValue([])); + $this->Trait->index(); + $expected = [ + 'Users' => [], + 'tableAlias' => 'Users', + '_serialize' => [ + 'Users', + 'tableAlias' + ] + ]; + $this->assertSame($expected, $this->viewVars); + } + + /** + * test + * + * @return void + */ + public function testView() + { + $id = 1; + $this->Trait->view($id); + $expected = [ + 'Users' => $this->table->get($id), + 'tableAlias' => 'Users', + '_serialize' => [ + 'Users', + 'tableAlias' + ] + ]; + $this->assertEquals($expected, $this->viewVars); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\RecordNotFoundException + */ + public function testViewNotFound() + { + $this->Trait->view('not-found'); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\InvalidPrimaryKeyException + */ + public function testViewInvalidPK() + { + $this->Trait->view(); + } + + /** + * test + * + * @return void + */ + public function testAddGet() + { + $this->_mockRequestGet(); + $this->Trait->add(); + $expected = [ + 'Users' => $this->table->newEntity(), + 'tableAlias' => 'Users', + '_serialize' => [ + 'Users', + 'tableAlias' + ] + ]; + $this->assertEquals($expected, $this->viewVars); + } + + /** + * test + * + * @return void + */ + public function testAddPostHappy() + { + $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->data = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('The User has been saved'); + + $this->Trait->add(); + + $this->assertSame(1, $this->table->find()->where(['username' => 'testuser'])->count()); + } + + /** + * test + * + * @return void + */ + public function testAddPostErrors() + { + $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->data = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The User could not be saved'); + + $this->Trait->add(); + + $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); + } + + /** + * test + * + * @return void + */ + public function testEditPostHappy() + { + $this->assertEquals('user-1@test.com', $this->table->get(1)->email); + $this->_mockRequestPost(['patch', 'post', 'put']); + $this->_mockFlash(); + $this->Trait->request->data = [ + 'email' => 'newtestuser@test.com', + ]; + + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('The User has been saved'); + + $this->Trait->edit(1); + + $this->assertEquals('newtestuser@test.com', $this->table->get(1)->email); + } + + /** + * test + * + * @return void + */ + public function testEditPostErrors() + { + $this->assertEquals('user-1@test.com', $this->table->get(1)->email); + $this->_mockRequestPost(['patch', 'post', 'put']); + $this->_mockFlash(); + $this->Trait->request->data = [ + 'email' => 'not-an-email', + ]; + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The User could not be saved'); + + $this->Trait->edit(1); + + $this->assertEquals('user-1@test.com', $this->table->get(1)->email); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\RecordNotFoundException + */ + public function testDeleteHappy() + { + $this->assertNotEmpty($this->table->get(1)); + $this->_mockRequestPost(); + $this->Trait->request->expects($this->any()) + ->method('allow') + ->with(['post', 'delete']) + ->will($this->returnValue(true)); + + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('The User has been deleted'); + + $this->Trait->delete(1); + + $this->table->get(1); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\RecordNotFoundException + */ + public function testDeleteNotFound() + { + $this->assertNotEmpty($this->table->get(1)); + $this->_mockRequestPost(); + $this->Trait->request->expects($this->any()) + ->method('allow') + ->with(['post', 'delete']) + ->will($this->returnValue(true)); + + $this->Trait->delete('not-found'); + + $this->assertNotEmpty($this->table->get(1)); + } +} diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index fddd1016a..0449a59cc 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -16,15 +16,6 @@ class UserValidationTraitTest extends BaseTraitTest { - /** - * Fixtures - * - * @var array - */ - public $fixtures = [ - 'plugin.users.users', - ]; - /** * setup * From 8c559479c506f66836d7f040ed6c82456cb7d347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 22 Aug 2015 18:02:01 +0100 Subject: [PATCH 0201/1476] refs #refactor-behavior fix SocialAccounts allow, add tests --- src/Controller/SocialAccountsController.php | 2 +- .../SocialAccountsControllerTest.php | 105 ++++++++++++++++++ .../Behavior/SocialAccountBehaviorTest.php | 1 - 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 tests/TestCase/Controller/SocialAccountsControllerTest.php diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 4f9d147c7..96473ffd0 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -33,7 +33,7 @@ class SocialAccountsController extends AppController public function initialize() { parent::initialize(); - $this->Auth->allow(['validate', 'resendValidation']); + $this->Auth->allow(['validateAccount', 'resendValidation']); } /** diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php new file mode 100644 index 000000000..48dd6dc79 --- /dev/null +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -0,0 +1,105 @@ +get('/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234'); + $this->assertResponseSuccess(); + $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + $this->assertSession('Account validated successfully', 'Flash.flash.message'); + } + + /** + * test + * + * @return void + */ + public function testValidateAccountInvalidToken() + { + $this->get('/users/social-accounts/validate-account/Facebook/reference-1-1234/token-not-found'); + $this->assertResponseSuccess(); + $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + $this->assertSession('Invalid token and/or social account', 'Flash.flash.message'); + } + + /** + * test + * + * @return void + */ + public function testValidateAccountAlreadyActive() + { + $this->get('/users/social-accounts/validate-account/Twitter/reference-1-1234/token-1234'); + $this->assertResponseSuccess(); + $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + $this->assertSession('SocialAccount already active', 'Flash.flash.message'); + } + + /** + * test + * + * @return void + */ + public function testResendValidationHappy() + { + $this->get('/users/social-accounts/resend-validation/Facebook/reference-1-1234'); + $this->assertResponseSuccess(); + $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + $this->assertSession('Email sent successfully', 'Flash.flash.message'); + } + + /** + * test + * + * @return void + */ + public function testResendValidationInvalid() + { + $this->get('/users/social-accounts/resend-validation/Facebook/reference-invalid'); + $this->assertResponseSuccess(); + $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + $this->assertSession('Invalid account', 'Flash.flash.message'); + } + + /** + * test + * + * @return void + */ + public function testResendValidationAlreadyActive() + { + $this->get('/users/social-accounts/validate-account/Twitter/reference-1-1234/token-1234'); + $this->assertResponseSuccess(); + $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + $this->assertSession('SocialAccount already active', 'Flash.flash.message'); + } +} diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index e321a57de..22614c95c 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -17,7 +17,6 @@ use InvalidArgumentException; use Users\Model\Table\SocialAccountsTable; - /** * Test Case */ From 4342da6e0fc929fd6d9ab6a636eea3243e15fd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 22 Aug 2015 18:51:59 +0100 Subject: [PATCH 0202/1476] refs #refactor-behavior refactor register trait register fixing a couple bugs, improve test coverage --- src/Controller/Traits/RegisterTrait.php | 60 ++++-- src/Model/Behavior/RegisterBehavior.php | 1 + .../Controller/Traits/RegisterTraitTest.php | 198 +++++++++++++++++- 3 files changed, 240 insertions(+), 19 deletions(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 36d3cdfd6..db434d78a 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -13,7 +13,9 @@ use Cake\Core\Configure; use Cake\Datasource\EntityInterface; +use Cake\Network\Exception\NotFoundException; use Cake\Network\Response; +use InvalidArgumentException; use Users\Controller\Component\UsersAuthComponent; /** @@ -32,8 +34,8 @@ trait RegisterTrait */ public function register() { - if (!Configure::check('Users.Registration.active')) { - throw new \Cake\Network\Exception\NotFoundException(); + if (!Configure::read('Users.Registration.active')) { + throw new NotFoundException(); } $usersTable = $this->getUsersTable(); $user = $usersTable->newEntity(); @@ -61,25 +63,47 @@ public function register() return $this->redirect($event->result); } - if ($this->request->is('post')) { - $validReCaptcha = $this->validateReCaptcha( - $this->request->data('g-recaptcha-response'), - $this->request->clientIp() - ); - if ($validReCaptcha) { - if ($userSaved = $usersTable->register($user, $requestData, $options)) { - return $this->_afterRegister($userSaved); - } else { - $this->Flash->error(__d('Users', 'The user could not be saved')); - } - } else { - $this->Flash->error(__d('Users', 'The reCaptcha could not be validated')); - } + $this->set(compact('user')); + $this->set('_serialize', ['user']); + + if (!$this->request->is('post')) { + return; } + $validPost = $this->_validateRegisterPost(); + if (!$validPost) { + $this->Flash->error(__d('Users', 'The reCaptcha could not be validated')); + return; + } + try { + $userSaved = $usersTable->register($user, $requestData, $options); + } catch (InvalidArgumentException $ex) { + $this->Flash->error($ex->getMessage()); + return; + } + if (!$userSaved) { + $this->Flash->error(__d('Users', 'The user could not be saved')); + return; + } - $this->set(compact('user')); - $this->set('_serialize', ['user']); + return $this->_afterRegister($userSaved); + } + + /** + * Check the POST and validate it for registration, for now we check the reCaptcha + * + * @return bool + */ + protected function _validateRegisterPost() + { + if (!Configure::read('Users.Registration.reCaptcha')) { + return true; + } + $validReCaptcha = $this->validateReCaptcha( + $this->request->data('g-recaptcha-response'), + $this->request->clientIp() + ); + return $validReCaptcha; } /** diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 75a4584d9..ab45ce31f 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -47,6 +47,7 @@ public function register($user, $data, $options) $tokenExpiration = Hash::get($options, 'token_expiration'); $useTos = Hash::get($options, 'use_tos'); if ($useTos && !$user->tos) { + //@todo: move to a specific validation rule for TOS instead of managing validation in controller throw new InvalidArgumentException(__d('Users', 'The "tos" property is not present')); } diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 31a8f544d..e491d4486 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -11,6 +11,7 @@ namespace Users\Test\TestCase\Controller\Traits; +use Cake\Core\Configure; use Cake\ORM\TableRegistry; use Users\Test\BaseTraitTest; @@ -24,7 +25,7 @@ class RegisterTraitTest extends BaseTraitTest public function setUp() { $this->traitClassName = 'Users\Controller\Traits\RegisterTrait'; - $this->traitMockMethods = ['validate', 'dispatchEvent', 'set']; + $this->traitMockMethods = ['validate', 'dispatchEvent', 'set', 'validateReCaptcha', 'redirect']; parent::setUp(); } @@ -59,10 +60,205 @@ public function testValidateEmail() */ public function testRegisterHappy() { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->once()) + ->method('validateRecaptcha') + ->will($this->returnValue(true)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->data = [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ]; + + $this->Trait->register(); + + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterValidationErrors() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The user could not be saved'); + $this->Trait->expects($this->once()) + ->method('validateRecaptcha') + ->will($this->returnValue(true)); + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->Trait->request->data = [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'not-matching', + 'tos' => 1 + ]; + + $this->Trait->register(); + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + * @todo: remove this use case once the TOS is refactored in RegisterBehavior + */ + public function testRegisterNoTos() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The "tos" property is not present'); + $this->Trait->expects($this->once()) + ->method('validateRecaptcha') + ->will($this->returnValue(true)); + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->Trait->request->data = [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 0 + ]; + + $this->Trait->register(); + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterRecaptchaNotValid() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The reCaptcha could not be validated'); + $this->Trait->expects($this->once()) + ->method('validateRecaptcha') + ->will($this->returnValue(false)); + $this->Trait->request->data = [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ]; + + $this->Trait->register(); + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterGet() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + $this->Trait->expects($this->never()) + ->method('validateRecaptcha'); + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->Trait->register(); + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterRecaptchaDisabled() + { + $recaptcha = Configure::read('Users.Registration.reCaptcha'); + Configure::write('Users.Registration.reCaptcha', false); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->never()) + ->method('validateRecaptcha'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->data = [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ]; + + $this->Trait->register(); + + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + Configure::write('Users.Registration.reCaptcha', $recaptcha); + } + + /** + * test + * + * @return void + * @expectedException Cake\Network\Exception\NotFoundException + */ + public function testRegisterNotEnabled() + { + $active = Configure::read('Users.Registration.active'); + Configure::write('Users.Registration.active', false); $this->_mockRequestPost(); $this->_mockAuth(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->register(); + Configure::write('Users.Registration.active', $active); } } From 7d6f4a1fd7d18d2e65d6ae5ff71e52bb16411b82 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Sat, 22 Aug 2015 23:44:31 -0430 Subject: [PATCH 0203/1476] WIP Users shell unit tests --- src/Shell/UsersShell.php | 39 +++- tests/TestCase/Shell/UsersShellTest.php | 242 ++++++++++++++++++++++++ 2 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 tests/TestCase/Shell/UsersShellTest.php diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index ec39faf3b..4870cf0d2 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -77,10 +77,11 @@ public function getOptionParser() public function addUser() { $username = (empty($this->params['username']) ? - $this->_usernameSeed[array_rand($this->_usernameSeed)] : $this->params['username']); + $this->_generateRandomUsername() : $this->params['username']); + $username = $this->Users->generateUniqueUsername($username); $password = (empty($this->params['password']) ? - str_replace('-', '', \Cake\Utility\Text::uuid()) : $this->params['password']); + $this->_generateRandomPassword() : $this->params['password']); $email = (empty($this->params['email']) ? $username . '@example.com' : $this->params['email']); $user = [ 'username' => $username, @@ -108,7 +109,7 @@ public function addUser() public function addSuperuser() { $username = $this->Users->generateUniqueUsername('superadmin'); - $password = str_replace('-', '', \Cake\Utility\Text::uuid()); + $password = $this->_generateRandomPassword(); $user = [ 'username' => $username, 'email' => $username . '@example.com', @@ -142,7 +143,7 @@ public function resetAllPasswords() if (empty($password)) { $this->error(__d('Users', 'Please enter a password.')); } - $hashedPassword = (new User)->hashPassword($password); + $hashedPassword = $this->_generatedHashedPassword($password); $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); $this->out(__d('Users', 'Password changed for all users')); $this->out(__d('Users', 'New password: {0}', $password)); @@ -321,6 +322,36 @@ public function deleteUser() } } + /** + * Generates a random password. + * + * @return void + */ + protected function _generateRandomPassword() + { + return str_replace('-', '', \Cake\Utility\Text::uuid()); + } + + /** + * Generates a random username based on a list of preexisting ones. + * + * @return void + */ + protected function _generateRandomUsername() + { + return $this->_usernameSeed[array_rand($this->_usernameSeed)]; + } + + /** + * Hash a password + * + * @param password + * @return void + */ + 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/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php new file mode 100644 index 000000000..3236581f9 --- /dev/null +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -0,0 +1,242 @@ +out = new ConsoleOutput(); + $this->io = new ConsoleIo($this->out); + $this->Users = TableRegistry::get('Users.Users'); + + $this->Shell = $this->getMockBuilder('Users\Shell\UsersShell') + ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', + '_generateRandomUsername', '_generatedHashedPassword', 'error']) + ->setConstructorArgs([$this->io]) + ->getMock(); + + $this->Shell->Users = $this->getMockBuilder('Users\Model\UsersTable') + ->setMethods(['generateUniqueUsername', 'newEntity', 'save', 'updateAll']) + ->getMock(); + + $this->Shell->Command = $this->getMock( + 'Cake\Shell\Task\CommandTask', + ['in', '_stop', 'clear', 'out'], + [$this->io] + ); + } + + /** + * Tear Down + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + unset($this->Shell); + } + + /** + * Add user test + * Adding user with username, email and password + * + * @return void + */ + public function testAddUser() + { + $user = [ + 'username' => 'yeliparra', + 'password' => '123', + 'email' => 'yeli.parra@gmail.com', + 'active' => 1, + ]; + + $this->Shell->expects($this->never()) + ->method('_generateRandomUsername'); + + $this->Shell->expects($this->never()) + ->method('_generateRandomPassword'); + + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with($user['username']) + ->will($this->returnValue($user['username'])); + + $entityUser = $this->Users->newEntity($user); + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + //TODO: Add assertions with 'out' + + $this->Shell->runCommand(['addUser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email']]); + + } + + /** + * Add user test + * Adding user passing no params + * + * @return void + */ + public function testAddUserWithNoParams() + { + $user = [ + 'username' => 'anakin', + 'password' => 'mypassword', + 'email' => 'anakin@example.com', + 'active' => 1, + ]; + + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with($user['username']) + ->will($this->returnValue($user['username'])); + + $this->Shell->expects($this->once()) + ->method('_generateRandomPassword') + ->will($this->returnValue($user['password'])); + + $this->Shell->expects($this->once()) + ->method('_generateRandomUsername') + ->will($this->returnValue($user['username'])); + + $entityUser = $this->Users->newEntity($user); + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + //TODO: Add assertions with 'out' + + $this->Shell->runCommand(['addUser']); + + } + + /** + * Add superadmin user + * + * @return void + */ + public function testAddSuperuser() + { + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with('superadmin') + ->will($this->returnValue('superadmin')); + + $this->Shell->expects($this->once()) + ->method('_generateRandomPassword') + ->will($this->returnValue('password')); + + $user = [ + 'username' => 'superadmin', + 'password' => 'password', + 'email' => 'superadmin@example.com', + 'active' => 1, + ]; + $entityUser = $this->Users->newEntity($user); + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + $userSaved->is_superuser = true; + $userSaved->role = 'superuser'; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + $this->Shell->runCommand(['addSuperuser']); + + } + + /** + * Reset all passwords + * + * @return void + */ + public function testResetAllPasswords() + { + $this->Shell->expects($this->once()) + ->method('_generatedHashedPassword') + ->will($this->returnValue('hashedPasssword')); + + $this->Shell->Users->expects($this->once()) + ->method('updateAll') + ->with(['password' => 'hashedPasssword'], ['id IS NOT NULL']); + + $this->Shell->runCommand(['resetAllPasswords', '123']); + + } + + /** + * Reset all passwords + * + * @return void + */ + public function testResetAllPasswordsNoPassingParams() + { + $this->Shell->expects($this->once()) + ->method('error') + ->with('Please enter a password.'); + + $this->Shell->runCommand(['resetAllPasswords']); + + } +} From 19b178a4dd912f7548c7df104d12bc3dc95047a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 24 Aug 2015 11:06:34 +0100 Subject: [PATCH 0204/1476] refs #refactor-behavior fix isUrlAuthorized to match array format in string and array url formats, improve coverage --- .../Component/UsersAuthComponent.php | 6 +- .../Component/UsersAuthComponentTest.php | 111 ++++++++++++++++++ 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 12c98bdb5..2f92ca44a 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -125,19 +125,19 @@ public function isUrlAuthorized(Event $event) if (empty($this->_registry->getController()->Auth->user())) { return false; } - $url = Hash::get($event->data, 'url'); + $url = Hash::get((array)$event->data, 'url'); if (empty($url)) { return false; } if (is_array($url)) { - $requestParams = $url; $requestUrl = Router::reverse($url); + $requestParams = Router::parse($requestUrl); } else { $requestParams = Router::parse($url); $requestUrl = $url; } - $request = new Request($url); + $request = new Request($requestUrl); $request->params = $requestParams; $isAuthorized = $this->_registry->getController()->Auth->isAuthorized(null, $request); diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 73fce1718..6a2474e49 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -14,6 +14,8 @@ use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Database\Exception; +use Cake\Event\Event; +use Cake\Network\Request; use Cake\Network\Session; use Cake\ORM\Entity; use Cake\Routing\Router; @@ -122,4 +124,113 @@ public function testInitializeNoRequiredRememberMe() ->method('_loadRememberMe'); $this->Controller->UsersAuth->initialize([]); } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUserNotLoggedIn() + { + $event = new Event('event'); + $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 + * + * @return void + */ + public function testIsUrlAuthorizedNoUrl() + { + $event = new Event('event'); + $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])); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUrlString() + { + $event = new Event('event'); + $event->data = [ + 'url' => '/a/validate', + ]; + $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])); + $request = new Request('/a/validate'); + $request->params = [ + 'plugin' => 'Users', + 'controller' => 'SocialAccounts', + 'action' => 'resendValidation', + 'pass' => [], + ]; + $this->Controller->Auth->expects($this->once()) + ->method('isAuthorized') + ->with(null, $request) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUrlArray() + { + $event = new Event('event'); + $event->data = [ + 'url' => [ + 'plugin' => 'Users', + 'controller' => 'SocialAccounts', + 'action' => 'resendValidation', + '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])); + $request = new Request('/a/validate/pass-one'); + $request->params = [ + 'plugin' => 'Users', + 'controller' => 'SocialAccounts', + 'action' => 'resendValidation', + 'pass' => ['pass-one'], + ]; + $this->Controller->Auth->expects($this->once()) + ->method('isAuthorized') + ->with(null, $request) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } } From 02df17218788b73e01364512001862736d13d691 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Mon, 24 Aug 2015 21:58:09 -0430 Subject: [PATCH 0205/1476] Refactoring tos and email validation in RegisterBehavior. Updating and adding unit tests --- src/Model/Behavior/RegisterBehavior.php | 97 ++++++++++++++++--- src/Model/Entity/User.php | 12 +++ src/Model/Table/UsersTable.php | 16 --- .../Controller/Traits/RegisterTraitTest.php | 34 ------- .../Model/Behavior/RegisterBehaviorTest.php | 56 ++++++++++- 5 files changed, 145 insertions(+), 70 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index ab45ce31f..a7e162e8e 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -11,8 +11,11 @@ namespace Users\Model\Behavior; +use Cake\Core\Configure; use Cake\Datasource\EntityInterface; +use Cake\Event\Event; use Cake\Utility\Hash; +use Cake\Validation\Validator; use DateTime; use InvalidArgumentException; use Users\Exception\TokenExpiredException; @@ -21,11 +24,25 @@ use Users\Model\Behavior\Behavior; use Users\Model\Entity\User; + /** * Covers the user registration */ class RegisterBehavior extends Behavior { + /** + * Constructor hook method. + * + * @param array $config The configuration settings provided to this behavior. + * @return void + */ + public function initialize(array $config) + { + parent::initialize($config); + $this->validateEmail = (bool)Configure::read('Users.Email.validate'); + $this->useTos = (bool)Configure::read('Users.Tos.required'); + } + /** * Registers an user. * @@ -38,29 +55,15 @@ class RegisterBehavior extends Behavior public function register($user, $data, $options) { $validateEmail = Hash::get($options, 'validate_email'); - $validator = Hash::get($options, 'validator') ?: 'register'; - if ($validateEmail) { - $validator = 'email'; - } - $user = $this->_table->patchEntity($user, $data, ['validate' => $validator]); - $tokenExpiration = Hash::get($options, 'token_expiration'); - $useTos = Hash::get($options, 'use_tos'); - if ($useTos && !$user->tos) { - //@todo: move to a specific validation rule for TOS instead of managing validation in controller - throw new InvalidArgumentException(__d('Users', 'The "tos" property is not present')); - } - - if (!empty($user['tos'])) { - $user->tos_date = new DateTime(); - } + $user = $this->_table->patchEntity($user, $data, ['validate' => Hash::get($options, 'validator') ?: $this->_getValidators($options)]); $user->validated = false; //@todo move updateActive to afterSave? $user = $this->_updateActive($user, $validateEmail, $tokenExpiration); $this->_table->isValidateEmail = $validateEmail; $userSaved = $this->_table->save($user); if ($userSaved && $validateEmail) { - // $this->_sendEmail($user, __d('Users', 'Your account validation link')); + $this->_sendEmail($user, __d('Users', 'Your account validation link')); } return $userSaved; } @@ -112,4 +115,66 @@ public function activateUser(EntityInterface $user) return $result; } + + public function buildValidator(Event $event, Validator $validator, $name){ + if ($name == 'default') { + $this->_emailValidator($validator, $this->validateEmail); + } + } + + /** + * Email validator + * + * @param Validator $validator Validator instance. + * @param $validateEmail true when email needs to be required + * @return Validator + */ + protected function _emailValidator(Validator $validator, $validateEmail) + { + $this->validateEmail = $validateEmail; + $validator + ->add('email', 'valid', ['rule' => 'email']) + ->notEmpty('email', 'This field is required', function ($context) { + return $this->validateEmail; + }); + return $validator; + } + + /** + * Tos validator + * + * @param Validator $validator Validator instance. + * @return Validator + */ + protected function _tosValidator(Validator $validator) + { + $validator + ->requirePresence('tos', 'create') + ->notEmpty('tos'); + return $validator; + } + + /** + * Returns the list of validators + * + * @param array $options Array of options ['validate_email' => true/false, 'use_tos' => true/false] + * @return Validator + */ + protected function _getValidators($options) + { + $validateEmail = Hash::get($options, 'validate_email'); + $useTos = Hash::get($options, 'use_tos'); + + $validator = $this->_table->validationDefault(new Validator()); + $validator = $this->_table->validationRegister($validator); + if ($useTos) { + $validator = $this->_tosValidator($validator); + } + + if ($validateEmail) { + $validator = $this->_emailValidator($validator, $validateEmail); + } + return $validator; + + } } diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 6802f02cb..692127a68 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -65,6 +65,18 @@ protected function _setConfirmPassword($password) return $this->hashPassword($password); } + /** + * @param string $tos tos option. It will be set the tos_date + * @return bool + */ + protected function _setTos($tos) + { + if ((bool)$tos === true) { + $this->set('tos_date', new DateTime()); + } + return $tos; + } + /** * Hash a password using the configured password hasher, * use DefaultPasswordHasher if no one was configured diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 91228b5ae..fa5af04a1 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -129,22 +129,6 @@ public function validationDefault(Validator $validator) return $validator; } - /** - * Default+Email validation rules. - * - * @param Validator $validator Validator instance. - * @return Validator - */ - public function validationEmail(Validator $validator) - { - $validator = $this->validationRegister($validator); - $validator - ->add('email', 'valid', ['rule' => 'email']) - ->requirePresence('email', 'create') - ->notEmpty('email'); - return $validator; - } - /** * Wrapper for all validation rules for register * @param Validator $validator Cake validator object. diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index e491d4486..da58f8b61 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -120,40 +120,6 @@ public function testRegisterValidationErrors() $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); } - /** - * test - * - * @return void - * @todo: remove this use case once the TOS is refactored in RegisterBehavior - */ - public function testRegisterNoTos() - { - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The "tos" property is not present'); - $this->Trait->expects($this->once()) - ->method('validateRecaptcha') - ->will($this->returnValue(true)); - $this->Trait->expects($this->never()) - ->method('redirect'); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 0 - ]; - - $this->Trait->register(); - - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - /** * test * diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 868369e8a..1070984ed 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -51,7 +51,7 @@ public function setUp() */ public function tearDown() { - unset($this->table, $this->Behavior); + unset($this->Table, $this->Behavior); parent::tearDown(); } @@ -93,7 +93,7 @@ public function testValidateRegisterEmptyUser() * * @return void */ - public function testValidateRegisterValidateEmail() + public function testValidateRegisterValidateEmailAndTos() { $user = [ 'username' => 'testuser', @@ -107,12 +107,59 @@ public function testValidateRegisterValidateEmail() $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $this->assertNotEmpty($result); $this->assertFalse($result->active); + $this->assertNotEmpty($result->tos_date); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterValidatorOption() + { + $this->Table = $this->getMockForModel('Users.Users', ['validationCustom', 'patchEntity', 'errors', 'save']); + + $this->Behavior = $this->getMockBuilder('Users\Model\Behavior\RegisterBehavior') + ->setMethods(['getValidators', '_updateActive']) + ->setConstructorArgs([$this->Table]) + ->getMock(); + + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + + $this->Behavior->expects($this->never()) + ->method('getValidators'); + + $entityUser = $this->Table->newEntity($user); + + $this->Behavior->expects($this->once()) + ->method('_updateActive') + ->will($this->returnValue($entityUser)); + + $this->Table->expects($this->once()) + ->method('patchEntity') + ->with($this->Table->newEntity(), $user, ['validate' => 'custom']) + ->will($this->returnValue($entityUser)); + + $this->Table->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($entityUser)); + + $result = $this->Behavior->register($this->Table->newEntity(), $user, ['validator' => 'custom', 'validate_email' => 1]); + $this->assertNotEmpty($result->tos_date); } /** * Test register method * - * @expectedException InvalidArgumentException */ public function testValidateRegisterTosRequired() { @@ -124,7 +171,8 @@ public function testValidateRegisterTosRequired() 'first_name' => 'test', 'last_name' => 'user', ]; - $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + $this->assertFalse($result); } /** From d6fc6162fdddb22d3227f77f19f7ddaf4654d6cd Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 25 Aug 2015 16:14:42 -0500 Subject: [PATCH 0206/1476] Use configured table. Fix login template --- src/Shell/UsersShell.php | 20 ++++++++++++++------ src/Template/Users/login.ctp | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 4870cf0d2..2327ea1bf 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -40,7 +40,7 @@ class UsersShell extends Shell public function initialize() { parent::initialize(); - $this->loadModel('Users.Users'); + $this->Users = $this->loadModel(Configure::read('Users.table')); } /** @@ -121,11 +121,19 @@ public function addSuperuser() $userEntity->is_superuser = true; $userEntity->role = 'superuser'; $savedUser = $this->Users->save($userEntity); - $this->out(__d('Users', 'Superuser added:')); - $this->out(__d('Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('Users', 'Username: {0}', $username)); - $this->out(__d('Users', 'Email: {0}', $savedUser->email)); - $this->out(__d('Users', 'Password: {0}', $password)); + if (!empty($savedUser)) { + $this->out(__d('Users', 'Superuser added:')); + $this->out(__d('Users', 'Id: {0}', $savedUser->id)); + $this->out(__d('Users', 'Username: {0}', $username)); + $this->out(__d('Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('Users', 'Password: {0}', $password)); + } else { + $this->out(__d('Users', 'Superuser could not be added:')); + + collection($userEntity->errors())->each(function ($error, $field) { + $this->out(__d('Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); + }); + } } /** diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 591fcc073..927287985 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -41,7 +41,7 @@ use Cake\Core\Configure;

+ if (Configure::read('Users.Social.login')) : ?> User->facebookLogin(); ?> User->twitterLogin(); ?> Date: Wed, 26 Aug 2015 07:02:09 -0430 Subject: [PATCH 0207/1476] refs #224 Changing namespace to CakeDC\Users --- composer.json | 6 +++--- src/Auth/Factory/OpauthFactory.php | 2 +- src/Auth/RememberMeAuthenticate.php | 2 +- src/Auth/SimpleRbacAuthorize.php | 4 ++-- src/Auth/SocialAuthenticate.php | 2 +- src/Auth/SuperuserAuthorize.php | 2 +- src/Controller/AppController.php | 4 ++-- .../Component/RememberMeComponent.php | 2 +- .../Component/UsersAuthComponent.php | 6 +++--- src/Controller/SocialAccountsController.php | 8 ++++---- .../Traits/CustomUsersTableTrait.php | 2 +- src/Controller/Traits/LoginTrait.php | 8 ++++---- .../Traits/PasswordManagementTrait.php | 6 +++--- src/Controller/Traits/ProfileTrait.php | 2 +- src/Controller/Traits/ReCaptchaTrait.php | 2 +- src/Controller/Traits/RegisterTrait.php | 4 ++-- src/Controller/Traits/SimpleCrudTrait.php | 2 +- src/Controller/Traits/SocialTrait.php | 4 ++-- src/Controller/Traits/UserValidationTrait.php | 8 ++++---- src/Controller/UsersController.php | 16 +++++++-------- .../AccountAlreadyActiveException.php | 2 +- src/Exception/AccountNotActiveException.php | 2 +- src/Exception/BadConfigurationException.php | 2 +- src/Exception/MissingEmailException.php | 2 +- src/Exception/TokenExpiredException.php | 2 +- src/Exception/UserAlreadyActiveException.php | 2 +- src/Exception/UserNotFoundException.php | 2 +- src/Exception/WrongPasswordException.php | 2 +- src/Model/Behavior/Behavior.php | 2 +- src/Model/Behavior/PasswordBehavior.php | 10 +++++----- src/Model/Behavior/RegisterBehavior.php | 12 +++++------ src/Model/Behavior/SocialAccountBehavior.php | 12 +++++------ src/Model/Behavior/SocialBehavior.php | 12 +++++------ src/Model/Entity/SocialAccount.php | 2 +- src/Model/Entity/User.php | 2 +- src/Model/Table/SocialAccountsTable.php | 8 ++++---- src/Model/Table/UsersTable.php | 14 ++++++------- src/Shell/UsersShell.php | 4 ++-- src/Test/BaseTraitTest.php | 6 +++--- src/Traits/RandomStringTrait.php | 2 +- src/View/Helper/UserHelper.php | 4 ++-- tests/Fixture/SocialAccountsFixture.php | 2 +- tests/Fixture/UsersFixture.php | 2 +- .../Auth/RememberMeAuthenticateTest.php | 8 ++++---- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 14 ++++++------- .../TestCase/Auth/SuperuserAuthorizeTest.php | 4 ++-- .../Component/RememberMeComponentTest.php | 6 +++--- .../Component/UsersAuthComponentTest.php | 14 ++++++------- .../SocialAccountsControllerTest.php | 6 +++--- .../Traits/CustomUsersTableTraitTest.php | 4 ++-- .../Controller/Traits/LoginTraitTest.php | 18 ++++++++--------- .../Traits/PasswordManagementTraitTest.php | 6 +++--- .../Controller/Traits/ProfileTraitTest.php | 12 +++++------ .../Controller/Traits/RecaptchaTraitTest.php | 4 ++-- .../Controller/Traits/RegisterTraitTest.php | 6 +++--- .../Controller/Traits/SimpleCrudTraitTest.php | 6 +++--- .../Controller/Traits/SocialTraitTest.php | 4 ++-- .../Traits/UserValidationTraitTest.php | 6 +++--- .../Model/Behavior/PasswordBehaviorTest.php | 20 +++++++++---------- .../Model/Behavior/RegisterBehaviorTest.php | 18 ++++++++--------- .../Behavior/SocialAccountBehaviorTest.php | 14 ++++++------- tests/TestCase/Model/Entity/UserTest.php | 4 ++-- .../Model/Table/SocialAccountsTableTest.php | 14 ++++++------- tests/TestCase/Model/Table/UsersTableTest.php | 18 ++++++++--------- tests/TestCase/Shell/UsersShellTest.php | 10 +++++----- .../TestCase/Traits/RandomStringTraitTest.php | 4 ++-- tests/TestCase/View/Helper/UserHelperTest.php | 4 ++-- 67 files changed, 213 insertions(+), 213 deletions(-) diff --git a/composer.json b/composer.json index d8b5834f6..765463bb3 100644 --- a/composer.json +++ b/composer.json @@ -17,13 +17,13 @@ }, "autoload": { "psr-4": { - "Users\\": "src", - "Users\\Test\\Fixture\\": "tests\\Fixture" + "CakeDC\\Users\\": "src", + "CakeDC\\Users\\Test\\Fixture\\": "tests\\Fixture" } }, "autoload-dev": { "psr-4": { - "Users\\Test\\": "tests", + "CakeDC\\Users\\Test\\": "tests", "Cake\\Test\\": "./vendor/cakephp/cakephp/tests" } } diff --git a/src/Auth/Factory/OpauthFactory.php b/src/Auth/Factory/OpauthFactory.php index 6fdfbcd77..15d61abcd 100644 --- a/src/Auth/Factory/OpauthFactory.php +++ b/src/Auth/Factory/OpauthFactory.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Auth\Factory; +namespace CakeDC\Users\Auth\Factory; use Opauth\Opauth\Opauth; diff --git a/src/Auth/RememberMeAuthenticate.php b/src/Auth/RememberMeAuthenticate.php index 5f3c9fc3b..f92cf4582 100644 --- a/src/Auth/RememberMeAuthenticate.php +++ b/src/Auth/RememberMeAuthenticate.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Auth; +namespace CakeDC\Users\Auth; use Cake\Auth\BaseAuthenticate; use Cake\Core\Configure; diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index cbc95d9e1..1a55aadd6 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Auth; +namespace CakeDC\Users\Auth; use Cake\Auth\BaseAuthorize; use Cake\Controller\ComponentRegistry; @@ -77,7 +77,7 @@ class SimpleRbacAuthorize extends BaseAuthorize * @var array */ protected $_defaultPermissions = [ - //admin role allowed to use Users plugin actions + //admin role allowed to use CakeDC\Users plugin actions [ 'role' => 'admin', 'plugin' => '*', diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 480c5c204..80de3834d 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Auth; +namespace CakeDC\Users\Auth; use Cake\Auth\BaseAuthenticate; use Cake\Core\Configure; diff --git a/src/Auth/SuperuserAuthorize.php b/src/Auth/SuperuserAuthorize.php index 8718aa6ba..3a37f24c4 100644 --- a/src/Auth/SuperuserAuthorize.php +++ b/src/Auth/SuperuserAuthorize.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Auth; +namespace CakeDC\Users\Auth; use Cake\Auth\BaseAuthorize; use Cake\Network\Request; diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 802051335..6aa6f5872 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller; +namespace CakeDC\Users\Controller; use App\Controller\AppController as BaseController; @@ -28,6 +28,6 @@ public function initialize() parent::initialize(); $this->loadComponent('Security'); $this->loadComponent('Csrf'); - $this->loadComponent('Users.UsersAuth'); + $this->loadComponent('CakeDC/Users.UsersAuth'); } } diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 3f6da32d1..18f342203 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Component; +namespace CakeDC\Users\Controller\Component; use Cake\Controller\Component; use Cake\Core\Configure; diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 2f92ca44a..131e196ce 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Component; +namespace CakeDC\Users\Controller\Component; use Cake\Controller\Component; use Cake\Core\Configure; @@ -17,7 +17,7 @@ use Cake\Network\Request; use Cake\Routing\Router; use Cake\Utility\Hash; -use Users\Exception\BadConfigurationException; +use CakeDC\Users\Exception\BadConfigurationException; class UsersAuthComponent extends Component { @@ -75,7 +75,7 @@ protected function _loadSocialLogin() */ protected function _loadRememberMe() { - $this->_registry->getController()->loadComponent('Users.RememberMe'); + $this->_registry->getController()->loadComponent('CakeDC/Users.RememberMe'); } /** diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 96473ffd0..2e243b765 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -9,13 +9,13 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller; +namespace CakeDC\Users\Controller; use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Network\Response; -use Users\Controller\AppController; -use Users\Exception\AccountAlreadyActiveException; -use Users\Model\Table\SocialAccountsTable; +use CakeDC\Users\Controller\AppController; +use CakeDC\Users\Exception\AccountAlreadyActiveException; +use CakeDC\Users\Model\Table\SocialAccountsTable; /** * SocialAccounts Controller diff --git a/src/Controller/Traits/CustomUsersTableTrait.php b/src/Controller/Traits/CustomUsersTableTrait.php index 5d6f47866..5a070ac1c 100644 --- a/src/Controller/Traits/CustomUsersTableTrait.php +++ b/src/Controller/Traits/CustomUsersTableTrait.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; use Cake\ORM\Table; diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index f6654fbee..8fe664e70 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -9,12 +9,12 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; -use Users\Controller\Component\UsersAuthComponent; -use Users\Exception\AccountNotActiveException; -use Users\Exception\MissingEmailException; +use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\MissingEmailException; /** * Covers the login, logout and social login diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 994936cd5..b91f3abb8 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -9,12 +9,12 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; use Exception; -use Users\Exception\UserNotFoundException; -use Users\Exception\WrongPasswordException; +use CakeDC\Users\Exception\UserNotFoundException; +use CakeDC\Users\Exception\WrongPasswordException; /** * Covers the password management: reset, change diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 74a3235c2..15f9e1c3d 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; use Cake\Datasource\Exception\InvalidPrimaryKeyException; diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php index 9970105b2..825e410f8 100644 --- a/src/Controller/Traits/ReCaptchaTrait.php +++ b/src/Controller/Traits/ReCaptchaTrait.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; use ReCaptcha\ReCaptcha; diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index db434d78a..416e13828 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -9,14 +9,14 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Network\Exception\NotFoundException; use Cake\Network\Response; use InvalidArgumentException; -use Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Controller\Component\UsersAuthComponent; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index 9bbba9b58..71280f225 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Network\Exception\NotFoundException; use Cake\ORM\TableRegistry; diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 2796065c7..56c1c7fc1 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -9,12 +9,12 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; use Cake\Network\Exception\NotFoundException; use Cake\Routing\Router; -use Users\Auth\Factory\OpauthFactory; +use CakeDC\Users\Auth\Factory\OpauthFactory; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index fa702735f..ed1588e11 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -9,15 +9,15 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller\Traits; +namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; use Cake\Network\Response; use Exception; use InvalidArgumentException; -use Users\Exception\TokenExpiredException; -use Users\Exception\UserAlreadyActiveException; -use Users\Exception\UserNotFoundException; +use CakeDC\Users\Exception\TokenExpiredException; +use CakeDC\Users\Exception\UserAlreadyActiveException; +use CakeDC\Users\Exception\UserNotFoundException; /** * Covers the user validation diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 92255d7e9..1edadd984 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -9,15 +9,15 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Controller; +namespace CakeDC\Users\Controller; -use Users\Controller\AppController; -use Users\Controller\Traits\LoginTrait; -use Users\Controller\Traits\ProfileTrait; -use Users\Controller\Traits\RegisterTrait; -use Users\Controller\Traits\SimpleCrudTrait; -use Users\Controller\Traits\SocialTrait; -use Users\Model\Table\UsersTable; +use CakeDC\Users\Controller\AppController; +use CakeDC\Users\Controller\Traits\LoginTrait; +use CakeDC\Users\Controller\Traits\ProfileTrait; +use CakeDC\Users\Controller\Traits\RegisterTrait; +use CakeDC\Users\Controller\Traits\SimpleCrudTrait; +use CakeDC\Users\Controller\Traits\SocialTrait; +use CakeDC\Users\Model\Table\UsersTable; /** * Users Controller diff --git a/src/Exception/AccountAlreadyActiveException.php b/src/Exception/AccountAlreadyActiveException.php index 227692af2..273c4de05 100644 --- a/src/Exception/AccountAlreadyActiveException.php +++ b/src/Exception/AccountAlreadyActiveException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Exception/AccountNotActiveException.php b/src/Exception/AccountNotActiveException.php index cacc8364b..6e24fba92 100644 --- a/src/Exception/AccountNotActiveException.php +++ b/src/Exception/AccountNotActiveException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Exception/BadConfigurationException.php b/src/Exception/BadConfigurationException.php index 2f8b49602..fb10186c5 100644 --- a/src/Exception/BadConfigurationException.php +++ b/src/Exception/BadConfigurationException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Exception/MissingEmailException.php b/src/Exception/MissingEmailException.php index 33af20c77..85a01881c 100644 --- a/src/Exception/MissingEmailException.php +++ b/src/Exception/MissingEmailException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Exception/TokenExpiredException.php b/src/Exception/TokenExpiredException.php index 39fb94332..7bdae98b5 100644 --- a/src/Exception/TokenExpiredException.php +++ b/src/Exception/TokenExpiredException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Exception/UserAlreadyActiveException.php b/src/Exception/UserAlreadyActiveException.php index 903c58a7e..31c158fdf 100644 --- a/src/Exception/UserAlreadyActiveException.php +++ b/src/Exception/UserAlreadyActiveException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Exception/UserNotFoundException.php b/src/Exception/UserNotFoundException.php index ace72d9c1..a397de051 100644 --- a/src/Exception/UserNotFoundException.php +++ b/src/Exception/UserNotFoundException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Exception; +namespace CakeDC\Users\Exception; use Cake\Datasource\Exception\RecordNotFoundException; diff --git a/src/Exception/WrongPasswordException.php b/src/Exception/WrongPasswordException.php index 03543767e..4edfb90cb 100644 --- a/src/Exception/WrongPasswordException.php +++ b/src/Exception/WrongPasswordException.php @@ -1,6 +1,6 @@ displayField('id'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); - $this->addBehavior('Users.SocialAccount'); + $this->addBehavior('CakeDC/Users.SocialAccount'); } /** diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index fa5af04a1..cd62306a6 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Model\Table; +namespace CakeDC\Users\Model\Table; use Cake\Datasource\EntityInterface; use Cake\Network\Email\Email; @@ -17,8 +17,8 @@ use Cake\ORM\Table; use Cake\Utility\Hash; use Cake\Validation\Validator; -use Users\Exception\WrongPasswordException; -use Users\Model\Entity\User; +use CakeDC\Users\Exception\WrongPasswordException; +use CakeDC\Users\Model\Entity\User; /** * Users Model @@ -47,12 +47,12 @@ public function initialize(array $config) $this->displayField('id'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); - $this->addBehavior('Users.Register'); - $this->addBehavior('Users.Password'); - $this->addBehavior('Users.Social'); + $this->addBehavior('CakeDC/Users.Register'); + $this->addBehavior('CakeDC/Users.Password'); + $this->addBehavior('CakeDC/Users.Social'); $this->hasMany('SocialAccounts', [ 'foreignKey' => 'user_id', - 'className' => 'Users.SocialAccounts' + 'className' => 'CakeDC/Users.SocialAccounts' ]); } diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 4870cf0d2..1f469b408 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -9,13 +9,13 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Shell; +namespace CakeDC\Users\Shell; use Cake\Auth\DefaultPasswordHasher; use Cake\Console\Shell; use Cake\Core\Configure; use Cake\Utility\Hash; -use Users\Model\Entity\User; +use CakeDC\Users\Model\Entity\User; /** * Shell with utilities for the Users Plugin diff --git a/src/Test/BaseTraitTest.php b/src/Test/BaseTraitTest.php index faa725cbe..31925b268 100644 --- a/src/Test/BaseTraitTest.php +++ b/src/Test/BaseTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test; +namespace CakeDC\Users\Test; use Cake\Event\Event; use Cake\ORM\TableRegistry; @@ -24,7 +24,7 @@ abstract class BaseTraitTest extends TestCase * @var array */ public $fixtures = [ - 'plugin.users.users', + 'plugin.CakeDC/Users.users', ]; /** @@ -44,7 +44,7 @@ public function setUp() { parent::setUp(); $traitMockMethods = array_unique(array_merge(['getUsersTable'], $this->traitMockMethods)); - $this->table = TableRegistry::get('Users.Users'); + $this->table = TableRegistry::get('CakeDC/Users.Users'); try { $this->Trait = $this->getMockBuilder($this->traitClassName) ->setMethods($traitMockMethods) diff --git a/src/Traits/RandomStringTrait.php b/src/Traits/RandomStringTrait.php index 6e7916729..470aea671 100644 --- a/src/Traits/RandomStringTrait.php +++ b/src/Traits/RandomStringTrait.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Traits; +namespace CakeDC\Users\Traits; trait RandomStringTrait { diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 2ad9b2f9f..56207a205 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -9,13 +9,13 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\View\Helper; +namespace CakeDC\Users\View\Helper; use Cake\Core\Configure; use Cake\Event\Event; use Cake\Utility\Hash; use Cake\View\Helper; -use Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Controller\Component\UsersAuthComponent; /** * User helper diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 21d9c3c0a..838d3ba0c 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -1,5 +1,5 @@ 'admin', 'plugin' => '*', @@ -97,7 +97,7 @@ public function testConstruct() */ public function testLoadPermissions() { - $this->simpleRbacAuthorize = $this->getMockBuilder('Users\Auth\SimpleRbacAuthorize') + $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') ->disableOriginalConstructor() ->getMock(); $reflectedClass = new ReflectionClass($this->simpleRbacAuthorize); @@ -113,7 +113,7 @@ public function testLoadPermissions() public function testConstructMissingPermissionsFile() { $this->simpleRbacAuthorize = $this->getMock( - 'Users\Auth\SimpleRbacAuthorize', + 'CakeDC\Users\Auth\SimpleRbacAuthorize', null, [$this->registry, ['autoload_config' => 'does-not-exist']] ); @@ -141,7 +141,7 @@ public function testConstructPermissionsFileHappy() 'controller' => 'Test', 'action' => 'test' ]]; - $className = 'Users\Auth\SimpleRbacAuthorize'; + $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; $this->simpleRbacAuthorize = $this->getMockBuilder($className) ->setMethods(['_loadPermissions']) ->disableOriginalConstructor() @@ -156,7 +156,7 @@ public function testConstructPermissionsFileHappy() protected function preparePermissions($permissions) { - $className = 'Users\Auth\SimpleRbacAuthorize'; + $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; $simpleRbacAuthorize = $this->getMockBuilder($className) ->setMethods(['_loadPermissions']) ->disableOriginalConstructor() diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php index 234112a23..ab73fd61f 100644 --- a/tests/TestCase/Auth/SuperuserAuthorizeTest.php +++ b/tests/TestCase/Auth/SuperuserAuthorizeTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Auth; +namespace CakeDC\Users\Test\TestCase\Auth; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; @@ -17,7 +17,7 @@ use Cake\Network\Request; use Cake\Network\Response; use Cake\TestSuite\TestCase; -use Users\Auth\SuperuserAuthorize; +use CakeDC\Users\Auth\SuperuserAuthorize; class SuperuserAuthorizeTest extends TestCase { diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 44ca5bc99..460873ca5 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Component; +namespace CakeDC\Users\Test\TestCase\Controller\Component; use Cake\Controller\ComponentRegistry; use Cake\Controller\Component\AuthComponent; @@ -22,7 +22,7 @@ use Cake\TestSuite\TestCase; use Cake\Utility\Security; use InvalidArgumentException; -use Users\Controller\Component\RememberMeComponent; +use CakeDC\Users\Controller\Component\RememberMeComponent; /** * Users\Controller\Component\RememberMeComponent Test Case @@ -31,7 +31,7 @@ class RememberMeComponentTest extends TestCase { public $fixtures = [ - 'plugin.users.users' + 'plugin.CakeDC/Users.users' ]; /** * setUp method diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 6a2474e49..120cd3359 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Component; +namespace CakeDC\Users\Test\TestCase\Controller\Component; use Cake\Controller\Controller; use Cake\Core\Configure; @@ -21,9 +21,9 @@ use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\Utility\Security; -use Users\Controller\Component\UsersAuthComponent; -use Users\Exception\MissingEmailException; -use Users\Exception\UserNotFoundException; +use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Exception\UserNotFoundException; /** * Users\Controller\Component\UsersAuthComponent Test Case @@ -36,7 +36,7 @@ class UsersAuthComponentTest extends TestCase * @var array */ public $fixtures = [ - 'plugin.users.users', + 'plugin.CakeDC/Users.users', ]; /** @@ -101,7 +101,7 @@ public function testInitialize() { $this->Registry->unload('Auth'); $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); - $this->assertInstanceOf('Users\Controller\Component\UsersAuthComponent', $this->Controller->UsersAuth); + $this->assertInstanceOf('CakeDC\Users\Controller\Component\UsersAuthComponent', $this->Controller->UsersAuth); } /** @@ -111,7 +111,7 @@ public function testInitialize() public function testInitializeNoRequiredRememberMe() { Configure::write('Users.RememberMe.active', false); - $class = 'Users\Controller\Component\UsersAuthComponent'; + $class = 'CakeDC\Users\Controller\Component\UsersAuthComponent'; $this->Controller->UsersAuth = $this->getMockBuilder($class) ->setMethods(['_loadRememberMe', '_initAuth', '_loadSocialLogin', '_attachPermissionChecker']) ->disableOriginalConstructor() diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 48dd6dc79..a5541c240 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller; +namespace CakeDC\Users\Test\TestCase\Controller; use Cake\TestSuite\IntegrationTestCase; @@ -21,8 +21,8 @@ class SocialAccountsControllerTest extends IntegrationTestCase * @var array */ public $fixtures = [ - 'plugin.users.social_accounts', - 'plugin.users.users' + 'plugin.CakeDC/Users.social_accounts', + 'plugin.CakeDC/Users.users' ]; /** diff --git a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php index 8d371c7fd..4657d590c 100644 --- a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php +++ b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\ORM\Table; use Cake\TestSuite\TestCase; @@ -23,7 +23,7 @@ public function setUp() 'Cake\Controller\Controller', ['header', 'redirect', 'render', '_stop'] ); - $this->controller->Trait = $this->getMockForTrait('Users\Controller\Traits\CustomUsersTableTrait'); + $this->controller->Trait = $this->getMockForTrait('CakeDC\Users\Controller\Traits\CustomUsersTableTrait'); } public function tearDown() diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index c15114e1e..73c7b7645 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Controller\Controller; use Cake\Core\Configure; @@ -17,10 +17,10 @@ use Cake\Network\Request; use Cake\TestSuite\TestCase; use Opauth\Opauth\Response; -use Users\Controller\Component\UsersAuthComponent; -use Users\Controller\Traits\LoginTrait; -use Users\Exception\AccountNotActiveException; -use Users\Exception\MissingEmailException; +use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Controller\Traits\LoginTrait; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\MissingEmailException; class LoginTraitTest extends TestCase { @@ -33,7 +33,7 @@ public function setUp() { parent::setUp(); $request = new Request(); - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') ->setMethods(['dispatchEvent', 'redirect']) ->getMockForTrait(); $this->Trait->request = $request; @@ -140,7 +140,7 @@ public function testAfterIdentifyEmptyUser() */ public function testAfterIdentifyEmptyUserSocialLogin() { - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') ->setMethods(['dispatchEvent', 'redirect', '_isSocialLogin']) ->getMockForTrait(); $this->Trait->expects($this->any()) @@ -179,7 +179,7 @@ public function testAfterIdentifyEmptyUserSocialLogin() */ public function testLoginAfterIdentifyAccountNotActive() { - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') ->setMethods(['dispatchEvent', 'redirect', '_afterIdentifyUser']) ->getMockForTrait(); $this->_mockDispatchEvent(new Event('event')); @@ -221,7 +221,7 @@ public function testLoginAfterIdentifyAccountNotActive() */ public function testLoginAfterIdentifyMissingEmailException() { - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\LoginTrait') + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') ->setMethods(['dispatchEvent', 'redirect', '_afterIdentifyUser']) ->getMockForTrait(); $this->_mockDispatchEvent(new Event('event')); diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index a5e9d547e..968fbbf50 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -9,12 +9,12 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Auth\PasswordHasherFactory; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; -use Users\Test\BaseTraitTest; +use CakeDC\Users\Test\BaseTraitTest; class PasswordManagementTraitTest extends BaseTraitTest { @@ -25,7 +25,7 @@ class PasswordManagementTraitTest extends BaseTraitTest */ public function setUp() { - $this->traitClassName = 'Users\Controller\Traits\PasswordManagementTrait'; + $this->traitClassName = 'CakeDC\Users\Controller\Traits\PasswordManagementTrait'; $this->traitMockMethods = ['set', 'redirect', 'validate']; parent::setUp(); } diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index 503813969..be57972aa 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -9,11 +9,11 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\ORM\TableRegistry; -use Users\Controller\Traits\ProfileTrait; -use Users\Test\BaseTraitTest; +use CakeDC\Users\Controller\Traits\ProfileTrait; +use CakeDC\Users\Test\BaseTraitTest; class ProfileTraitTest extends BaseTraitTest { @@ -23,8 +23,8 @@ class ProfileTraitTest extends BaseTraitTest * @var array */ public $fixtures = [ - 'plugin.users.users', - 'plugin.users.social_accounts', + 'plugin.CakeDC/Users.users', + 'plugin.CakeDC/Users.social_accounts', ]; /** @@ -34,7 +34,7 @@ class ProfileTraitTest extends BaseTraitTest */ public function setUp() { - $this->traitClassName = 'Users\Controller\Traits\ProfileTrait'; + $this->traitClassName = 'CakeDC\Users\Controller\Traits\ProfileTrait'; $this->traitMockMethods = ['set', 'getUsersTable', 'redirect', 'validate']; parent::setUp(); } diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php index 34c2472b4..655e83c18 100644 --- a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php +++ b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\TestSuite\TestCase; @@ -23,7 +23,7 @@ class ReCaptchaTraitTest extends TestCase public function setUp() { parent::setUp(); - $this->Trait = $this->getMockBuilder('Users\Controller\Traits\ReCaptchaTrait') + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait') ->setMethods(['_getReCaptchaInstance']) ->getMockForTrait(); } diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index da58f8b61..2cf474d5c 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -9,11 +9,11 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Core\Configure; use Cake\ORM\TableRegistry; -use Users\Test\BaseTraitTest; +use CakeDC\Users\Test\BaseTraitTest; class RegisterTraitTest extends BaseTraitTest { @@ -24,7 +24,7 @@ class RegisterTraitTest extends BaseTraitTest */ public function setUp() { - $this->traitClassName = 'Users\Controller\Traits\RegisterTrait'; + $this->traitClassName = 'CakeDC\Users\Controller\Traits\RegisterTrait'; $this->traitMockMethods = ['validate', 'dispatchEvent', 'set', 'validateReCaptcha', 'redirect']; parent::setUp(); } diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 17a877a56..abbdf2b10 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -9,10 +9,10 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Network\Request; -use Users\Test\BaseTraitTest; +use CakeDC\Users\Test\BaseTraitTest; class SimpleCrudTraitTest extends BaseTraitTest { @@ -25,7 +25,7 @@ class SimpleCrudTraitTest extends BaseTraitTest */ public function setUp() { - $this->traitClassName = 'Users\Controller\Traits\SimpleCrudTrait'; + $this->traitClassName = 'CakeDC\Users\Controller\Traits\SimpleCrudTrait'; $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set', 'loadModel', 'paginate']; parent::setUp(); $viewVarsContainer = $this; diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index a7e3708a3..cb71ac66d 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Core\Configure; use Cake\TestSuite\TestCase; @@ -24,7 +24,7 @@ public function setUp() ['header', 'redirect', 'render', '_stop'] ); $this->controller->Trait = $this->getMockForTrait( - 'Users\Controller\Traits\SocialTrait', + 'CakeDC\Users\Controller\Traits\SocialTrait', [], '', true, diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 0449a59cc..fdadf0cac 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -9,10 +9,10 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Controller\Traits; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Network\Request; -use Users\Test\BaseTraitTest; +use CakeDC\Users\Test\BaseTraitTest; class UserValidationTraitTest extends BaseTraitTest { @@ -23,7 +23,7 @@ class UserValidationTraitTest extends BaseTraitTest */ public function setUp() { - $this->traitClassName = 'Users\Controller\Traits\UserValidationTrait'; + $this->traitClassName = 'CakeDC\Users\Controller\Traits\UserValidationTrait'; $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; parent::setUp(); } diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index c03fc4a35..ca111abdc 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -9,13 +9,13 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Model\Behavior; +namespace CakeDC\Users\Test\TestCase\Model\Behavior; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use InvalidArgumentException; -use Users\Exception\UserAlreadyActiveException; -use Users\Model\Table\UsersTable; +use CakeDC\Users\Exception\UserAlreadyActiveException; +use CakeDC\Users\Model\Table\UsersTable; /** * Test Case @@ -28,7 +28,7 @@ class PasswordBehaviorTest extends TestCase * @var array */ public $fixtures = [ - 'plugin.users.users', + 'plugin.CakeDC/Users.users', ]; /** @@ -39,8 +39,8 @@ class PasswordBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $this->table = TableRegistry::get('Users.Users'); - $this->Behavior = $this->getMockBuilder('Users\Model\Behavior\PasswordBehavior') + $this->table = TableRegistry::get('CakeDC/Users.Users'); + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\PasswordBehavior') ->setMethods(['sendResetPasswordEmail']) ->setConstructorArgs([$this->table]) ->getMock(); @@ -113,7 +113,7 @@ public function testResetTokenWithNullParams() /** * Test resetToken * - * @expectedException Users\Exception\UserNotFoundException + * @expectedException CakeDC\Users\Exception\UserNotFoundException */ public function testResetTokenNotExistingUser() { @@ -125,13 +125,13 @@ public function testResetTokenNotExistingUser() /** * Test resetToken * - * @expectedException Users\Exception\UserAlreadyActiveException + * @expectedException CakeDC\Users\Exception\UserAlreadyActiveException */ public function testResetTokenUserAlreadyActive() { - $activeUser = TableRegistry::get('Users.Users')->findAllByUsername('user-4')->first(); + $activeUser = TableRegistry::get('CakeDC/Users.Users')->findAllByUsername('user-4')->first(); $this->assertTrue($activeUser->active); - $this->table = $this->getMockForModel('Users.Users', ['save']); + $this->table = $this->getMockForModel('CakeDC/Users.Users', ['save']); $this->table->expects($this->never()) ->method('save'); $this->Behavior->expects($this->never()) diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 1070984ed..fbe07240c 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Model\Behavior; +namespace CakeDC\Users\Test\TestCase\Model\Behavior; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; @@ -26,7 +26,7 @@ class RegisterBehaviorTest extends TestCase * @var array */ public $fixtures = [ - 'plugin.users.users', + 'plugin.CakeDC/Users.users', ]; /** @@ -37,8 +37,8 @@ class RegisterBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $table = TableRegistry::get('Users.Users'); - $table->addBehavior('Users/Register.Register'); + $table = TableRegistry::get('CakeDC/Users.Users'); + $table->addBehavior('CakeDC/Users/Register.Register'); $this->Table = $table; $this->Behavior = $table->behaviors()->Register; @@ -117,9 +117,9 @@ public function testValidateRegisterValidateEmailAndTos() */ public function testValidateRegisterValidatorOption() { - $this->Table = $this->getMockForModel('Users.Users', ['validationCustom', 'patchEntity', 'errors', 'save']); + $this->Table = $this->getMockForModel('CakeDC/Users.Users', ['validationCustom', 'patchEntity', 'errors', 'save']); - $this->Behavior = $this->getMockBuilder('Users\Model\Behavior\RegisterBehavior') + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') ->setMethods(['getValidators', '_updateActive']) ->setConstructorArgs([$this->Table]) ->getMock(); @@ -222,7 +222,7 @@ public function testValidate() * Test Validate method * * @return void - * @expectedException \Users\Exception\TokenExpiredException + * @expectedException CakeDC\Users\Exception\TokenExpiredException */ public function testValidateUserWithExpiredToken() { @@ -233,7 +233,7 @@ public function testValidateUserWithExpiredToken() * Test Validate method * * @return void - * @expectedException \Users\Exception\UserNotFoundException + * @expectedException CakeDC\Users\Exception\UserNotFoundException */ public function testValidateNotExistingUser() { @@ -248,7 +248,7 @@ public function testValidateNotExistingUser() public function testActiveUserRemoveValidationToken() { $user = $this->Table->find()->where(['id' => 1])->first(); - $this->Behavior = $this->getMockBuilder('Users\Model\Behavior\RegisterBehavior') + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') ->setMethods(['_removeValidationToken']) ->setConstructorArgs([$this->Table]) ->getMock(); diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index 22614c95c..f3e853787 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -9,13 +9,13 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Model\Behavior; +namespace CakeDC\Users\Test\TestCase\Model\Behavior; use Cake\Event\Event; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use InvalidArgumentException; -use Users\Model\Table\SocialAccountsTable; +use CakeDC\Users\Model\Table\SocialAccountsTable; /** * Test Case @@ -28,8 +28,8 @@ class SocialAccountBehaviorTest extends TestCase * @var array */ public $fixtures = [ - 'plugin.users.social_accounts', - 'plugin.users.users' + 'plugin.CakeDC/Users.social_accounts', + 'plugin.CakeDC/Users.users' ]; /** @@ -40,8 +40,8 @@ class SocialAccountBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $table = TableRegistry::get('Users.SocialAccounts'); - $table->addBehavior('Users.SocialAccount'); + $table = TableRegistry::get('CakeDC/Users.SocialAccounts'); + $table->addBehavior('CakeDC/Users.SocialAccount'); $this->Table = $table; $this->Behavior = $table->behaviors()->SocialAccount; } @@ -93,7 +93,7 @@ public function testValidateEmailInvalidUser() /** * Test validateEmail method * - * @expectedException \Users\Exception\AccountAlreadyActiveException + * @expectedException CakeDC\Users\Exception\AccountAlreadyActiveException */ public function testValidateEmailActiveAccount() { diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index c594367a2..00f4f89c6 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -1,9 +1,9 @@ 'Users\Model\Table\SocialAccountsTable' + 'className' => 'CakeDC\Users\Model\Table\SocialAccountsTable' ]; $this->SocialAccounts = TableRegistry::get('SocialAccounts', $config); $this->fullBaseBackup = Router::fullBaseUrl(); @@ -81,7 +81,7 @@ public function testAfterSaveSocialNotActiveUserActive() $this->markTestIncomplete('fix this test after SocialBehavior done'); $event = new Event('eventName'); $entity = $this->SocialAccounts->findById(5)->first(); - $this->SocialAccounts->Users = $this->getMockForModel('Users.Users', ['getEmailInstance']); + $this->SocialAccounts->Users = $this->getMockForModel('CakeDC/Users.Users', ['getEmailInstance']); $this->SocialAccounts->Users->expects($this->once()) ->method('getEmailInstance') ->will($this->returnValue($this->Email)); diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 2a45847f4..1348e0c28 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Model\Table; +namespace CakeDC\Users\Test\TestCase\Model\Table; use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; @@ -17,10 +17,10 @@ use Cake\TestSuite\TestCase; use InvalidArgumentException; use Opauth\Opauth\Response; -use Users\Exception\AccountNotActiveException; -use Users\Exception\UserAlreadyActiveException; -use Users\Exception\UserNotFoundException; -use Users\Model\Table\SocialAccountsTable; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\UserAlreadyActiveException; +use CakeDC\Users\Exception\UserNotFoundException; +use CakeDC\Users\Model\Table\SocialAccountsTable; /** * Users\Model\Table\UsersTable Test Case @@ -34,8 +34,8 @@ class UsersTableTest extends TestCase * @var array */ public $fixtures = [ - 'plugin.users.users', - 'plugin.users.social_accounts' + 'plugin.CakeDC/Users.users', + 'plugin.CakeDC/Users.social_accounts' ]; /** @@ -46,7 +46,7 @@ class UsersTableTest extends TestCase public function setUp() { parent::setUp(); - $this->Users = TableRegistry::get('Users.Users'); + $this->Users = TableRegistry::get('CakeDC/Users.Users'); $this->fullBaseBackup = Router::fullBaseUrl(); Router::fullBaseUrl('http://users.test'); Email::configTransport('test', [ @@ -114,7 +114,7 @@ public function testSocialLogin() /** * Test socialLogin * - * @expectedException \Users\Exception\AccountNotActiveException + * @expectedException CakeDC\Users\Exception\AccountNotActiveException */ public function testSocialLoginInactiveAccount() { diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 3236581f9..89176be30 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Shell; +namespace CakeDC\Users\Test\TestCase\Shell; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOutput; @@ -24,7 +24,7 @@ class UsersShellTest extends TestCase * @var array */ public $fixtures = [ - 'plugin.users.users', + 'plugin.CakeDC/Users.users', ]; /** @@ -37,15 +37,15 @@ public function setUp() parent::setUp(); $this->out = new ConsoleOutput(); $this->io = new ConsoleIo($this->out); - $this->Users = TableRegistry::get('Users.Users'); + $this->Users = TableRegistry::get('CakeDC/Users.Users'); - $this->Shell = $this->getMockBuilder('Users\Shell\UsersShell') + $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', '_generateRandomUsername', '_generatedHashedPassword', 'error']) ->setConstructorArgs([$this->io]) ->getMock(); - $this->Shell->Users = $this->getMockBuilder('Users\Model\UsersTable') + $this->Shell->Users = $this->getMockBuilder('CakeDC\Users\Model\UsersTable') ->setMethods(['generateUniqueUsername', 'newEntity', 'save', 'updateAll']) ->getMock(); diff --git a/tests/TestCase/Traits/RandomStringTraitTest.php b/tests/TestCase/Traits/RandomStringTraitTest.php index eaeb3596c..58324c67b 100644 --- a/tests/TestCase/Traits/RandomStringTraitTest.php +++ b/tests/TestCase/Traits/RandomStringTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\Traits; +namespace CakeDC\Users\Test\TestCase\Traits; use Cake\TestSuite\TestCase; @@ -18,7 +18,7 @@ class RandomStringTraitTest extends TestCase public function setUp() { parent::setUp(); - $this->Trait = $this->getMockForTrait('Users\Traits\RandomStringTrait'); + $this->Trait = $this->getMockForTrait('CakeDC\Users\Traits\RandomStringTrait'); } public function tearDown() diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 739a0c2a0..6ed93c1ba 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace Users\Test\TestCase\View\Helper; +namespace CakeDC\Users\Test\TestCase\View\Helper; use Cake\Core\Configure; use Cake\Event\Event; @@ -17,7 +17,7 @@ use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\View\View; -use Users\View\Helper\UserHelper; +use CakeDC\Users\View\Helper\UserHelper; /** * Users\View\Helper\UserHelper Test Case From 8239ec41f8862b9effd796241d06703d8cf4005a Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Thu, 27 Aug 2015 14:25:46 -0500 Subject: [PATCH 0208/1476] Override loadModel --- src/Controller/UsersController.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 92255d7e9..74756918c 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -11,6 +11,7 @@ namespace Users\Controller; +use Cake\Core\Configure; use Users\Controller\AppController; use Users\Controller\Traits\LoginTrait; use Users\Controller\Traits\ProfileTrait; @@ -31,4 +32,15 @@ class UsersController extends AppController use RegisterTrait; use SimpleCrudTrait; use SocialTrait; + + /** + * Override loadModel to load specific users table + * @param null $modelClass + * @param string $type + * @return object + */ + public function loadModel($modelClass = null, $type = 'Table') + { + return parent::loadModel(Configure::read('Users.table')); + } } From 165e66b010bcd0e9fe45a7eba9b196250a6a1ddc Mon Sep 17 00:00:00 2001 From: Andrej Date: Sun, 30 Aug 2015 20:53:01 +1000 Subject: [PATCH 0209/1476] opauth complete url fix --- src/Controller/Traits/SocialTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 2796065c7..a497c28c3 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -54,7 +54,7 @@ protected function _generateOpauthCompleteUrl() $url = Router::parse($url); } $url['?'] = ['social' => $this->request->query('code')]; - return Router::url($url); + return Router::url($url, true); } /** From a47a3f28d6c2ab48c032fe874dbeb397063a5d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 19:46:27 +0100 Subject: [PATCH 0210/1476] refs #fixcs fix phpcs --- src/Model/Behavior/RegisterBehavior.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index a7e162e8e..03d8da5b1 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -116,9 +116,17 @@ public function activateUser(EntityInterface $user) return $result; } + /** + * buildValidator + * + * @param Event $event event + * @param Validator $validator validator + * @param string $name name + * @return Validator + */ public function buildValidator(Event $event, Validator $validator, $name){ - if ($name == 'default') { - $this->_emailValidator($validator, $this->validateEmail); + if ($name === 'default') { + return $this->_emailValidator($validator, $this->validateEmail); } } @@ -126,7 +134,7 @@ public function buildValidator(Event $event, Validator $validator, $name){ * Email validator * * @param Validator $validator Validator instance. - * @param $validateEmail true when email needs to be required + * @param bool $validateEmail true when email needs to be required * @return Validator */ protected function _emailValidator(Validator $validator, $validateEmail) @@ -175,6 +183,5 @@ protected function _getValidators($options) $validator = $this->_emailValidator($validator, $validateEmail); } return $validator; - } } From 36a6e2b5e61940258e20d988b4d806950626f813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 20:17:05 +0100 Subject: [PATCH 0211/1476] refs #224 move BaseTraitTest to tests --- .../TestCase/Controller/Traits/PasswordManagementTraitTest.php | 2 +- tests/TestCase/Controller/Traits/ProfileTraitTest.php | 2 +- tests/TestCase/Controller/Traits/RegisterTraitTest.php | 2 +- tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php | 2 +- tests/TestCase/Controller/Traits/UserValidationTraitTest.php | 2 +- {src/Test => tests/Util}/BaseTraitTest.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename {src/Test => tests/Util}/BaseTraitTest.php (99%) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 968fbbf50..4fa26870e 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use CakeDC\Users\Test\Util\BaseTraitTest; use Cake\Auth\PasswordHasherFactory; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; -use CakeDC\Users\Test\BaseTraitTest; class PasswordManagementTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index be57972aa..7f0743a22 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -13,7 +13,7 @@ use Cake\ORM\TableRegistry; use CakeDC\Users\Controller\Traits\ProfileTrait; -use CakeDC\Users\Test\BaseTraitTest; +use CakeDC\Users\Test\Util\BaseTraitTest; class ProfileTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 2cf474d5c..1e6e6936a 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -13,7 +13,7 @@ use Cake\Core\Configure; use Cake\ORM\TableRegistry; -use CakeDC\Users\Test\BaseTraitTest; +use CakeDC\Users\Test\Util\BaseTraitTest; class RegisterTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index abbdf2b10..79e93d77a 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Network\Request; -use CakeDC\Users\Test\BaseTraitTest; +use CakeDC\Users\Test\Util\BaseTraitTest; class SimpleCrudTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index fdadf0cac..1581076af 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Network\Request; -use CakeDC\Users\Test\BaseTraitTest; +use CakeDC\Users\Test\Util\BaseTraitTest; class UserValidationTraitTest extends BaseTraitTest { diff --git a/src/Test/BaseTraitTest.php b/tests/Util/BaseTraitTest.php similarity index 99% rename from src/Test/BaseTraitTest.php rename to tests/Util/BaseTraitTest.php index 31925b268..c6abd1d27 100644 --- a/src/Test/BaseTraitTest.php +++ b/tests/Util/BaseTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test; +namespace CakeDC\Users\Test\Util; use Cake\Event\Event; use Cake\ORM\TableRegistry; From b969f96f140a2c881eaef969926a13a834749453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 20:17:37 +0100 Subject: [PATCH 0212/1476] refs #224 cleanup composers autoload --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 765463bb3..66a174712 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,7 @@ }, "autoload": { "psr-4": { - "CakeDC\\Users\\": "src", - "CakeDC\\Users\\Test\\Fixture\\": "tests\\Fixture" + "CakeDC\\Users\\": "src" } }, "autoload-dev": { From 4cac3328d02873e49a385fa5f6ad7f25d7eccca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 20:43:22 +0100 Subject: [PATCH 0213/1476] refs #224 move BaseTraitTest --- tests/{Util => TestCase/Controller/Traits}/BaseTraitTest.php | 2 +- .../TestCase/Controller/Traits/PasswordManagementTraitTest.php | 2 +- tests/TestCase/Controller/Traits/ProfileTraitTest.php | 2 +- tests/TestCase/Controller/Traits/RegisterTraitTest.php | 2 +- tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php | 2 +- tests/TestCase/Controller/Traits/UserValidationTraitTest.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename tests/{Util => TestCase/Controller/Traits}/BaseTraitTest.php (98%) diff --git a/tests/Util/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php similarity index 98% rename from tests/Util/BaseTraitTest.php rename to tests/TestCase/Controller/Traits/BaseTraitTest.php index c6abd1d27..03755e301 100644 --- a/tests/Util/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\Util; +namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Event\Event; use Cake\ORM\TableRegistry; diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 4fa26870e..60db6a850 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -11,7 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Test\Util\BaseTraitTest; +use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; use Cake\Auth\PasswordHasherFactory; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index 7f0743a22..e9b6c9222 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -13,7 +13,7 @@ use Cake\ORM\TableRegistry; use CakeDC\Users\Controller\Traits\ProfileTrait; -use CakeDC\Users\Test\Util\BaseTraitTest; +use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; class ProfileTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 1e6e6936a..635c95fd6 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -13,7 +13,7 @@ use Cake\Core\Configure; use Cake\ORM\TableRegistry; -use CakeDC\Users\Test\Util\BaseTraitTest; +use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; class RegisterTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 79e93d77a..969ccfdeb 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Network\Request; -use CakeDC\Users\Test\Util\BaseTraitTest; +use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; class SimpleCrudTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 1581076af..321c03573 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Network\Request; -use CakeDC\Users\Test\Util\BaseTraitTest; +use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; class UserValidationTraitTest extends BaseTraitTest { From f70983669c225fe2db1baeb6fc4f18bd866e1f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 20:56:23 +0100 Subject: [PATCH 0214/1476] refs #224 fix template location --- src/Model/Behavior/PasswordBehavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 4022023bd..b101610d0 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -91,7 +91,7 @@ public function sendResetPasswordEmail(EntityInterface $user, Email $email = nul $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $subject = __d('Users', '{0}Your reset password link', $firstName); return $this->_getEmailInstance($email) - ->template('Users.reset_password') + ->template('CakeDC/Users.reset_password') ->to($user['email']) ->subject($subject) ->viewVars($user->toArray()) From cad5f25275af68f9aa2044fe035b727a0414ef1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 20:57:51 +0100 Subject: [PATCH 0215/1476] refs #224 start fixing the test bootstrap --- config/bootstrap.php | 2 +- tests/bootstrap.php | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 096267b8e..069ec6f16 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -11,7 +11,7 @@ use Cake\Core\Configure; -Configure::load('Users.users'); +Configure::load('CakeDC/Users.users'); collection((array)Configure::read('Users.config'))->each(function ($file) { Configure::load($file); }); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index a5151b4d1..b72bb4d83 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,10 +1,6 @@ dirname(dirname(__FILE__)) . DS]); if (file_exists($root . '/config/bootstrap.php')) { require $root . '/config/bootstrap.php'; - return; } -require dirname(__DIR__) . '/vendor/cakephp/cakephp/tests/bootstrap.php'; From d9de6758d40de2e83e100be635700c455f267de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 21:13:58 +0100 Subject: [PATCH 0216/1476] refs #224 fix email unit tests, add Email injection in register --- src/Model/Behavior/RegisterBehavior.php | 3 +- .../Model/Behavior/RegisterBehaviorTest.php | 59 ++++++++++--------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index c177786ce..4c8637a58 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -56,6 +56,7 @@ public function register($user, $data, $options) { $validateEmail = Hash::get($options, 'validate_email'); $tokenExpiration = Hash::get($options, 'token_expiration'); + $emailClass = Hash::get($options, 'email_class'); $user = $this->_table->patchEntity($user, $data, ['validate' => Hash::get($options, 'validator') ?: $this->_getValidators($options)]); $user->validated = false; //@todo move updateActive to afterSave? @@ -63,7 +64,7 @@ public function register($user, $data, $options) $this->_table->isValidateEmail = $validateEmail; $userSaved = $this->_table->save($user); if ($userSaved && $validateEmail) { - $this->_sendEmail($user, __d('Users', 'Your account validation link')); + $this->_sendEmail($user, __d('Users', 'Your account validation link'), $emailClass); } return $userSaved; } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index fbe07240c..19bb55e2c 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -1,4 +1,5 @@ addBehavior('CakeDC/Users/Register.Register'); $this->Table = $table; $this->Behavior = $table->behaviors()->Register; - + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); } /** @@ -52,16 +58,16 @@ public function setUp() public function tearDown() { unset($this->Table, $this->Behavior); + Email::dropTransport('test'); parent::tearDown(); } - /** * Test register method * * @return void */ - public function testValidateRegisterNoValidateEmail() + public function testValidateRegisterNoValidateEmail() { $user = [ 'username' => 'testuser', @@ -72,7 +78,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->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0, 'email_class' => $this->Email]); $this->assertTrue($result->active); } @@ -84,7 +90,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->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); $this->assertFalse($result); } @@ -104,7 +110,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->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); $this->assertNotEmpty($result); $this->assertFalse($result->active); $this->assertNotEmpty($result->tos_date); @@ -120,9 +126,9 @@ public function testValidateRegisterValidatorOption() $this->Table = $this->getMockForModel('CakeDC/Users.Users', ['validationCustom', 'patchEntity', 'errors', 'save']); $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') - ->setMethods(['getValidators', '_updateActive']) - ->setConstructorArgs([$this->Table]) - ->getMock(); + ->setMethods(['getValidators', '_updateActive']) + ->setConstructorArgs([$this->Table]) + ->getMock(); $user = [ 'username' => 'testuser', @@ -135,25 +141,25 @@ public function testValidateRegisterValidatorOption() ]; $this->Behavior->expects($this->never()) - ->method('getValidators'); + ->method('getValidators'); $entityUser = $this->Table->newEntity($user); $this->Behavior->expects($this->once()) - ->method('_updateActive') - ->will($this->returnValue($entityUser)); + ->method('_updateActive') + ->will($this->returnValue($entityUser)); $this->Table->expects($this->once()) - ->method('patchEntity') - ->with($this->Table->newEntity(), $user, ['validate' => 'custom']) - ->will($this->returnValue($entityUser)); + ->method('patchEntity') + ->with($this->Table->newEntity(), $user, ['validate' => 'custom']) + ->will($this->returnValue($entityUser)); $this->Table->expects($this->once()) - ->method('save') - ->with($entityUser) - ->will($this->returnValue($entityUser)); + ->method('save') + ->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->newEntity(), $user, ['validator' => 'custom', 'validate_email' => 1, 'email_class' => $this->Email]); $this->assertNotEmpty($result->tos_date); } @@ -171,7 +177,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->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1, 'email_class' => $this->Email]); $this->assertFalse($result); } @@ -190,7 +196,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->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0, 'email_class' => $this->Email]); $this->assertNotEmpty($result); } @@ -249,19 +255,18 @@ public function testActiveUserRemoveValidationToken() { $user = $this->Table->find()->where(['id' => 1])->first(); $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') - ->setMethods(['_removeValidationToken']) - ->setConstructorArgs([$this->Table]) - ->getMock(); + ->setMethods(['_removeValidationToken']) + ->setConstructorArgs([$this->Table]) + ->getMock(); $resultValidationToken = $user; $resultValidationToken->token_expires = null; $resultValidationToken->token = null; $this->Behavior->expects($this->once()) - ->method('_removeValidationToken') - ->will($this->returnValue($resultValidationToken)); + ->method('_removeValidationToken') + ->will($this->returnValue($resultValidationToken)); $this->Behavior->activateUser($user); } - } From 802bbd66c82dabea11108d96bae0a6bd909b1ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 31 Aug 2015 21:44:53 +0100 Subject: [PATCH 0217/1476] refs #refactor-behavior mock router --- .../Component/RememberMeComponentTest.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 460873ca5..6f453f6fa 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -44,8 +44,11 @@ public function setUp() Security::salt('2a20bac195a9eb2e28f05b7ac7090afe599365a8fe480b7d8a5ce0f79687346e'); $this->request = new Request('controller_posts/index'); $this->request->params['pass'] = []; - $controller = new Controller($this->request); - $this->registry = new ComponentRegistry($controller); + $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, []); } @@ -150,8 +153,10 @@ public function testBeforeFilter() $this->rememberMeComponent->Auth->expects($this->once()) ->method('redirectUrl') ->will($this->returnValue('/login')); - $response = $this->rememberMeComponent->beforeFilter($event); - $this->assertSame(Router::url('/login', true), $response->location()); + $this->controller->expects($this->once()) + ->method('redirect') + ->with('/login'); + $this->rememberMeComponent->beforeFilter($event); } /** From 571cc21a91f290ea7f0d191aff8b8aede54c054b Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 1 Sep 2015 18:22:09 -0430 Subject: [PATCH 0218/1476] WIP routes fix --- tests/bootstrap.php | 7 +++++++ tests/config/routes.php | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/config/routes.php diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b72bb4d83..fcc01dbd8 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -6,6 +6,7 @@ * has been installed as a dependency of the plugin, or the plugin is itself * installed as a dependency of an application. */ + $findRoot = function ($root) { do { $lastRoot = $root; @@ -19,8 +20,14 @@ $root = $findRoot(__FILE__); unset($findRoot); chdir($root); + +define('CONFIG', $root . '/tests/config/'); + require $root . '/vendor/cakephp/cakephp/tests/bootstrap.php'; \Cake\Core\Plugin::load('CakeDC/Users', ['path' => dirname(dirname(__FILE__)) . DS]); + + if (file_exists($root . '/config/bootstrap.php')) { require $root . '/config/bootstrap.php'; } + diff --git a/tests/config/routes.php b/tests/config/routes.php new file mode 100644 index 000000000..faec0701e --- /dev/null +++ b/tests/config/routes.php @@ -0,0 +1,32 @@ +fallbacks('DashedRoute'); + }); + +Router::scope('/auth', function ($routes) { + $routes->connect( + '/*', + Configure::read('Opauth.path') + ); + }); +Router::connect('/accounts/validate/*', [ + 'plugin' => 'Users', + 'controller' => 'SocialAccounts', + 'action' => 'validate' + ]); +Router::connect('/profile/*', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); +Router::connect('/login', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); +Router::connect('/logout', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout']); From 3be1b3c788c5d932febc5a2c194f56b7379e4de9 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 1 Sep 2015 23:57:55 -0430 Subject: [PATCH 0219/1476] Including routes filter --- tests/bootstrap.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index fcc01dbd8..0243da08f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -7,6 +7,10 @@ * installed as a dependency of an application. */ +use Cake\Core\Configure; +use Cake\Routing\DispatcherFactory; +use Cake\Routing\Filter\ControllerFactory; + $findRoot = function ($root) { do { $lastRoot = $root; @@ -24,10 +28,18 @@ define('CONFIG', $root . '/tests/config/'); require $root . '/vendor/cakephp/cakephp/tests/bootstrap.php'; -\Cake\Core\Plugin::load('CakeDC/Users', ['path' => dirname(dirname(__FILE__)) . DS]); +\Cake\Core\Plugin::load('CakeDC/Users', [ + 'path' => dirname(dirname(__FILE__)) . DS, + ]); if (file_exists($root . '/config/bootstrap.php')) { require $root . '/config/bootstrap.php'; } +/** + * Connect middleware/dispatcher filters. + */ +DispatcherFactory::add('Routing'); +DispatcherFactory::add('ControllerFactory'); + From 85796a239d4a8670e14baf752f5eec02fa42b6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 2 Sep 2015 14:23:34 +0100 Subject: [PATCH 0220/1476] refs #refactor-behavior fix config load --- config/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 069ec6f16..096267b8e 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -11,7 +11,7 @@ use Cake\Core\Configure; -Configure::load('CakeDC/Users.users'); +Configure::load('Users.users'); collection((array)Configure::read('Users.config'))->each(function ($file) { Configure::load($file); }); From 236c2563da1ffb763190abee340d3864ca77f4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 3 Sep 2015 13:06:20 +0100 Subject: [PATCH 0221/1476] refs #refactor-behavior fix SocialAccountsControllerTests to use unit tests instead od integration tests. Fix all references to plugin Users to include CakeDC/ vendor prefix --- Docs/Documentation/SocialAuthenticate.md | 6 +- composer.json | 3 +- config/bootstrap.php | 2 +- config/permissions.php | 6 +- config/routes.php | 10 +- config/users.php | 8 +- src/Auth/SimpleRbacAuthorize.php | 2 +- src/Controller/SocialAccountsController.php | 4 +- src/Model/Behavior/Behavior.php | 2 +- src/Template/Email/html/reset_password.ctp | 2 +- .../Email/html/social_account_validation.ctp | 2 +- src/Template/Email/html/validation.ctp | 2 +- src/Template/Email/text/reset_password.ctp | 2 +- .../Email/text/social_account_validation.ctp | 2 +- src/Template/Email/text/validation.ctp | 2 +- src/Template/Users/profile.ctp | 2 +- src/View/Helper/UserHelper.php | 2 +- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 2 +- .../Component/UsersAuthComponentTest.php | 10 +- .../SocialAccountsControllerTest.php | 149 +++++++++++++++--- .../Traits/PasswordManagementTraitTest.php | 2 +- tests/TestCase/Model/Table/UsersTableTest.php | 4 +- 22 files changed, 161 insertions(+), 65 deletions(-) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index 2076b637b..6bcfefe20 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -49,9 +49,9 @@ Configure::write('Users', [ 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). ``` Configure::write('Opauth', [ - 'path' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit'], - 'callback_url' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit', 'callback'], - 'complete_url' => ['admin' => false, 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'login'], + 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'opauthInit'], + 'callback_url' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'opauthInit', 'callback'], + 'complete_url' => ['admin' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], 'Strategy' => [ 'Facebook' => [ 'scope' => ['public_profile', 'user_friends', 'email'] diff --git a/composer.json b/composer.json index 66a174712..c56a09446 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,7 @@ }, "autoload-dev": { "psr-4": { - "CakeDC\\Users\\Test\\": "tests", - "Cake\\Test\\": "./vendor/cakephp/cakephp/tests" + "CakeDC\\Users\\Test\\": "tests" } } } diff --git a/config/bootstrap.php b/config/bootstrap.php index 096267b8e..069ec6f16 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -11,7 +11,7 @@ use Cake\Core\Configure; -Configure::load('Users.users'); +Configure::load('CakeDC/Users.users'); collection((array)Configure::read('Users.config'))->each(function ($file) { Configure::load($file); }); diff --git a/config/permissions.php b/config/permissions.php index 2c0be29c2..1b76eed6c 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -52,19 +52,19 @@ 'Users.SimpleRbac.permissions' => [ [ 'role' => '*', - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => '*', 'action' => '*', ], [ 'role' => 'user', - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => ['register', 'edit', 'view'], ], [ 'role' => 'user', - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => '*', 'allowed' => false, diff --git a/config/routes.php b/config/routes.php index e8a05ecc2..61086c566 100644 --- a/config/routes.php +++ b/config/routes.php @@ -12,7 +12,7 @@ use Cake\Core\Configure; use Cake\Routing\Router; -Router::plugin('Users', function ($routes) { +Router::plugin('CakeDC/Users', function ($routes) { $routes->fallbacks('DashedRoute'); }); @@ -23,10 +23,10 @@ ); }); Router::connect('/accounts/validate/*', [ - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validate' ]); -Router::connect('/profile/*', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); -Router::connect('/login', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); -Router::connect('/logout', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout']); +Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); +Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); +Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); diff --git a/config/users.php b/config/users.php index 52d48470b..a7c147167 100644 --- a/config/users.php +++ b/config/users.php @@ -44,7 +44,7 @@ 'Profile' => [ //Allow view other users profiles 'viewOthers' => true, - 'route' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile'], + 'route' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], ], 'Key' => [ 'Session' => [ @@ -83,7 +83,7 @@ //default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ 'loginAction' => [ - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', ], @@ -101,9 +101,9 @@ ], //default Opauth configuration, you'll need to provide the strategy keys 'Opauth' => [ - 'path' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit'], + 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'opauthInit'], 'callback_param' => 'callback', - 'complete_url' => ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login'], + 'complete_url' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], 'Strategy' => [ 'Facebook' => [ 'scope' => ['public_profile', 'user_friends', 'email'] diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 1a55aadd6..47256aa6d 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -87,7 +87,7 @@ class SimpleRbacAuthorize extends BaseAuthorize //specific actions allowed for the user role in Users plugin [ 'role' => 'user', - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => ['profile', 'logout'], ], diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 2e243b765..5a6b0207c 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -60,7 +60,7 @@ public function validateAccount($provider, $reference, $token) } catch (Exception $exception) { $this->Flash->error(__d('Users', 'Social Account could not be validated')); } - return $this->redirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } /** @@ -87,6 +87,6 @@ public function resendValidation($provider, $reference) } catch (Exception $exception) { $this->Flash->error(__d('Users', 'Email could not be resent')); } - return $this->redirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); + return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } } diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index d58ed243f..e295dc273 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -53,7 +53,7 @@ protected function _getEmailInstance(Email $email = null) { if ($email === null) { $email = new Email('default'); - $email->template('Users.validation') + $email->template('CakeDC/Users.validation') ->emailFormat('both'); } diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp index d5bf7cc2b..10feeba1f 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -11,7 +11,7 @@ $activationUrl = [ '_full' => true, - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword', isset($token) ? $token : '' diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp index 87a48b3aa..f4357c898 100644 --- a/src/Template/Email/html/social_account_validation.ctp +++ b/src/Template/Email/html/social_account_validation.ctp @@ -18,7 +18,7 @@ $text = __d('Users', 'Activate your social login here'); $activationUrl = [ '_full' => true, - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validateAccount', $socialAccount['provider'], diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index af78b62bc..dbdc2fe4f 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -11,7 +11,7 @@ $activationUrl = [ '_full' => true, - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', isset($token) ? $token : '' diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp index 79a74e385..c2f38948e 100644 --- a/src/Template/Email/text/reset_password.ctp +++ b/src/Template/Email/text/reset_password.ctp @@ -11,7 +11,7 @@ $activationUrl = [ '_full' => true, - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword', isset($token) ? $token : '' diff --git a/src/Template/Email/text/social_account_validation.ctp b/src/Template/Email/text/social_account_validation.ctp index 59240e0c3..e2a7503d7 100644 --- a/src/Template/Email/text/social_account_validation.ctp +++ b/src/Template/Email/text/social_account_validation.ctp @@ -11,7 +11,7 @@ $activationUrl = [ '_full' => true, - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validateAccount', $socialAccount['provider'], diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp index 26503c9cd..9bc3deb34 100644 --- a/src/Template/Email/text/validation.ctp +++ b/src/Template/Email/text/validation.ctp @@ -11,7 +11,7 @@ $activationUrl = [ '_full' => true, - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', isset($token) ? $token : '' diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index 5f2382dd8..e2f1ec01b 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -21,7 +21,7 @@ ?> - Html->link(__d('Users', 'Change Password'), ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'changePassword']); ?> + Html->link(__d('Users', 'Change Password'), ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword']); ?>
diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 56207a205..aa713ab4c 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -83,7 +83,7 @@ public function twitterLogin() public function logout($message = null, $options = []) { return $this->Html->link(empty($message) ? __d('Users', 'Logout') : $message, [ - 'plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout' + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout' ], $options); } diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index 08e11fcff..b4fb06ba3 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -40,7 +40,7 @@ class SimpleRbacAuthorizeTest extends TestCase //specific actions allowed for the user role in Users plugin [ 'role' => 'user', - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => ['profile', 'logout'], ], diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 120cd3359..cb4f1080d 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -60,11 +60,11 @@ public function setUp() Router::scope('/auth', function ($routes) { $routes->connect( '/*', - ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'opauthInit'] + ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'opauthInit'] ); }); Router::connect('/a/validate/*', [ - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'resendValidation' ]); @@ -183,7 +183,7 @@ public function testIsUrlAuthorizedUrlString() ->will($this->returnValue(['id' => 1])); $request = new Request('/a/validate'); $request->params = [ - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'resendValidation', 'pass' => [], @@ -206,7 +206,7 @@ public function testIsUrlAuthorizedUrlArray() $event = new Event('event'); $event->data = [ 'url' => [ - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'resendValidation', 'pass-one' @@ -221,7 +221,7 @@ public function testIsUrlAuthorizedUrlArray() ->will($this->returnValue(['id' => 1])); $request = new Request('/a/validate/pass-one'); $request->params = [ - 'plugin' => 'Users', + 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'resendValidation', 'pass' => ['pass-one'], diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index a5541c240..27501e316 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -11,9 +11,16 @@ namespace CakeDC\Users\Test\TestCase\Controller; -use Cake\TestSuite\IntegrationTestCase; +use CakeDC\Users\Controller\SocialAccountsController; +use CakeDC\Users\Model\Table\SocialAccountsTable; +use CakeDC\Users\Model\Behavior\SocialAccountBehavior; +use Cake\Core\Configure; +use Cake\Event\EventManager; +use Cake\Network\Email\Email; +use Cake\Network\Request; +use Cake\TestSuite\TestCase; -class SocialAccountsControllerTest extends IntegrationTestCase +class SocialAccountsControllerTest extends TestCase { /** * Fixtures @@ -25,6 +32,58 @@ class SocialAccountsControllerTest extends IntegrationTestCase 'plugin.CakeDC/Users.users' ]; + /** + * setUp + * + * @return void + */ + public function setUp() + { + parent::setUp(); + + $this->configOpauth = Configure::read('Opauth'); + $this->configRememberMe = Configure::read('Users.RememberMe.active'); + Configure::write('Opauth', null); + Configure::write('Users.RememberMe.active', false); + + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->configEmail = Email::config('default'); + Email::config('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + + $request = new Request('/users/users/index'); + $request->params['plugin'] = 'CakeDC/Users'; + + $this->Controller = $this->getMockBuilder('CakeDC\Users\Controller\SocialAccountsController') + ->setMethods(['redirect', 'render']) + ->setConstructorArgs([$request, null, 'SocialAccounts']) + ->getMock(); + $this->Controller->SocialAccounts = $this->getMockForModel('CakeDC\Users.SocialAccounts', ['sendSocialValidationEmail'], [ + 'className' => 'CakeDC\Users\Model\Table\SocialAccountsTable' + ]); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + Email::drop('default'); + Email::dropTransport('test'); + Email::config('default', $this->configEmail); + + Configure::write('Opauth', $this->configOpauth); + Configure::write('Users.RememberMe.active', $this->configRememberMe); + + parent::tearDown(); + } + /** * test * @@ -32,10 +91,11 @@ class SocialAccountsControllerTest extends IntegrationTestCase */ public function testValidateAccountHappy() { - $this->get('/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234'); - $this->assertResponseSuccess(); - $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); - $this->assertSession('Account validated successfully', 'Flash.flash.message'); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-1234'); + $this->assertEquals('Account validated successfully', $this->Controller->request->session()->read('Flash.flash.message')); } /** @@ -45,10 +105,11 @@ public function testValidateAccountHappy() */ public function testValidateAccountInvalidToken() { - $this->get('/users/social-accounts/validate-account/Facebook/reference-1-1234/token-not-found'); - $this->assertResponseSuccess(); - $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); - $this->assertSession('Invalid token and/or social account', 'Flash.flash.message'); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-not-found'); + $this->assertEquals('Invalid token and/or social account', $this->Controller->request->session()->read('Flash.flash.message')); } /** @@ -58,10 +119,11 @@ public function testValidateAccountInvalidToken() */ public function testValidateAccountAlreadyActive() { - $this->get('/users/social-accounts/validate-account/Twitter/reference-1-1234/token-1234'); - $this->assertResponseSuccess(); - $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); - $this->assertSession('SocialAccount already active', 'Flash.flash.message'); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); + $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.message')); } /** @@ -71,10 +133,43 @@ public function testValidateAccountAlreadyActive() */ public function testResendValidationHappy() { - $this->get('/users/social-accounts/resend-validation/Facebook/reference-1-1234'); - $this->assertResponseSuccess(); - $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); - $this->assertSession('Email sent successfully', 'Flash.flash.message'); + $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') + ->setMethods(['sendSocialValidationEmail']) + ->setConstructorArgs([$this->Controller->SocialAccounts]) + ->getMock(); + $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); + $behaviorMock->expects($this->once()) + ->method('sendSocialValidationEmail') + ->will($this->returnValue(true)); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Controller->resendValidation('Facebook', 'reference-1-1234'); + $this->assertEquals('Email sent successfully', $this->Controller->request->session()->read('Flash.flash.message')); + } + + /** + * test + * + * @return void + */ + public function testResendValidationEmailError() + { + $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') + ->setMethods(['sendSocialValidationEmail']) + ->setConstructorArgs([$this->Controller->SocialAccounts]) + ->getMock(); + $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); + $behaviorMock->expects($this->once()) + ->method('sendSocialValidationEmail') + ->will($this->returnValue(false)); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Controller->resendValidation('Facebook', 'reference-1-1234'); + $this->assertEquals('Email could not be sent', $this->Controller->request->session()->read('Flash.flash.message')); } /** @@ -84,10 +179,11 @@ public function testResendValidationHappy() */ public function testResendValidationInvalid() { - $this->get('/users/social-accounts/resend-validation/Facebook/reference-invalid'); - $this->assertResponseSuccess(); - $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); - $this->assertSession('Invalid account', 'Flash.flash.message'); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->resendValidation('Facebook', 'reference-invalid'); + $this->assertEquals('Invalid account', $this->Controller->request->session()->read('Flash.flash.message')); } /** @@ -97,9 +193,10 @@ public function testResendValidationInvalid() */ public function testResendValidationAlreadyActive() { - $this->get('/users/social-accounts/validate-account/Twitter/reference-1-1234/token-1234'); - $this->assertResponseSuccess(); - $this->assertRedirect(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); - $this->assertSession('SocialAccount already active', 'Flash.flash.message'); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); + $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.message')); } } diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 60db6a850..a3567162a 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -59,7 +59,7 @@ public function testChangePasswordHappy() ])); $this->Trait->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); $this->Trait->Flash->expects($this->any()) ->method('success') ->with('Password has been changed successfully'); diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 1348e0c28..0685db40a 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -215,7 +215,7 @@ public function testSendValidationEmail() 'email' => 'test@example.com', 'token' => '12345' ]); - $this->Email->template('Users.validation') + $this->Email->template('CakeDC/Users.validation') ->emailFormat('both'); $result = $this->Users->sendValidationEmail($user, $this->Email); @@ -267,7 +267,7 @@ public function testSendResetPasswordEmail() 'email' => 'test@example.com', 'token' => '12345' ]); - $this->Email->template('Users.reset_password') + $this->Email->template('CakeDC/Users.reset_password') ->emailFormat('both'); $result = $this->Users->sendResetPasswordEmail($user, $this->Email); From 697a6fad5ca3e88edd17654d7a0266bb557c8564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 3 Sep 2015 13:59:15 +0100 Subject: [PATCH 0222/1476] refs #refactor-behavior fix plugin references to boot the plugin correctly --- config/users.php | 6 +++--- src/Controller/Component/UsersAuthComponent.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/users.php b/config/users.php index a7c147167..9d21a930e 100644 --- a/config/users.php +++ b/config/users.php @@ -91,12 +91,12 @@ 'all' => [ 'scope' => ['active' => 1] ], - 'Users.RememberMe', + 'CakeDC/Users.RememberMe', 'Form', ], 'authorize' => [ - 'Users.Superuser', - 'Users.SimpleRbac', + 'CakeDC/Users.Superuser', + 'CakeDC/Users.SimpleRbac', ], ], //default Opauth configuration, you'll need to provide the strategy keys diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 131e196ce..7d375a874 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -64,7 +64,7 @@ public function initialize(array $config) protected function _loadSocialLogin() { $this->_registry->getController()->Auth->config('authenticate', [ - 'Users.Social' + 'CakeDC/Users.Social' ], true); } From ba59e137e4f78a802107a4410205729f2305fc63 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 8 Sep 2015 08:53:44 -0430 Subject: [PATCH 0223/1476] Generating contain based on the configuration --- src/Controller/Traits/ProfileTrait.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 15f9e1c3d..defb9c576 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -35,9 +35,11 @@ public function profile($id = null) $id = $loggedUserId; } try { + $appContain = Configure::read('Auth.authenticate.' . \Cake\Controller\Component\AuthComponent::ALL . '.contain'); + $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; $user = $this->getUsersTable()->get($id, [ - 'contain' => ['SocialAccounts'] - ]); + 'contain' => array_merge($appContain, $socialContain) + ]); $this->set('avatarPlaceholder', Configure::read('Users.Avatar.placeholder')); if ($user->id === $loggedUserId) { $isCurrentUser = true; From 971f0338e45fffd3b206d7d22d45e36bd7943569 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 8 Sep 2015 08:55:56 -0430 Subject: [PATCH 0224/1476] Messages improvement --- src/Controller/Traits/UserValidationTrait.php | 2 +- src/Locale/Users.pot | 2 +- tests/TestCase/Controller/Traits/UserValidationTraitTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index ed1588e11..ef78e05a6 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -88,7 +88,7 @@ public function resendTokenValidation() 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => true, ])) { - $this->Flash->success(__d('Users', 'Token has been reset successfully')); + $this->Flash->success(__d('Users', 'Token has been reset successfully. Please check your email.')); } else { $this->Flash->error(__d('Users', 'Token could not be reset')); } diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 1caa9f2cf..79f386803 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -183,7 +183,7 @@ msgid "Invalid validation type" msgstr "" #: Controller/Traits/UserValidationTrait.php:88 -msgid "Token has been reset successfully" +msgid "Token has been reset successfully. Please check your email." msgstr "" #: Controller/Traits/UserValidationTrait.php:96 diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 321c03573..ba2d39837 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -138,7 +138,7 @@ public function testResendTokenValidationHappy() $this->Trait->Flash->expects($this->once()) ->method('success') - ->with('Token has been reset successfully'); + ->with('Token has been reset successfully. Please check your email.'); $this->Trait->expects($this->once()) ->method('redirect') ->with(['action' => 'login']); From 63451bfbc78618da247c0ee31fa92ee92637d6f4 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 10 Sep 2015 19:30:03 +0300 Subject: [PATCH 0225/1476] Fixing test suite to run tests. Temporary disable tests for social integration. Fixed issue with user activation after reset password. --- composer.json | 5 +- composer.lock | 350 ++++++++++++------ src/Controller/Traits/ProfileTrait.php | 2 +- tests/App/Controller/AppController.php | 25 ++ tests/TestCase/Model/Table/UsersTableTest.php | 8 +- tests/TestCase/View/Helper/UserHelperTest.php | 8 +- tests/bootstrap.php | 87 ++++- tests/config/routes.php | 30 +- 8 files changed, 368 insertions(+), 147 deletions(-) create mode 100644 tests/App/Controller/AppController.php diff --git a/composer.json b/composer.json index c56a09446..461dbe3b2 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,10 @@ "cakephp/cakephp": "~3.0" }, "require-dev": { - "phpunit/phpunit": "*" + "phpunit/phpunit": "*", + "opauth/opauth": "*", + "opauth/facebook": "*", + "opauth/twitter": "*" }, "suggest": { "opauth/opauth": "Used for Social Login, if you add Opauth, remember adding at least one strategy too", diff --git a/composer.lock b/composer.lock index 1f84e528b..223a588a9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "272d2fc14a03fb78ed921ed2e143784b", + "hash": "042aacec48115d299cbb935ebe2d8985", "packages": [ { "name": "aura/installer-default", @@ -127,16 +127,16 @@ }, { "name": "cakephp/cakephp", - "version": "3.0.4", + "version": "3.0.13", "source": { "type": "git", "url": "https://github.com/cakephp/cakephp.git", - "reference": "22976db9856c1d6dea8b94136030cf8804609035" + "reference": "5921b2facedbc4cdcdc4daa5f736118838796bad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/cakephp/zipball/22976db9856c1d6dea8b94136030cf8804609035", - "reference": "22976db9856c1d6dea8b94136030cf8804609035", + "url": "https://api.github.com/repos/cakephp/cakephp/zipball/5921b2facedbc4cdcdc4daa5f736118838796bad", + "reference": "5921b2facedbc4cdcdc4daa5f736118838796bad", "shasum": "" }, "require": { @@ -155,6 +155,7 @@ "cakephp/database": "self.version", "cakephp/datasource": "self.version", "cakephp/event": "self.version", + "cakephp/filesystem": "self.version", "cakephp/i18n": "self.version", "cakephp/log": "self.version", "cakephp/orm": "self.version", @@ -197,7 +198,7 @@ "keywords": [ "framework" ], - "time": "2015-05-08 01:45:39" + "time": "2015-09-07 01:53:22" }, { "name": "ircmaxell/password-compat", @@ -329,16 +330,16 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { @@ -349,7 +350,7 @@ "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "2.0.*@ALPHA" + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { @@ -358,8 +359,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\Instantiator\\": "src" + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -379,7 +380,148 @@ "constructor", "instantiate" ], - "time": "2014-10-13 12:58:55" + "time": "2015-06-14 21:17:01" + }, + { + "name": "opauth/facebook", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/opauth/facebook.git", + "reference": "28c0e53393a03a66cbfea03073d1d6aacfaddb69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opauth/facebook/zipball/28c0e53393a03a66cbfea03073d1d6aacfaddb69", + "reference": "28c0e53393a03a66cbfea03073d1d6aacfaddb69", + "shasum": "" + }, + "require": { + "opauth/opauth": ">=0.2.0", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "U-Zyn Chua", + "email": "chua@uzyn.com", + "homepage": "http://uzyn.com" + } + ], + "description": "Facebook strategy for Opauth", + "homepage": "http://opauth.org", + "keywords": [ + "Authentication", + "auth", + "facebook" + ], + "time": "2012-09-21 04:47:35" + }, + { + "name": "opauth/opauth", + "version": "0.4.4", + "source": { + "type": "git", + "url": "https://github.com/opauth/opauth.git", + "reference": "436fb98c2374c9e8ae4d8adddf83214bee4d9c72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opauth/opauth/zipball/436fb98c2374c9e8ae4d8adddf83214bee4d9c72", + "reference": "436fb98c2374c9e8ae4d8adddf83214bee4d9c72", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "suggest": { + "opauth/facebook": "Allows Facebook authentication", + "opauth/google": "Allows Google authentication", + "opauth/twitter": "Allows Twitter authentication" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/Opauth/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "U-Zyn Chua", + "email": "chua@uzyn.com", + "homepage": "http://uzyn.com" + } + ], + "description": "Multi-provider authentication framework for PHP", + "homepage": "http://opauth.org", + "keywords": [ + "Authentication", + "OpenId", + "auth", + "facebook", + "google", + "oauth", + "omniauth", + "twitter" + ], + "time": "2013-05-10 09:01:52" + }, + { + "name": "opauth/twitter", + "version": "0.3.1", + "source": { + "type": "git", + "url": "https://github.com/opauth/twitter.git", + "reference": "24792d512ccc67e7d11e9249737616f039551c11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opauth/twitter/zipball/24792d512ccc67e7d11e9249737616f039551c11", + "reference": "24792d512ccc67e7d11e9249737616f039551c11", + "shasum": "" + }, + "require": { + "opauth/opauth": ">=0.2.0", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "U-Zyn Chua", + "email": "chua@uzyn.com", + "homepage": "http://uzyn.com" + } + ], + "description": "Twitter strategy for Opauth", + "homepage": "http://opauth.org", + "keywords": [ + "Authentication", + "auth", + "twitter" + ], + "time": "2013-06-12 07:50:11" }, { "name": "phpdocumentor/reflection-docblock", @@ -432,16 +574,16 @@ }, { "name": "phpspec/prophecy", - "version": "v1.4.1", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373" + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", - "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", "shasum": "" }, "require": { @@ -488,20 +630,20 @@ "spy", "stub" ], - "time": "2015-04-27 22:15:08" + "time": "2015-08-13 10:07:40" }, { "name": "phpunit/php-code-coverage", - "version": "2.0.16", + "version": "2.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c" + "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2d7c03c0e4e080901b8f33b2897b0577be18a13c", + "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c", "shasum": "" }, "require": { @@ -509,7 +651,7 @@ "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "~1.0", + "sebastian/environment": "^1.3.2", "sebastian/version": "~1.0" }, "require-dev": { @@ -524,7 +666,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { @@ -550,20 +692,20 @@ "testing", "xunit" ], - "time": "2015-04-11 04:35:00" + "time": "2015-08-04 03:42:39" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb" + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb", - "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "shasum": "" }, "require": { @@ -597,20 +739,20 @@ "filesystem", "iterator" ], - "time": "2015-04-02 05:19:05" + "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { @@ -619,20 +761,17 @@ "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -641,20 +780,20 @@ "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "1.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", "shasum": "" }, "require": { @@ -663,13 +802,10 @@ "type": "library", "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -685,20 +821,20 @@ "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2015-06-21 08:01:12" }, { "name": "phpunit/php-token-stream", - "version": "1.4.1", + "version": "1.4.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "eab81d02569310739373308137284e0158424330" + "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", - "reference": "eab81d02569310739373308137284e0158424330", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3ab72c62e550370a6cd5dc873e1a04ab57562f5b", + "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b", "shasum": "" }, "require": { @@ -734,20 +870,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-04-08 04:46:07" + "time": "2015-08-16 08:51:00" }, { "name": "phpunit/phpunit", - "version": "4.6.6", + "version": "4.8.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac" + "reference": "2246830f4a1a551c67933e4171bf2126dc29d357" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3afe303d873a4d64c62ef84de491b97b006fbdac", - "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357", + "reference": "2246830f4a1a551c67933e4171bf2126dc29d357", "shasum": "" }, "require": { @@ -757,15 +893,15 @@ "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpspec/prophecy": "~1.3,>=1.3.1", - "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0", + "phpunit/php-timer": ">=1.0.6", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", - "sebastian/environment": "~1.2", + "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", @@ -780,7 +916,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.6.x-dev" + "dev-master": "4.8.x-dev" } }, "autoload": { @@ -806,26 +942,27 @@ "testing", "xunit" ], - "time": "2015-04-29 15:18:52" + "time": "2015-08-24 04:09:38" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.1", + "version": "2.3.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" + "reference": "5e2645ad49d196e020b85598d7c97e482725786a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5e2645ad49d196e020b85598d7c97e482725786a", + "reference": "5e2645ad49d196e020b85598d7c97e482725786a", "shasum": "" }, "require": { - "doctrine/instantiator": "~1.0,>=1.0.2", + "doctrine/instantiator": "^1.0.2", "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2" + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -861,20 +998,20 @@ "mock", "xunit" ], - "time": "2015-04-02 05:36:41" + "time": "2015-08-19 09:14:08" }, { "name": "sebastian/comparator", - "version": "1.1.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", "shasum": "" }, "require": { @@ -888,7 +1025,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -925,7 +1062,7 @@ "compare", "equality" ], - "time": "2015-01-29 16:28:08" + "time": "2015-07-26 15:48:44" }, { "name": "sebastian/diff", @@ -981,16 +1118,16 @@ }, { "name": "sebastian/environment", - "version": "1.2.2", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", "shasum": "" }, "require": { @@ -1027,20 +1164,20 @@ "environment", "hhvm" ], - "time": "2015-01-01 10:01:08" + "time": "2015-08-03 06:14:51" }, { "name": "sebastian/exporter", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "84839970d05254c73cde183a721c7af13aede943" + "reference": "7ae5513327cb536431847bcc0c10edba2701064e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", - "reference": "84839970d05254c73cde183a721c7af13aede943", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e", "shasum": "" }, "require": { @@ -1093,7 +1230,7 @@ "export", "exporter" ], - "time": "2015-01-27 07:23:06" + "time": "2015-06-21 07:55:53" }, { "name": "sebastian/global-state", @@ -1148,16 +1285,16 @@ }, { "name": "sebastian/recursion-context", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", "shasum": "" }, "require": { @@ -1197,20 +1334,20 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-01-24 09:48:32" + "time": "2015-06-21 08:04:50" }, { "name": "sebastian/version", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "type": "library", @@ -1232,25 +1369,24 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-02-24 06:35:25" + "time": "2015-06-21 13:59:46" }, { "name": "symfony/yaml", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Yaml", + "version": "v2.7.4", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + "reference": "2dc7b06c065df96cc686c66da2705e5e18aef661" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/2dc7b06c065df96cc686c66da2705e5e18aef661", + "reference": "2dc7b06c065df96cc686c66da2705e5e18aef661", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -1258,11 +1394,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Yaml\\": "" } }, @@ -1282,7 +1418,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-08-24 07:13:45" } ], "aliases": [], diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index defb9c576..f5e825054 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -38,7 +38,7 @@ public function profile($id = null) $appContain = Configure::read('Auth.authenticate.' . \Cake\Controller\Component\AuthComponent::ALL . '.contain'); $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; $user = $this->getUsersTable()->get($id, [ - 'contain' => array_merge($appContain, $socialContain) + 'contain' => array_merge((array)$appContain, (array)$socialContain) ]); $this->set('avatarPlaceholder', Configure::read('Users.Avatar.placeholder')); if ($user->id === $loggedUserId) { diff --git a/tests/App/Controller/AppController.php b/tests/App/Controller/AppController.php new file mode 100644 index 000000000..9f88e565a --- /dev/null +++ b/tests/App/Controller/AppController.php @@ -0,0 +1,25 @@ +loadComponent('Flash'); + // $this->loadComponent('CakeDC/Users.UsersAuth'); + $this->loadComponent('RequestHandler'); + } + +} diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 0685db40a..25d773f74 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -89,7 +89,7 @@ public function testValidateRegisterNoValidateEmail() $this->assertTrue($result->active); } - public function testSocialLogin() + public function _testSocialLogin() { $raw = [ 'id' => 'reference-2-1', @@ -116,7 +116,7 @@ public function testSocialLogin() * * @expectedException CakeDC\Users\Exception\AccountNotActiveException */ - public function testSocialLoginInactiveAccount() + public function _testSocialLoginInactiveAccount() { $raw = [ 'id' => 'reference-2-2', @@ -142,7 +142,7 @@ public function testSocialLoginInactiveAccount() * * @expectedException InvalidArgumentException */ - public function testSocialLoginddCreateNewAccountWithNoCredentials() + public function _testSocialLoginddCreateNewAccountWithNoCredentials() { $raw = [ 'id' => 'reference-not-existing', @@ -165,7 +165,7 @@ public function testSocialLoginddCreateNewAccountWithNoCredentials() * Test socialLogin * */ - public function testSocialLoginCreateNewAccount() + public function _testSocialLoginCreateNewAccount() { $raw = [ 'id' => 'no-existing-reference', diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 6ed93c1ba..84be4d0fb 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -83,7 +83,7 @@ public function testTwitterLoginEnabled() public function testLogout() { $result = $this->User->logout(); - $expected = 'Logout'; + $expected = 'Logout'; $this->assertEquals($expected, $result); } @@ -95,7 +95,7 @@ public function testLogout() public function testLogoutDifferentMessage() { $result = $this->User->logout('Sign Out'); - $expected = 'Sign Out'; + $expected = 'Sign Out'; $this->assertEquals($expected, $result); } @@ -107,7 +107,7 @@ public function testLogoutDifferentMessage() public function testLogoutWithOptions() { $result = $this->User->logout('Sign Out', ['class' => 'logout']); - $expected = 'Sign Out'; + $expected = 'Sign Out'; $this->assertEquals($expected, $result); } @@ -168,7 +168,7 @@ public function testWelcome() ->method('session') ->will($this->returnValue($session)); - $expected = 'Welcome, david'; + $expected = 'Welcome, david'; $result = $this->User->welcome(); $this->assertEquals($expected, $result); } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 0243da08f..31d7ef6e6 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -6,11 +6,6 @@ * has been installed as a dependency of the plugin, or the plugin is itself * installed as a dependency of an application. */ - -use Cake\Core\Configure; -use Cake\Routing\DispatcherFactory; -use Cake\Routing\Filter\ControllerFactory; - $findRoot = function ($root) { do { $lastRoot = $root; @@ -24,22 +19,84 @@ $root = $findRoot(__FILE__); unset($findRoot); chdir($root); +// require $root . '/vendor/cakephp/cakephp/tests/bootstrap.php'; + +define('DS', DIRECTORY_SEPARATOR); +define('ROOT', $root); +define('APP_DIR', 'App'); +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('TMP', ROOT . DS . 'tmp' . DS); +define('LOGS', TMP . 'logs' . DS); +define('CACHE', TMP . 'cache' . DS); +define('CAKE_CORE_INCLUDE_PATH', ROOT . '/vendor/cakephp/cakephp'); +define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS); +define('CAKE', CORE_PATH . 'src' . DS); + +require ROOT . '/vendor/cakephp/cakephp/src/basics.php'; +require ROOT . '/vendor/autoload.php'; -define('CONFIG', $root . '/tests/config/'); +Cake\Core\Configure::write('App', ['namespace' => 'Users\Test\App']); +// Cake\Core\Configure::write('App', ['namespace' => 'App']); -require $root . '/vendor/cakephp/cakephp/tests/bootstrap.php'; -\Cake\Core\Plugin::load('CakeDC/Users', [ - 'path' => dirname(dirname(__FILE__)) . DS, - ]); +Cake\Core\Configure::write('debug', true); +Cake\Core\Configure::write('App.encoding', 'UTF-8'); +$TMP = new \Cake\Filesystem\Folder(TMP); +$TMP->create(TMP . 'cache/models', 0777); +$TMP->create(TMP . 'cache/persistent', 0777); +$TMP->create(TMP . 'cache/views', 0777); +$cache = [ + 'default' => [ + 'engine' => 'File', + ], + '_cake_core_' => [ + 'className' => 'File', + 'prefix' => 'users_myapp_cake_core_', + 'path' => CACHE . 'persistent/', + 'serialize' => true, + 'duration' => '+10 seconds', + ], + '_cake_model_' => [ + 'className' => 'File', + 'prefix' => 'users_app_cake_model_', + 'path' => CACHE . 'models/', + 'serialize' => 'File', + 'duration' => '+10 seconds', + ], +]; + +Cake\Cache\Cache::config($cache); +Cake\Core\Configure::write('Session', [ + 'defaults' => 'php' +]); + + +\Cake\Core\Plugin::load('CakeDC/Users', ['path' => dirname(dirname(__FILE__)) . DS]); if (file_exists($root . '/config/bootstrap.php')) { require $root . '/config/bootstrap.php'; } -/** - * Connect middleware/dispatcher filters. - */ -DispatcherFactory::add('Routing'); -DispatcherFactory::add('ControllerFactory'); +Cake\Routing\DispatcherFactory::add('Routing'); +Cake\Routing\DispatcherFactory::add('ControllerFactory'); + + +class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\AppController'); +// echo class_exists('App\Controller\AppController'); + +// exit; + +// Ensure default test connection is defined +if (!getenv('db_dsn')) { + putenv('db_dsn=sqlite:///:memory:'); +} + +Cake\Datasource\ConnectionManager::config('test', [ + 'url' => getenv('db_dsn'), + 'timezone' => 'UTC' +]); diff --git a/tests/config/routes.php b/tests/config/routes.php index faec0701e..61086c566 100644 --- a/tests/config/routes.php +++ b/tests/config/routes.php @@ -12,21 +12,21 @@ use Cake\Core\Configure; use Cake\Routing\Router; -Router::plugin('Users', function ($routes) { - $routes->fallbacks('DashedRoute'); - }); +Router::plugin('CakeDC/Users', function ($routes) { + $routes->fallbacks('DashedRoute'); +}); Router::scope('/auth', function ($routes) { - $routes->connect( - '/*', - Configure::read('Opauth.path') - ); - }); + $routes->connect( + '/*', + Configure::read('Opauth.path') + ); +}); Router::connect('/accounts/validate/*', [ - 'plugin' => 'Users', - 'controller' => 'SocialAccounts', - 'action' => 'validate' - ]); -Router::connect('/profile/*', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'profile']); -Router::connect('/login', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'login']); -Router::connect('/logout', ['plugin' => 'Users', 'controller' => 'Users', 'action' => 'logout']); + '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 4954ec4c0d279a1204589525bdf19a719b772c14 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 10 Sep 2015 19:30:35 +0300 Subject: [PATCH 0226/1476] Fixed issue with custom validator definition on app level --- src/Controller/Traits/RegisterTrait.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 416e13828..09bd91cdc 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -54,7 +54,6 @@ public function register() ]); if ($event->result instanceof EntityInterface) { - $options['validator'] = 'default'; if ($userSaved = $usersTable->register($user, $event->result->toArray(), $options)) { return $this->_afterRegister($userSaved); } From 358915f147222f96c576cdefd38a4aa17ee8a325 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 10 Sep 2015 22:02:29 +0300 Subject: [PATCH 0227/1476] added send email on validation request --- src/Controller/Traits/UserValidationTrait.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index ef78e05a6..d31c9f36a 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -87,6 +87,7 @@ public function resendTokenValidation() if ($this->getUsersTable()->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => true, + 'sendEmail' => true ])) { $this->Flash->success(__d('Users', 'Token has been reset successfully. Please check your email.')); } else { From 1c0c2bc8f5eb1974ccf3c2805e84ef91c473c549 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 10 Sep 2015 16:26:22 -0430 Subject: [PATCH 0228/1476] Defining differents templates based on the reason of the token reset (reset password or resend email validation) --- src/Controller/Traits/UserValidationTrait.php | 3 ++- src/Model/Behavior/PasswordBehavior.php | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index d31c9f36a..5b848ea22 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -87,7 +87,8 @@ public function resendTokenValidation() if ($this->getUsersTable()->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => true, - 'sendEmail' => true + 'sendEmail' => true, + 'emailTemplate' => 'CakeDC/Users.validation' ])) { $this->Flash->success(__d('Users', 'Token has been reset successfully. Please check your email.')); } else { diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index b101610d0..fd6c56169 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -60,8 +60,9 @@ public function resetToken($reference, array $options = []) } $user->updateToken(Hash::get($options, 'expiration')); $saveResult = $this->_table->save($user); + $template = !empty($options['emailTemplate']) ? $options['emailTemplate'] : 'CakeDC/Users.reset_password'; if (Hash::get($options, 'sendEmail')) { - $this->sendResetPasswordEmail($saveResult); + $this->sendResetPasswordEmail($saveResult, null, $template); } return $saveResult; } @@ -82,16 +83,17 @@ protected function _getUser($reference) * * @param EntityInterface $user User entity * @param Email $email instance, if null the default email configuration with the + * @param string $template email template * Users.validation template will be used, so set a ->template() if you pass an Email * instance * @return array email send result */ - public function sendResetPasswordEmail(EntityInterface $user, Email $email = null) + public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $subject = __d('Users', '{0}Your reset password link', $firstName); return $this->_getEmailInstance($email) - ->template('CakeDC/Users.reset_password') + ->template($template) ->to($user['email']) ->subject($subject) ->viewVars($user->toArray()) From 4daa210cb2660d55fac0e4cbbddcd0320e233d75 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sat, 12 Sep 2015 15:35:52 +0000 Subject: [PATCH 0229/1476] fix routes loading --- tests/TestCase/View/Helper/UserHelperTest.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 6ed93c1ba..00538e16b 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -11,7 +11,9 @@ namespace CakeDC\Users\Test\TestCase\View\Helper; +use Cake\Core\App; use Cake\Core\Configure; +use Cake\Core\Plugin; use Cake\Event\Event; use Cake\Network\Request; use Cake\Routing\Router; @@ -33,7 +35,7 @@ class UserHelperTest extends TestCase public function setUp() { parent::setUp(); - Router::connect(':plugin/:controller/:action'); + Plugin::routes('CakeDC/Users'); $this->View = $this->getMock('Cake\View\View', ['append']); $this->User = new UserHelper($this->View); $this->request = new Request(); @@ -83,7 +85,7 @@ public function testTwitterLoginEnabled() public function testLogout() { $result = $this->User->logout(); - $expected = 'Logout'; + $expected = 'Logout'; $this->assertEquals($expected, $result); } @@ -95,7 +97,7 @@ public function testLogout() public function testLogoutDifferentMessage() { $result = $this->User->logout('Sign Out'); - $expected = 'Sign Out'; + $expected = 'Sign Out'; $this->assertEquals($expected, $result); } @@ -107,7 +109,7 @@ public function testLogoutDifferentMessage() public function testLogoutWithOptions() { $result = $this->User->logout('Sign Out', ['class' => 'logout']); - $expected = 'Sign Out'; + $expected = 'Sign Out'; $this->assertEquals($expected, $result); } @@ -168,7 +170,7 @@ public function testWelcome() ->method('session') ->will($this->returnValue($session)); - $expected = 'Welcome, david'; + $expected = 'Welcome, david'; $result = $this->User->welcome(); $this->assertEquals($expected, $result); } From f49b7c3d0bbb10017741a65b591d655438fd5444 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sat, 12 Sep 2015 15:51:40 +0000 Subject: [PATCH 0230/1476] fix routes to use /users --- config/routes.php | 2 +- src/Controller/Traits/ProfileTrait.php | 2 +- tests/TestCase/Model/Table/UsersTableTest.php | 2 ++ tests/bootstrap.php | 10 ++++++---- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/config/routes.php b/config/routes.php index 61086c566..17187c1fd 100644 --- a/config/routes.php +++ b/config/routes.php @@ -12,7 +12,7 @@ use Cake\Core\Configure; use Cake\Routing\Router; -Router::plugin('CakeDC/Users', function ($routes) { +Router::plugin('CakeDC/Users', ['path' => '/users'], function ($routes) { $routes->fallbacks('DashedRoute'); }); diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index defb9c576..be1d809e1 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -35,7 +35,7 @@ public function profile($id = null) $id = $loggedUserId; } try { - $appContain = Configure::read('Auth.authenticate.' . \Cake\Controller\Component\AuthComponent::ALL . '.contain'); + $appContain = (array)Configure::read('Auth.authenticate.' . \Cake\Controller\Component\AuthComponent::ALL . '.contain'); $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; $user = $this->getUsersTable()->get($id, [ 'contain' => array_merge($appContain, $socialContain) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 0685db40a..381167ae2 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Model\Table; +use Cake\Core\Plugin; use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; use Cake\Routing\Router; @@ -53,6 +54,7 @@ public function setUp() 'className' => 'Debug' ]); $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); + Plugin::routes('CakeDC/Users'); } /** diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b72bb4d83..209cc32ca 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -20,7 +20,9 @@ unset($findRoot); chdir($root); require $root . '/vendor/cakephp/cakephp/tests/bootstrap.php'; -\Cake\Core\Plugin::load('CakeDC/Users', ['path' => dirname(dirname(__FILE__)) . DS]); -if (file_exists($root . '/config/bootstrap.php')) { - require $root . '/config/bootstrap.php'; -} +\Cake\Core\Plugin::load('CakeDC/Users', [ + 'path' => dirname(dirname(__FILE__)) . DS, + 'routes' => true, +]); +require $root . '/config/bootstrap.php'; +unset($root); \ No newline at end of file From dc62c6e701c17dfc2929ea0bbdf6b680b7e6ae31 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sat, 12 Sep 2015 16:09:55 +0000 Subject: [PATCH 0231/1476] fix all failed tests after vendor in namespace --- .../Controller/Traits/RegisterTraitTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 635c95fd6..01d0ce3b9 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -12,6 +12,8 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Core\Configure; +use Cake\Core\Plugin; +use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; @@ -27,6 +29,17 @@ public function setUp() $this->traitClassName = 'CakeDC\Users\Controller\Traits\RegisterTrait'; $this->traitMockMethods = ['validate', 'dispatchEvent', 'set', 'validateReCaptcha', 'redirect']; parent::setUp(); + + Plugin::routes('CakeDC/Users'); + + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->configEmail = Email::config('default'); + Email::config('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); } /** @@ -36,6 +49,10 @@ public function setUp() */ public function tearDown() { + Email::drop('default'); + Email::dropTransport('test'); + Email::config('default', $this->configEmail); + parent::tearDown(); } From 2e141a777784b81659452b54735d38d2182cc1e7 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sun, 13 Sep 2015 12:23:19 +0000 Subject: [PATCH 0232/1476] register no longer throws InvalidArgumentException, fix tests and trait --- src/Controller/Traits/RegisterTrait.php | 8 ++------ tests/TestCase/Model/Table/UsersTableTest.php | 6 ++++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 09bd91cdc..ed033a600 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -74,12 +74,8 @@ public function register() $this->Flash->error(__d('Users', 'The reCaptcha could not be validated')); return; } - try { - $userSaved = $usersTable->register($user, $requestData, $options); - } catch (InvalidArgumentException $ex) { - $this->Flash->error($ex->getMessage()); - return; - } + + $userSaved = $usersTable->register($user, $requestData, $options); if (!$userSaved) { $this->Flash->error(__d('Users', 'The user could not be saved')); return; diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index bd076141f..41cba2133 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -125,7 +125,7 @@ public function testValidateRegisterValidateEmail() } /** - * @expectedException InvalidArgumentException + * test */ public function testValidateRegisterTosRequired() { @@ -137,7 +137,9 @@ public function testValidateRegisterTosRequired() 'first_name' => 'test', 'last_name' => 'user', ]; - $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + $userEntity = $this->Users->newEntity(); + $this->Users->register($userEntity, $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + $this->assertEquals(['tos' => ['_required' => 'This field is required']], $userEntity->errors()); } /** From 8c94ca1e204a3f7771497833bb960debd0a4949d Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sun, 13 Sep 2015 12:27:12 +0000 Subject: [PATCH 0233/1476] fix @covers classnames --- tests/TestCase/Auth/SimpleRbacAuthorizeTest.php | 6 +++--- tests/TestCase/Auth/SuperuserAuthorizeTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index b4fb06ba3..3f758bd1f 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -81,7 +81,7 @@ public function tearDown() } /** - * @covers Users\Auth\SimpleRbacAuthorize::__construct + * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct */ public function testConstruct() { @@ -108,7 +108,7 @@ public function testLoadPermissions() } /** - * @covers Users\Auth\SimpleRbacAuthorize::__construct + * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct */ public function testConstructMissingPermissionsFile() { @@ -133,7 +133,7 @@ protected function assertConstructorPermissions($instance, $config, $permissions } /** - * @covers Users\Auth\SimpleRbacAuthorize::__construct + * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct */ public function testConstructPermissionsFileHappy() { diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php index ab73fd61f..153ac9158 100644 --- a/tests/TestCase/Auth/SuperuserAuthorizeTest.php +++ b/tests/TestCase/Auth/SuperuserAuthorizeTest.php @@ -55,7 +55,7 @@ public function tearDown() } /** - * @covers Users\Auth\SuperuserAuthorize::authorize + * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize */ public function testAuthorizeIsSuperuser() { @@ -68,7 +68,7 @@ public function testAuthorizeIsSuperuser() } /** - * @covers Users\Auth\SuperuserAuthorize::authorize + * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize */ public function testAuthorizeIsNotSuperuser() { @@ -81,7 +81,7 @@ public function testAuthorizeIsNotSuperuser() } /** - * @covers Users\Auth\SuperuserAuthorize::authorize + * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize */ public function testAuthorizeWeirdUser() { From 427c8586e0433e80700bd052815654bb6d7c6f47 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sun, 13 Sep 2015 12:51:13 +0000 Subject: [PATCH 0234/1476] fix routes and related tests --- .../Component/UsersAuthComponentTest.php | 25 +++++++++++-------- tests/config/routes.php | 17 +++++++------ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index de0324642..c68968e71 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -50,8 +50,13 @@ public function setUp() parent::setUp(); $this->backupUsersConfig = Configure::read('Users'); + Router::reload(); Plugin::routes('CakeDC/Users'); - + Router::connect('/route/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword' + ]); Security::salt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); Configure::write('App.namespace', 'Users'); $this->request = $this->getMock('Cake\Network\Request', ['is', 'method']); @@ -155,7 +160,7 @@ public function testIsUrlAuthorizedUrlString() { $event = new Event('event'); $event->data = [ - 'url' => '/a/validate', + 'url' => '/route', ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) @@ -164,11 +169,11 @@ public function testIsUrlAuthorizedUrlString() $this->Controller->Auth->expects($this->once()) ->method('user') ->will($this->returnValue(['id' => 1])); - $request = new Request('/a/validate'); + $request = new Request('/route'); $request->params = [ 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'resendValidation', + 'controller' => 'Users', + 'action' => 'requestResetPassword', 'pass' => [], ]; $this->Controller->Auth->expects($this->once()) @@ -190,8 +195,8 @@ public function testIsUrlAuthorizedUrlArray() $event->data = [ 'url' => [ 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'resendValidation', + 'controller' => 'Users', + 'action' => 'requestResetPassword', 'pass-one' ], ]; @@ -202,11 +207,11 @@ public function testIsUrlAuthorizedUrlArray() $this->Controller->Auth->expects($this->once()) ->method('user') ->will($this->returnValue(['id' => 1])); - $request = new Request('/accounts/validate/pass-one'); + $request = new Request('/route/pass-one'); $request->params = [ 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'resendValidation', + 'controller' => 'Users', + 'action' => 'requestResetPassword', 'pass' => ['pass-one'], ]; $this->Controller->Auth->expects($this->once()) diff --git a/tests/config/routes.php b/tests/config/routes.php index 61086c566..1f8d915d6 100644 --- a/tests/config/routes.php +++ b/tests/config/routes.php @@ -12,16 +12,19 @@ use Cake\Core\Configure; use Cake\Routing\Router; -Router::plugin('CakeDC/Users', function ($routes) { +Router::plugin('CakeDC/Users', ['path' => '/users'], function ($routes) { $routes->fallbacks('DashedRoute'); }); -Router::scope('/auth', function ($routes) { - $routes->connect( - '/*', - Configure::read('Opauth.path') - ); -}); +$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', From e676e47d0e6c549058729ed1ccb6467c251ec248 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sun, 13 Sep 2015 15:43:28 +0000 Subject: [PATCH 0235/1476] fix all tests passing --- src/Controller/Traits/UserValidationTrait.php | 6 +-- .../Controller/Traits/BaseTraitTest.php | 18 ++++++++ .../Controller/Traits/RegisterTraitTest.php | 14 +------ .../Traits/UserValidationTraitTest.php | 1 + .../Model/Table/SocialAccountsTableTest.php | 41 +------------------ tests/TestCase/Model/Table/UsersTableTest.php | 7 ++++ 6 files changed, 32 insertions(+), 55 deletions(-) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 5b848ea22..23d0a2134 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -95,11 +95,11 @@ public function resendTokenValidation() $this->Flash->error(__d('Users', 'Token could not be reset')); } return $this->redirect(['action' => 'login']); - } catch (UserNotFoundException $exception) { + } catch (UserNotFoundException $ex) { $this->Flash->error(__d('Users', 'User {0} was not found', $reference)); - } catch (UserAlreadyActiveException $exception) { + } catch (UserAlreadyActiveException $ex) { $this->Flash->error(__d('Users', 'User {0} is already active', $reference)); - } catch (Exception $exception) { + } catch (Exception $ex) { $this->Flash->error(__d('Users', 'Token could not be reset')); } } diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 03755e301..e22c44a47 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Event\Event; +use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use PHPUnit_Framework_MockObject_RuntimeException; @@ -34,6 +35,7 @@ abstract class BaseTraitTest extends TestCase */ public $traitClassName = ''; public $traitMockMethods = []; + public $mockDefaultEmail = false; /** * SetUp and create Trait @@ -56,6 +58,17 @@ public function setUp() debug($ex); $this->fail("Unit tests extending BaseTraitTest should declare the trait class name in the \$traitClassName variable before calling setUp()"); } + + if ($this->mockDefaultEmail) { + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->configEmail = Email::config('default'); + Email::config('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + } } /** @@ -66,6 +79,11 @@ public function setUp() public function tearDown() { unset($this->table, $this->Trait); + if ($this->mockDefaultEmail) { + Email::drop('default'); + Email::dropTransport('test'); + Email::config('default', $this->configEmail); + } parent::tearDown(); } diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 01d0ce3b9..fb4022b50 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -28,18 +28,10 @@ public function setUp() { $this->traitClassName = 'CakeDC\Users\Controller\Traits\RegisterTrait'; $this->traitMockMethods = ['validate', 'dispatchEvent', 'set', 'validateReCaptcha', 'redirect']; + $this->mockDefaultEmail = true; parent::setUp(); Plugin::routes('CakeDC/Users'); - - Email::configTransport('test', [ - 'className' => 'Debug' - ]); - $this->configEmail = Email::config('default'); - Email::config('default', [ - 'transport' => 'test', - 'from' => 'cakedc@example.com' - ]); } /** @@ -49,10 +41,6 @@ public function setUp() */ public function tearDown() { - Email::drop('default'); - Email::dropTransport('test'); - Email::config('default', $this->configEmail); - parent::tearDown(); } diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index ba2d39837..b15197a0e 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -25,6 +25,7 @@ public function setUp() { $this->traitClassName = 'CakeDC\Users\Controller\Traits\UserValidationTrait'; $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; + $this->mockDefaultEmail = true; parent::setUp(); } diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index 4f3b9d439..c4c61271e 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -43,10 +43,7 @@ class SocialAccountsTableTest extends TestCase public function setUp() { parent::setUp(); - $config = TableRegistry::exists('SocialAccounts') ? [] : [ - 'className' => 'CakeDC\Users\Model\Table\SocialAccountsTable' - ]; - $this->SocialAccounts = TableRegistry::get('SocialAccounts', $config); + $this->SocialAccounts = TableRegistry::get('CakeDC/Users.SocialAccounts'); $this->fullBaseBackup = Router::fullBaseUrl(); Router::fullBaseUrl('http://users.test'); Email::configTransport('test', [ @@ -105,47 +102,13 @@ public function testValidateEmailInvalidUser() /** * Test validateEmail method * - * @expectedException \Users\Exception\AccountAlreadyActiveException + * @expectedException CakeDC\Users\Exception\AccountAlreadyActiveException */ public function testValidateEmailActiveAccount() { $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); } - /** - * testAfterSaveSocialNotActiveUserNotActive - * don't send email, user is not active - * - * @return void - */ - public function testAfterSaveSocialNotActiveUserNotActive() - { - $event = new Event('eventName'); - $entity = $this->SocialAccounts->find()->first(); - $this->assertTrue($this->SocialAccounts->afterSave($event, $entity, [])); - } - - /** - * testAfterSaveSocialNotActiveUserActive - * send email here, social account is not active, - * and user is active we need to link the account - * - * @return void - */ - public function testAfterSaveSocialNotActiveUserActive() - { - $this->markTestIncomplete('fix this test after SocialBehavior done'); - $event = new Event('eventName'); - $entity = $this->SocialAccounts->findById(5)->first(); - $this->SocialAccounts->Users = $this->getMockForModel('CakeDC/Users.Users', ['getEmailInstance']); - $this->SocialAccounts->Users->expects($this->once()) - ->method('getEmailInstance') - ->will($this->returnValue($this->Email)); - $result = $this->SocialAccounts->afterSave($event, $entity, []); - $this->assertTextContains('Subject: FirstName4, Your social account validation link', $result['headers']); - unset($this->SocialAccounts->Users); - } - /** * Test sendSocialValidationEmail method * diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 41cba2133..08731b0ff 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -53,6 +53,11 @@ public function setUp() Email::configTransport('test', [ 'className' => 'Debug' ]); + $this->configEmail = Email::config('default'); + Email::config('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); Plugin::routes('CakeDC/Users'); } @@ -66,7 +71,9 @@ public function tearDown() { unset($this->Users); Router::fullBaseUrl($this->fullBaseBackup); + Email::drop('default'); Email::dropTransport('test'); + Email::config('default', $this->configEmail); parent::tearDown(); } From 93ed73bf95a39ea074f933e60084fdc5e19d0135 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 08:51:17 +0000 Subject: [PATCH 0236/1476] move tests to behavior --- .../Behavior/SocialAccountBehaviorTest.php | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index f3e853787..0e1e59883 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -12,7 +12,9 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; use Cake\Event\Event; +use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; +use Cake\Routing\Router; use Cake\TestSuite\TestCase; use InvalidArgumentException; use CakeDC\Users\Model\Table\SocialAccountsTable; @@ -44,6 +46,16 @@ public function setUp() $table->addBehavior('CakeDC/Users.SocialAccount'); $this->Table = $table; $this->Behavior = $table->behaviors()->SocialAccount; + $this->fullBaseBackup = Router::fullBaseUrl(); + Router::fullBaseUrl('http://users.test'); + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->Email = new Email([ + 'from' => 'test@example.com', + 'transport' => 'test', + 'template' => 'CakeDC/Users.social_account_validation', + ]); } /** @@ -53,7 +65,9 @@ public function setUp() */ public function tearDown() { - unset($this->table, $this->Behavior); + unset($this->Table, $this->Behavior, $this->Email); + Router::fullBaseUrl($this->fullBaseBackup); + Email::dropTransport('test'); parent::tearDown(); } @@ -138,4 +152,22 @@ public function testAfterSaveSocialActiveUserNotActive() $entity = $this->Table->findById(2)->first(); $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); } + + /** + * Test sendSocialValidationEmail method + * + * @return void + */ + public function testSendSocialValidationEmail() + { + $user = $this->Table->find()->contain('Users')->first(); + $this->Email->emailFormat('both'); + $result = $this->Behavior->sendSocialValidationEmail($user, $user->user, $this->Email); + $this->assertTextContains('From: test@example.com', $result['headers']); + $this->assertTextContains('To: user-1@test.com', $result['headers']); + $this->assertTextContains('Subject: first1, Your social account validation link', $result['headers']); + $this->assertTextContains('Hi first1,', $result['message']); + $this->assertTextContains('Activate your social login here', $result['message']); + $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234', $result['message']); + } } From 357a3bc1afbcc7b968c89c179643a2ed1b1e1970 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 09:02:24 +0000 Subject: [PATCH 0237/1476] add test to SocialAccountsTable --- .../Model/Table/SocialAccountsTableTest.php | 78 +++---------------- 1 file changed, 11 insertions(+), 67 deletions(-) diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index c4c61271e..5e844ba95 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -44,12 +44,6 @@ public function setUp() { parent::setUp(); $this->SocialAccounts = TableRegistry::get('CakeDC/Users.SocialAccounts'); - $this->fullBaseBackup = Router::fullBaseUrl(); - Router::fullBaseUrl('http://users.test'); - Email::configTransport('test', [ - 'className' => 'Debug' - ]); - $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); } /** @@ -60,71 +54,21 @@ public function setUp() public function tearDown() { unset($this->SocialAccounts); - Router::fullBaseUrl($this->fullBaseBackup); - Email::dropTransport('test'); parent::tearDown(); } - /** - * Test validateEmail method - * - * @return void - */ - public function testValidateEmail() - { - $token = 'token-1234'; - $result = $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_FACEBOOK, 'reference-1-1234', $token); - $this->assertTrue($result->active); - $this->assertEquals($token, $result->token); - } - - /** - * Test validateEmail method - * - * @expectedException \Cake\Datasource\Exception\RecordNotFoundException - */ - public function testValidateEmailInvalidToken() - { - $this->SocialAccounts->validateAccount(1, 'reference-1234', 'invalid-token'); - } - - /** - * Test validateEmail method - * - * @expectedException \Cake\Datasource\Exception\RecordNotFoundException - */ - public function testValidateEmailInvalidUser() - { - $this->SocialAccounts->validateAccount(1, 'invalid-user', 'token-1234'); - } - - /** - * Test validateEmail method - * - * @expectedException CakeDC\Users\Exception\AccountAlreadyActiveException - */ - public function testValidateEmailActiveAccount() - { - $this->SocialAccounts->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); - } - - /** - * Test sendSocialValidationEmail method - * - * @return void - */ - public function testSendSocialValidationEmail() + public function testValidationHappy() { - $this->markTestIncomplete('move to SocialAccountBehaviorTest'); - $user = $this->SocialAccounts->find()->contain('Users')->first(); - $this->Email->emailFormat('both'); - $result = $this->SocialAccounts->sendSocialValidationEmail($user, $user->user, $this->Email); - $this->assertTextContains('From: test@example.com', $result['headers']); - $this->assertTextContains('To: user-1@test.com', $result['headers']); - $this->assertTextContains('Subject: first1, Your social account validation link', $result['headers']); - $this->assertTextContains('Hi first1,', $result['message']); - $this->assertTextContains('Activate your social login here', $result['message']); - $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234', $result['message']); + $data = [ + 'provider' => 'Facebook', + 'reference' => 'test-reference', + 'link' => 'test-link', + 'token' => 'test-token', + 'active' => 0, + 'data' => 'test-data', + ]; + $entity = $this->SocialAccounts->newEntity($data); + $this->assertEmpty($entity->errors()); } } From 7590926e7772eddca97d18e67789a6f322e46c5f Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 09:20:37 +0000 Subject: [PATCH 0238/1476] move tests to behavior --- .../Model/Behavior/PasswordBehaviorTest.php | 69 ++++++++++++ tests/TestCase/Model/Table/UsersTableTest.php | 103 ------------------ 2 files changed, 69 insertions(+), 103 deletions(-) diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index ca111abdc..6960a849b 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -11,7 +11,9 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; +use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; +use Cake\Routing\Router; use Cake\TestSuite\TestCase; use InvalidArgumentException; use CakeDC\Users\Exception\UserAlreadyActiveException; @@ -141,4 +143,71 @@ public function testResetTokenUserAlreadyActive() 'checkActive' => true, ]); } + + /** + * Test method + * + * @return void + */ + public function testSendResetPasswordEmail() + { + $behavior = $this->table->behaviors()->Password; + $this->fullBaseBackup = Router::fullBaseUrl(); + Router::fullBaseUrl('http://users.test'); + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + $this->Email = new Email([ + 'from' => 'test@example.com', + 'transport' => 'test', + 'template' => 'CakeDC/Users.reset_password', + 'emailFormat' => 'both', + ]); + + $user = $this->table->newEntity([ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]); + + $result = $behavior->sendResetPasswordEmail($user, $this->Email, 'CakeDC/Users.reset_password'); + $this->assertTextContains('From: test@example.com', $result['headers']); + $this->assertTextContains('To: test@example.com', $result['headers']); + $this->assertTextContains('Subject: FirstName, Your reset password link', $result['headers']); + $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Hi FirstName, + +Please copy the following address in your web browser http://users.test/users/users/reset-password/12345 +Thank you, +', $result['message']); + $this->assertTextContains('Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + + + + Email/html + + +

+Hi FirstName, +

+

+ Reset your password here +

+

+ If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/reset-password/12345

+

+ Thank you, +

+ + +', $result['message']); + + Router::fullBaseUrl($this->fullBaseBackup); + Email::dropTransport('test'); + } + } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 08731b0ff..4dc03d585 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -291,109 +291,6 @@ public function _testSocialLoginCreateNewAccount() $this->assertEquals('Last Name', $result->last_name); } - /** - * Test sendValidationEmail method - * - * @return void - */ - public function testSendValidationEmail() - { - $this->markTestIncomplete('move this unit test to the BehaviorTest class'); - $user = $this->Users->newEntity([ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]); - $this->Email->template('CakeDC/Users.validation') - ->emailFormat('both'); - - $result = $this->Users->sendValidationEmail($user, $this->Email); - $this->assertTextContains('From: test@example.com', $result['headers']); - $this->assertTextContains('To: test@example.com', $result['headers']); - $this->assertTextContains('Subject: FirstName, Your account validation link', $result['headers']); - $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Hi FirstName, - -Please copy the following address in your web browser http://users.test/users/users/validate-email/12345 -Thank you, -', $result['message']); - $this->assertTextContains('Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: 8bit - - - - - Email/html - - -

-Hi FirstName, -

-

- Activate your account here -

-

- If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/validate-email/12345

-

- Thank you, -

- - -', $result['message']); - } - - /** - * Test method - * - * @return void - */ - public function testSendResetPasswordEmail() - { - $user = $this->Users->newEntity([ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]); - $this->Email->template('CakeDC/Users.reset_password') - ->emailFormat('both'); - $result = $this->Users->sendResetPasswordEmail($user, $this->Email, 'CakeDC/Users.reset_password'); - $this->assertTextContains('From: test@example.com', $result['headers']); - $this->assertTextContains('To: test@example.com', $result['headers']); - $this->assertTextContains('Subject: FirstName, Your reset password link', $result['headers']); - $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Hi FirstName, - -Please copy the following address in your web browser http://users.test/users/users/reset-password/12345 -Thank you, -', $result['message']); - $this->assertTextContains('Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: 8bit - - - - - Email/html - - -

-Hi FirstName, -

-

- Reset your password here -

-

- If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/reset-password/12345

-

- Thank you, -

- - -', $result['message']); - } /** * testGetEmailInstance From f0e2554854e47b8ea996d3ce005894a56ebfb004 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 09:20:53 +0000 Subject: [PATCH 0239/1476] fix weird initialization --- tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index 0e1e59883..4e5382595 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -42,10 +42,8 @@ class SocialAccountBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $table = TableRegistry::get('CakeDC/Users.SocialAccounts'); - $table->addBehavior('CakeDC/Users.SocialAccount'); - $this->Table = $table; - $this->Behavior = $table->behaviors()->SocialAccount; + $this->Table = TableRegistry::get('CakeDC/Users.SocialAccounts'); + $this->Behavior = $this->Table->behaviors()->SocialAccount; $this->fullBaseBackup = Router::fullBaseUrl(); Router::fullBaseUrl('http://users.test'); Email::configTransport('test', [ From 67fb65d5cea22fa6ce216c59fa94552f84d440e8 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 09:23:00 +0000 Subject: [PATCH 0240/1476] remove tests on protected methods after refactor --- tests/TestCase/Model/Table/UsersTableTest.php | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 4dc03d585..55a1230e5 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -290,39 +290,4 @@ public function _testSocialLoginCreateNewAccount() $this->assertEquals('First Name', $result->first_name); $this->assertEquals('Last Name', $result->last_name); } - - - /** - * testGetEmailInstance - * - * @return void - */ - public function testGetEmailInstance() - { - $this->markTestIncomplete('move this test to BehaviorTest class'); - $email = $this->Users->getEmailInstance(); - $this->assertInstanceOf('Cake\Network\Email\Email', $email); - $this->assertEquals([ - 'template' => 'Users.validation', - 'layout' => 'default' - ], $email->template()); - } - - /** - * testGetEmailInstanceOverrideEmail - * - * @return void - */ - public function testGetEmailInstanceOverrideEmail() - { - $this->markTestIncomplete('move this test to BehaviorTest class'); - $email = new Email(); - $email->template('another_template'); - $email = $this->Users->getEmailInstance($email); - $this->assertInstanceOf('Cake\Network\Email\Email', $email); - $this->assertEquals([ - 'template' => 'another_template', - 'layout' => 'default' - ], $email->template()); - } } From fc3106019dd70f2eda7fc58109cd7d47bc02b981 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 09:33:35 +0000 Subject: [PATCH 0241/1476] fix default table used in config --- config/users.php | 2 +- tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/users.php b/config/users.php index 9d21a930e..aefecdfc9 100644 --- a/config/users.php +++ b/config/users.php @@ -14,7 +14,7 @@ $config = [ 'Users' => [ //Table used to manage users - 'table' => 'Users.Users', + 'table' => 'CakeDC/Users.Users', //configure Auth component 'auth' => true, //Password Hasher diff --git a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php index 4657d590c..90f142699 100644 --- a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php +++ b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php @@ -34,7 +34,7 @@ public function tearDown() public function testGetUsersTable() { $table = $this->controller->Trait->getUsersTable(); - $this->assertEquals('Users.Users', $table->registryAlias()); + $this->assertEquals('CakeDC/Users.Users', $table->registryAlias()); $newTable = new Table(); $this->controller->Trait->setUsersTable($newTable); $this->assertSame($newTable, $this->controller->Trait->getUsersTable()); From ced7f599608d06eaa963e70b9610dd21fff0a72b Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 09:36:42 +0000 Subject: [PATCH 0242/1476] fix placeholder reference --- config/users.php | 2 +- tests/TestCase/Controller/Traits/ProfileTraitTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/users.php b/config/users.php index aefecdfc9..2b5e8de7f 100644 --- a/config/users.php +++ b/config/users.php @@ -67,7 +67,7 @@ ], ], //Avatar placeholder - 'Avatar' => ['placeholder' => 'Users.avatar_placeholder.png'], + 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], 'RememberMe' => [ //configure Remember Me component 'active' => true, diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index e9b6c9222..8ac352971 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -103,7 +103,7 @@ public function testProfileGetLoggedInMyProfile() ->method('set') ->will($this->returnCallback(function ($param1, $param2 = null) { if ($param1 === 'avatarPlaceholder') { - BaseTraitTest::assertEquals('Users.avatar_placeholder.png', $param2); + BaseTraitTest::assertEquals('CakeDC/Users.avatar_placeholder.png', $param2); } elseif (is_array($param1)) { BaseTraitTest::assertEquals('user-1', $param1['user']->username); } From cfb476f37e30b0ea60adfbb14cbbd6eb49d69a26 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 10:15:49 +0000 Subject: [PATCH 0243/1476] fix docs installation --- Docs/Documentation/Installation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index c6fffb0d1..c63fb88ed 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -21,11 +21,11 @@ Creating Required Tables If you want to use the Users tables to store your users and social accounts: ``` -bin/cake migrations migrate -p Users +bin/cake migrations migrate -p CakeDC/Users ``` Note you don't need to use the provided tables, you could customize the table names, fields etc in your -application and then use the plugin configuration to use your own tables instead. Please refer to the [Extending the Plugin](Extending-the-Plugin.md) +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 @@ -34,7 +34,7 @@ Load the Plugin Ensure the Users Plugin is loaded in your config/bootstrap.php file ``` -Plugin::load('Users', ['routes' => true, 'bootstrap' => true]); +Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); ``` Customization @@ -43,7 +43,7 @@ Customization config/bootstrap.php ``` Configure::write('Users.config', ['users']); -Plugin::load('Users', ['routes' => true, 'bootstrap' => true]); +Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); ``` Then in your config/users.php @@ -67,7 +67,7 @@ Load the Component in your src/Controller/AppController.php, and use the passed { parent::initialize(); $this->loadComponent('Flash'); - $this->loadComponent('Users.UsersAuth'); + $this->loadComponent('CakeDC/Users.UsersAuth'); } ``` From 74d88c223eb43c804a2e0a0dd2b32eefdac7ee3f Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 10:27:18 +0000 Subject: [PATCH 0244/1476] fix configuration docs --- Docs/Documentation/Configuration.md | 29 ++++++++++++++--------------- config/users.php | 8 ++++++-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index b8b907374..2d98fafa9 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -9,7 +9,7 @@ For easier configuration, you can specify an array of config files to override t config/bootstrap.php ``` Configure::write('Users.config', ['users']); -Plugin::load('Users', ['routes' => true, 'bootstrap' => true]); +Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); ``` Then in your config/users.php @@ -17,6 +17,8 @@ Then in your config/users.php return [ 'Opauth.Strategy.Facebook.app_id' => 'YOUR APP ID', 'Opauth.Strategy.Facebook.app_secret' => 'YOUR APP SECRET', + 'Opauth.Strategy.Twitter.key' => 'YOUR APP KEY', + 'Opauth.Strategy.Twitter.secret' => 'YOUR APP SECRET', //etc ]; ``` @@ -43,18 +45,15 @@ 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, +Loading the UsersAuthComponent and using the right configuration values will setup the Users plugin, the AuthComponent and the Opauth component for your application. If you prefer to setup AuthComponent by yourself, you'll need to load AuthComponent before UsersAuthComponent -and set +and set ``` Configure::write('Users.auth', false); ``` - - - Interesting UsersAuthComponent options and defaults NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/users/config/users.php` for the complete list @@ -62,7 +61,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use ``` 'Users' => [ //Table used to manage users - 'table' => 'Users.Users', + 'table' => 'CakeDC/Users.Users', //configure Auth component 'auth' => true, 'Email' => [ @@ -86,7 +85,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'login' => true, ], //Avatar placeholder - 'Avatar' => ['placeholder' => 'Users.avatar_placeholder.png'], + 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], 'RememberMe' => [ //configure Remember Me component 'active' => true, @@ -98,12 +97,12 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'all' => [ 'scope' => ['active' => 1] ], - 'Users.RememberMe', + 'CakeDC/Users.RememberMe', 'Form', ], 'authorize' => [ - 'Users.Superuser', - 'Users.SimpleRbac', + 'CakeDC/Users.Superuser', + 'CakeDC/Users.SimpleRbac', ], ], ]; @@ -128,16 +127,16 @@ Email Templates To modify the templates as needed copy them to your application ``` -cp -r vendor/cakedc/users/src/Template/Email/* src/Template/Plugin/Users/Email/ +cp -r vendor/cakedc/users/src/Template/Email/* src/Template/Plugin/CakeDC/Users/Email/ ``` -Then customize the email templates as you need under the src/Template/Plugin/Users/Email/ directory +Then customize the email templates as you need under the src/Template/Plugin/CakeDC/Users/Email/ directory Plugin Templates --------------- Similar to Email Templates customization, follow the CakePHP conventions to put your new templates under -src/Template/Plugin/Users/[Controller]/[view].ctp +src/Template/Plugin/CakeDC/Users/[Controller]/[view].ctp Check http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application @@ -145,7 +144,7 @@ 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 http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#setting-up-translations for more details about how the PO files should be managed in your application. We've included an updated POT file with all the `Users` domain keys for your customization. \ No newline at end of file diff --git a/config/users.php b/config/users.php index 2b5e8de7f..a9a602d45 100644 --- a/config/users.php +++ b/config/users.php @@ -106,11 +106,15 @@ 'complete_url' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], 'Strategy' => [ 'Facebook' => [ - 'scope' => ['public_profile', 'user_friends', 'email'] + 'scope' => ['public_profile', 'user_friends', 'email'], + //app_id => 'YOUR_APP_ID', + //app_secret = 'YOUR_APP_SECRET', ], 'Twitter' => [ 'curl_cainfo' => false, - 'curl_capath' => false + 'curl_capath' => false, + //'key' => 'YOUR_APP_KEY', + //'secret' => 'YOUR_APP_SECRET', ] ] ] From 8d2f778f4f50968241d67d32bfad3b45070cd4a5 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 11:05:52 +0000 Subject: [PATCH 0245/1476] fix social validation email template wrong --- src/Controller/Traits/SocialTrait.php | 4 ++-- src/Model/Behavior/Behavior.php | 12 +++++++----- src/Model/Behavior/SocialAccountBehavior.php | 7 +++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 56c1c7fc1..2a5f9bf26 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -39,7 +39,7 @@ public function opauthInit($callback = null) } $url = $this->_generateOpauthCompleteUrl(); $this->request->session()->write(Configure::read('Users.Key.Session.social'), $response); - $this->redirect($url); + return $this->redirect($url); } /** @@ -54,7 +54,7 @@ protected function _generateOpauthCompleteUrl() $url = Router::parse($url); } $url['?'] = ['social' => $this->request->query('code')]; - return Router::url($url); + return Router::url($url, true); } /** diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index e295dc273..a8379b076 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -36,11 +36,14 @@ class Behavior extends BaseBehavior protected function _sendEmail(EntityInterface $user, $subject, Email $email = null) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - return $this->_getEmailInstance($email) + $emailInstance = $this->_getEmailInstance($email) ->to($user['email']) ->subject($firstName . $subject) - ->viewVars($user->toArray()) - ->send(); + ->viewVars($user->toArray()); + if (empty($email)) { + $emailInstance->template('CakeDC/Users.validation'); + } + return $emailInstance->send(); } /** @@ -53,8 +56,7 @@ protected function _getEmailInstance(Email $email = null) { if ($email === null) { $email = new Email('default'); - $email->template('CakeDC/Users.validation') - ->emailFormat('both'); + $email->emailFormat('both'); } return $email; diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index ad6a9d7f1..046c70749 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -77,11 +77,14 @@ public function afterSave(Event $event, Entity $entity, $options) */ public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) { - $email = $this->_getEmailInstance($email); + $emailInstance = $this->_getEmailInstance($email); + if (empty($email)) { + $emailInstance->template('CakeDC/Users.social_account_validation'); + } $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; //note: we control the space after the username in the previous line $subject = __d('Users', '{0}Your social account validation link', $firstName); - return $email + return $emailInstance ->to($user['email']) ->subject($subject) ->viewVars(compact('user', 'socialAccount')) From 49c0c221ddbb8dd8769117ea6e32aa1fa14a0c59 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 14 Sep 2015 23:35:14 +0000 Subject: [PATCH 0246/1476] fix docs --- Docs/Documentation/Events.md | 14 ++++++++------ Docs/Documentation/Extending-the-Plugin.md | 14 +++++++------- Docs/Documentation/Installation.md | 4 ++-- Docs/Documentation/SimpleRbacAuthorize.md | 5 ++--- Docs/Home.md | 7 +++---- README.md | 12 +++++++----- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index ea16d4c34..13e810165 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -3,14 +3,16 @@ Events The events in this plugin follow these conventions ...: -* 'Users.Component.UsersAuth.isAuthorized'; -* 'Users.Component.UsersAuth.beforeLogin'; -* 'Users.Component.UsersAuth.afterLogin'; +* '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.beforeRegister' +* 'Users.Component.UsersAuth.afterRegister' +* 'Users.Component.UsersAuth.beforeLogout' +* 'Users.Component.UsersAuth.afterLogout' -The events allow you to inject data into the plugin on the before* plugins and use the data for your +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 ``` diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index fc2610c4c..824bf69b4 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -4,9 +4,9 @@ Extending the Plugin Extending the Model (Table/Entity) ------------------- -Create a new Table and Entity in your app, matching the table you want to use for storing the +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 +If your column names doesn't match the columns in your current table, you could use the Entity to match the colums using accessors & mutators as described here http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators Example: we are going to use a custom table in our application ```my_users``` @@ -15,7 +15,7 @@ Example: we are going to use a custom table in our application ```my_users``` ```php namespace App\Model\Table; -use Users\Model\Table\UsersTable; +use CakeDC\Users\Model\Table\UsersTable; /** * Users Model @@ -29,7 +29,7 @@ class MyUsersTable extends UsersTable ```php namespace App\Model\Entity; -use Users\Model\Entity\User; +use CakeDC\Users\Model\Entity\User; class MyUser extends User { @@ -89,9 +89,9 @@ namespace App\Controller; use App\Controller\AppController; use App\Model\Table\MyUsersTable; use Cake\Event\Event; -use Users\Controller\Component\UsersAuthComponent; -use Users\Controller\Traits\LoginTrait; -use Users\Controller\Traits\RegisterTrait; +use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Controller\Traits\LoginTrait; +use CakeDC\Users\Controller\Traits\RegisterTrait; class MyUsersController extends AppController { diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index c63fb88ed..f44ff1148 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -51,6 +51,8 @@ Then in your config/users.php return [ 'Opauth.Strategy.Facebook.app_id' => 'YOUR APP ID', 'Opauth.Strategy.Facebook.app_secret' => 'YOUR APP SECRET', + 'Opauth.Strategy.Twitter.key' => 'YOUR APP KEY', + 'Opauth.Strategy.Twitter.secret' => 'YOUR APP SECRET', //etc ]; ``` @@ -70,5 +72,3 @@ Load the Component in your src/Controller/AppController.php, and use the passed $this->loadComponent('CakeDC/Users.UsersAuth'); } ``` - - diff --git a/Docs/Documentation/SimpleRbacAuthorize.md b/Docs/Documentation/SimpleRbacAuthorize.md index e236f9a6f..d029bcca5 100644 --- a/Docs/Documentation/SimpleRbacAuthorize.md +++ b/Docs/Documentation/SimpleRbacAuthorize.md @@ -1,4 +1,3 @@ -@todo: callbacks SimpleRbacAuthorize ============= @@ -36,14 +35,14 @@ $config['Auth']['authorize']['Users.SimpleRbac'] = [ ``` This is the default configuration, based on it the Authorize object will first check your ```config/permissions.php``` -file and load the permissions using the configuration key ```Users.SimpleRbac.permissions```, there is an +file and load the permissions using the configuration key ```Users.SimpleRbac.permissions```, there is an example file you can copy into your ```config/permissions.php``` under the Plugin's config directory. If you don't want to use a file for configuring the permissions, you just need to tweak the configuration and set ```'autoload_config' => false,``` then define all your rules in AppController (not a good practice as the rules tend to grow over time). -The Users Plugin will use the field ```role_field``` in the Users Table to match the role of the user and +The Users Plugin will use the field ```role_field``` in the Users Table to match the role of the user and check if there is a rule allowing him to access the url. The ```default_role``` will be used to set the role of the registered users by default. diff --git a/Docs/Home.md b/Docs/Home.md index f4f35761d..3ae1db423 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -1,15 +1,14 @@ Home ==== -IMPORANT: Current status is **ALPHA**. We are working now on improving the unit test coverage and docs +IMPORANT: Current status is **BETA**. We are still working on improving the unit test coverage and docs Plugin is usable now if you want to download and take a look. PRs and Issues welcome! -The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. +The **Users** Plugin allow users to register and login, manage their profile, etc. It also allows admins to manage the users. The plugin is thought as a base to extend your app specific users controller and model from. -That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. -Read the instructions carefully. +That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. Requirements ------------ diff --git a/README.md b/README.md index 126b7bff6..ad114812f 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ CakeDC Users Plugin [![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) -IMPORTANT: 3.x version is ALPHA status now, we are improving and testing it now. +IMPORTANT: 3.x version is BETA status now, we are still improving and testing it. -The **Users** plugin is back! +The **Users** plugin is back! It covers the following features: -* User registration +* User registration * Login/logout * Social login (Facebook, Twitter) * Simple RBAC @@ -25,7 +25,7 @@ The plugin is here to provide users related features following 2 approaches: * Use your own UsersTable * Use your own Controller -On the previous versions of the plugin, extensibility was an issue, and one of the main +On the previous versions of the plugin, extensibility was an issue, and one of the main objectives of the 3.0 rewrite is to guarantee all the pieces could be extended/reused as easily. @@ -50,8 +50,10 @@ Roadmap * Unit test coverage improvements * Refactor UsersTable to Behavior * Add google authentication - * Add captcha + * Add reCaptcha * Link social accounts in profile +* 3.0.2 Add google authentication + * Improve unit test coverage Support ------- From 591eb853948e96dfd387da995d28cb122910cb04 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 21 Sep 2015 01:09:54 +0000 Subject: [PATCH 0247/1476] fix facebook login to create a default link to profile if missing because of privacy settings in facebook --- src/Model/Behavior/SocialBehavior.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index dae415757..9ab379604 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -29,6 +29,11 @@ class SocialBehavior extends Behavior { use RandomStringTrait; + /** + * Used to create a default profile link if not available in raw data returned by FB + */ + const FACEBOOK_SCOPED_ID_URL = "https://www.facebook.com/app_scoped_user_id/"; + /** * Performs social login * @@ -80,6 +85,7 @@ protected function _createSocialUser($data, $options = []) $useEmail = Hash::get($options, 'use_email'); $validateEmail = Hash::get($options, 'validate_email'); $tokenExpiration = Hash::get($options, 'token_expiration'); + $existingUser = null; if ($useEmail && empty($data->email)) { throw new MissingEmailException(__d('Users', 'Email not present')); } else { @@ -114,7 +120,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail if ($data->provider == SocialAccountsTable::PROVIDER_TWITTER) { $accountData['link'] = Hash::get($data->info, 'urls.twitter'); } elseif ($data->provider == SocialAccountsTable::PROVIDER_FACEBOOK) { - $accountData['link'] = Hash::get($data->raw, 'link'); + $accountData['link'] = $this->_getFacebookLink($data->raw); } $accountData['avatar'] = str_replace('square', 'large', $accountData['avatar']); $accountData['description'] = Hash::get($data->info, 'description'); @@ -174,6 +180,20 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail return $user; } + /** + * Create a link for facebook profile + */ + protected function _getFacebookLink($raw = []) + { + $link = Hash::get((array)$raw, 'link'); + if (!empty($link)) { + return $link; + } + + $id = Hash::get((array)$raw, 'id'); + return self::FACEBOOK_SCOPED_ID_URL . $id; + } + /** * Checks if username exists and generate a new one * From 306154708fe2def3d26de13c2fe78cc586986758 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 21 Sep 2015 14:16:18 +0000 Subject: [PATCH 0248/1476] minor refactor to get rid of return value in write context --- src/Controller/Traits/LoginTrait.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 8fe664e70..d29977610 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; +use Cake\Utility\Hash; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -80,13 +81,15 @@ protected function _afterIdentifyUser($user, $socialLogin = false) $message = __d('Users', 'Username or password is incorrect'); if ($socialLogin) { $socialData = $this->request->session()->check($socialKey); + $socialDataEmail = Hash::get((array)$socialData->info, Configure::read('data_email_key')); + $postedEmail = $this->request->data(Configure::read('Users.Key.Data.email')); if (Configure::read('Users.Email.required') && - empty($socialData->info[Configure::read('data_email_key')]) && - empty($this->request->data(Configure::read('Users.Key.Data.email')))) { - return $this->redirect([ - 'controller' => 'Users', - 'action' => 'socialEmail' - ]); + empty($socialDataEmail) && + empty($postedEmail)) { + return $this->redirect([ + 'controller' => 'Users', + 'action' => 'socialEmail' + ]); } else { $message = __d('Users', 'There was an error associating your social network account'); } From 05db926c68405c9706ee7a45bbc65fb4806a241f Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 21 Sep 2015 14:42:19 +0000 Subject: [PATCH 0249/1476] fix return value in write context --- src/Controller/Component/RememberMeComponent.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 18f342203..4f318abe1 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -132,7 +132,8 @@ public function destroy(Event $event) */ public function beforeFilter(Event $event) { - if (!empty($this->Auth->user()) || $this->request->is(['post', 'put']) || $this->request->action === 'logout' || $this->request->session()->check(Configure::read('Users.Key.Session.social'))) { + $user = $this->Auth->user(); + if (!empty($user) || $this->request->is(['post', 'put']) || $this->request->action === 'logout' || $this->request->session()->check(Configure::read('Users.Key.Session.social'))) { return; } From 2ae696995df30a49b49ff1122484bcf0ac534ef9 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 21 Sep 2015 14:58:33 +0000 Subject: [PATCH 0250/1476] fix some more write context issues --- src/Controller/Component/UsersAuthComponent.php | 5 +++-- src/Model/Behavior/PasswordBehavior.php | 7 ++++--- src/Model/Behavior/SocialBehavior.php | 14 +++++++++----- src/Template/Users/profile.ctp | 3 ++- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 7d375a874..cf5bd907e 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -43,7 +43,7 @@ public function initialize(array $config) $this->_validateConfig(); $this->_initAuth(); - if (Configure::read('Users.Social.login') && !empty(Configure::read('Opauth'))) { + if (Configure::read('Users.Social.login') && Configure::read('Opauth')) { $this->_configOpauthRoutes(); } if (Configure::read('Users.Social.login')) { @@ -122,7 +122,8 @@ protected function _initAuth() */ public function isUrlAuthorized(Event $event) { - if (empty($this->_registry->getController()->Auth->user())) { + $user = $this->_registry->getController()->Auth->user(); + if (empty($user)) { return false; } $url = Hash::get((array)$event->data, 'url'); diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index fd6c56169..de3794c76 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -42,8 +42,9 @@ public function resetToken($reference, array $options = []) throw new InvalidArgumentException(__d('Users', "Reference cannot be null")); } - if (empty(Hash::get($options, 'expiration'))) { - throw new InvalidArgumentException(__d('Users', "Token expiration cannot be null")); + $expiration = Hash::get($options, 'expiration'); + if (empty($expiration)) { + throw new InvalidArgumentException(__d('Users', "Token expiration cannot be empty")); } $user = $this->_getUser($reference); @@ -58,7 +59,7 @@ public function resetToken($reference, array $options = []) $user->active = false; $user->activation_date = null; } - $user->updateToken(Hash::get($options, 'expiration')); + $user->updateToken($expiration); $saveResult = $this->_table->save($user); $template = !empty($options['emailTemplate']) ? $options['emailTemplate'] : 'CakeDC/Users.reset_password'; if (Hash::get($options, 'sendEmail')) { diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 9ab379604..fa43fe77b 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -126,14 +126,17 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $accountData['description'] = Hash::get($data->info, 'description'); $accountData['token'] = Hash::get((array)$data->credentials, 'token'); $accountData['token_secret'] = Hash::get((array)$data->credentials, 'secret'); - $accountData['token_expires'] = !empty(Hash::get((array)$data->credentials, 'expires')) ? (new DateTime(Hash::get((array)$data->credentials, 'expires')))->format('Y-m-d H:i:s') : null; + $expires = Hash::get((array)$data->credentials, 'expires'); + $accountData['token_expires'] = !empty($expires) ? (new DateTime($expires))->format('Y-m-d H:i:s') : null; $accountData['data'] = serialize($data->raw); $accountData['active'] = true; if (empty($existingUser)) { - if (!empty($data->info['first_name']) && !empty($data->info['last_name'])) { - $userData['first_name'] = Hash::get($data->info, 'first_name'); - $userData['last_name'] = Hash::get($data->info, 'last_name'); + $firstName = Hash::get($data->info, 'first_name'); + $lastName = Hash::get($data->info, 'last_name'); + if (!empty($firstName) && !empty($lastName)) { + $userData['first_name'] = $firstName; + $userData['last_name'] = $lastName; } else { $name = explode(' ', $data->name); $userData['first_name'] = Hash::get($name, 0); @@ -141,7 +144,8 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['last_name'] = implode(' ', $name); } $userData['username'] = Hash::get($data->info, 'nickname'); - if (empty(Hash::get($userData, 'username'))) { + $username = Hash::get($userData, 'username'); + if (empty($username)) { if (!empty($data->email)) { $email = explode('@', $data->email); $userData['username'] = Hash::get($email, 0); diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index e2f1ec01b..59091709d 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -43,7 +43,8 @@ social_accounts as $socialAccount): - $linkText = empty(h($socialAccount->username)) ? __d('Users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) + $escapedUsername = h($socialAccount->username); + $linkText = empty($escapedUsername) ? __d('Users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) ?> Date: Mon, 21 Sep 2015 15:13:39 +0000 Subject: [PATCH 0251/1476] check object property exists before read --- src/Controller/Traits/LoginTrait.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index d29977610..88e86980e 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -80,8 +80,11 @@ protected function _afterIdentifyUser($user, $socialLogin = false) } else { $message = __d('Users', 'Username or password is incorrect'); if ($socialLogin) { - $socialData = $this->request->session()->check($socialKey); - $socialDataEmail = Hash::get((array)$socialData->info, Configure::read('data_email_key')); + $socialData = $this->request->session()->read($socialKey); + $socialDataEmail = null; + if (!empty($socialData->info)) { + $socialDataEmail = Hash::get((array)$socialData->info, Configure::read('data_email_key')); + } $postedEmail = $this->request->data(Configure::read('Users.Key.Data.email')); if (Configure::read('Users.Email.required') && empty($socialDataEmail) && @@ -90,9 +93,8 @@ protected function _afterIdentifyUser($user, $socialLogin = false) 'controller' => 'Users', 'action' => 'socialEmail' ]); - } else { - $message = __d('Users', 'There was an error associating your social network account'); } + $message = __d('Users', 'There was an error associating your social network account'); } $this->Flash->error($message, 'default', [], 'auth'); } From 5b62c19f07e553ffda639acb0bbaf66649f4c63e Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 00:57:30 +0000 Subject: [PATCH 0252/1476] use real uuids in tests too --- tests/Fixture/SocialAccountsFixture.php | 20 ++++++++-------- tests/Fixture/UsersFixture.php | 20 ++++++++-------- .../Auth/RememberMeAuthenticateTest.php | 2 +- .../Controller/Traits/BaseTraitTest.php | 4 ++-- .../Traits/PasswordManagementTraitTest.php | 10 ++++---- .../Controller/Traits/SimpleCrudTraitTest.php | 24 +++++++++---------- .../Model/Behavior/RegisterBehaviorTest.php | 4 ++-- .../Behavior/SocialAccountBehaviorTest.php | 4 ++-- tests/TestCase/Model/Table/UsersTableTest.php | 2 +- 9 files changed, 45 insertions(+), 45 deletions(-) diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 838d3ba0c..19fdbde4e 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -48,8 +48,8 @@ class SocialAccountsFixture extends TestFixture */ public $records = [ [ - 'id' => 1, - 'user_id' => 1, + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', 'provider' => 'Facebook', 'username' => 'user-1-fb', 'reference' => 'reference-1-1234', @@ -64,8 +64,8 @@ class SocialAccountsFixture extends TestFixture 'modified' => '2015-05-22 21:52:44' ], [ - 'id' => 2, - 'user_id' => 1, + 'id' => '00000000-0000-0000-0000-000000000002', + 'user_id' => '00000000-0000-0000-0000-000000000001', 'provider' => 'Twitter', 'username' => 'user-1-tw', 'reference' => 'reference-1-1234', @@ -80,8 +80,8 @@ class SocialAccountsFixture extends TestFixture 'modified' => '2015-05-22 21:52:44' ], [ - 'id' => 3, - 'user_id' => 2, + 'id' => '00000000-0000-0000-0000-000000000003', + 'user_id' => '00000000-0000-0000-0000-000000000002', 'provider' => 'Facebook', 'username' => 'user-2-fb', 'reference' => 'reference-2-1', @@ -96,8 +96,8 @@ class SocialAccountsFixture extends TestFixture 'modified' => '2015-05-22 21:52:44' ], [ - 'id' => 4, - 'user_id' => 3, + 'id' => '00000000-0000-0000-0000-000000000004', + 'user_id' => '00000000-0000-0000-0000-000000000003', 'provider' => 'Twitter', 'username' => 'user-2-tw', 'reference' => 'reference-2-2', @@ -112,8 +112,8 @@ class SocialAccountsFixture extends TestFixture 'modified' => '2015-05-22 21:52:44' ], [ - 'id' => 5, - 'user_id' => 4, + 'id' => '00000000-0000-0000-0000-000000000005', + 'user_id' => '00000000-0000-0000-0000-000000000004', 'provider' => 'Twitter', 'username' => 'user-2-tw', 'reference' => 'reference-2-2', diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 296ce4d22..8ba1b1d9a 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -60,7 +60,7 @@ class UsersFixture extends TestFixture */ public $records = [ [ - 'id' => 1, + 'id' => '00000000-0000-0000-0000-000000000001', 'username' => 'user-1', 'email' => 'user-1@test.com', 'password' => '12345', @@ -78,7 +78,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 2, + 'id' => '00000000-0000-0000-0000-000000000002', 'username' => 'user-2', 'email' => 'user-2@test.com', 'password' => '12345', @@ -96,7 +96,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 3, + 'id' => '00000000-0000-0000-0000-000000000003', 'username' => 'user-3', 'email' => 'user-3@test.com', 'password' => '12345', @@ -114,7 +114,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 4, + 'id' => '00000000-0000-0000-0000-000000000004', 'username' => 'user-4', 'email' => '4@example.com', 'password' => 'Lorem ipsum dolor sit amet', @@ -132,7 +132,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 5, + 'id' => '00000000-0000-0000-0000-000000000005', 'username' => 'user-5', 'email' => 'test@example.com', 'password' => '12345', @@ -150,7 +150,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 6, + 'id' => '00000000-0000-0000-0000-000000000006', 'username' => 'Lorem ipsum dolor sit amet', 'email' => 'Lorem ipsum dolor sit amet', 'password' => 'Lorem ipsum dolor sit amet', @@ -168,7 +168,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 7, + 'id' => '00000000-0000-0000-0000-000000000007', 'username' => 'Lorem ipsum dolor sit amet', 'email' => 'Lorem ipsum dolor sit amet', 'password' => 'Lorem ipsum dolor sit amet', @@ -186,7 +186,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 8, + 'id' => '00000000-0000-0000-0000-000000000008', 'username' => 'Lorem ipsum dolor sit amet', 'email' => 'Lorem ipsum dolor sit amet', 'password' => 'Lorem ipsum dolor sit amet', @@ -204,7 +204,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 9, + 'id' => '00000000-0000-0000-0000-000000000009', 'username' => 'Lorem ipsum dolor sit amet', 'email' => 'Lorem ipsum dolor sit amet', 'password' => 'Lorem ipsum dolor sit amet', @@ -222,7 +222,7 @@ class UsersFixture extends TestFixture 'modified' => '2015-06-24 17:33:54' ], [ - 'id' => 10, + 'id' => '00000000-0000-0000-0000-000000000010', 'username' => 'Lorem ipsum dolor sit amet', 'email' => 'Lorem ipsum dolor sit amet', 'password' => 'Lorem ipsum dolor sit amet', diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php index 1d121c697..8e3b5d6ca 100644 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -82,7 +82,7 @@ public function testAuthenticateHappy() ->method('read') ->with('remember_me') ->will($this->returnValue([ - 'id' => 1, + 'id' => '00000000-0000-0000-0000-000000000001', 'user_agent' => 'user-agent' ])); $registry = new ComponentRegistry($this->controller); diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index e22c44a47..5905c7ee6 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -145,7 +145,7 @@ protected function _mockAuthLoggedIn() ->disableOriginalConstructor() ->getMock(); $user = [ - 'id' => 1, + 'id' => '00000000-0000-0000-0000-000000000001', 'password' => '12345', ]; $this->Trait->Auth->expects($this->any()) @@ -154,7 +154,7 @@ protected function _mockAuthLoggedIn() $this->Trait->Auth->expects($this->any()) ->method('user') ->with('id') - ->will($this->returnValue(1)); + ->will($this->returnValue('00000000-0000-0000-0000-000000000001')); } /** diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index a3567162a..3c64ebb75 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -47,7 +47,7 @@ public function tearDown() */ public function testChangePasswordHappy() { - $this->assertEquals('12345', $this->table->get(1)->password); + $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); $this->_mockRequestPost(); $this->_mockAuthLoggedIn(); $this->_mockFlash(); @@ -65,7 +65,7 @@ public function testChangePasswordHappy() ->with('Password has been changed successfully'); $this->Trait->changePassword(); $hasher = PasswordHasherFactory::build('Default'); - $this->assertTrue($hasher->check('new', $this->table->get(1)->password)); + $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); } /** @@ -127,7 +127,7 @@ public function testResetPassword() */ public function testRequestResetPasswordGet() { - $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get(1)->token); + $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); $this->_mockRequestGet(); $this->_mockFlash(); $this->Trait->request->expects($this->never()) @@ -142,7 +142,7 @@ public function testRequestResetPasswordGet() */ public function testRequestPasswordHappy() { - $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get(1)->token); + $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); $this->_mockRequestPost(); $this->_mockAuthLoggedIn(); $this->_mockFlash(); @@ -155,6 +155,6 @@ public function testRequestPasswordHappy() ->method('success') ->with('Password has been changed successfully'); $this->Trait->requestResetPassword(); - $this->assertNotEquals('xxx', $this->table->get(1)->token); + $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000001')->token); } } diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 969ccfdeb..c155947d4 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -80,7 +80,7 @@ public function testIndex() */ public function testView() { - $id = 1; + $id = '00000000-0000-0000-0000-000000000001'; $this->Trait->view($id); $expected = [ 'Users' => $this->table->get($id), @@ -195,7 +195,7 @@ public function testAddPostErrors() */ public function testEditPostHappy() { - $this->assertEquals('user-1@test.com', $this->table->get(1)->email); + $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); $this->_mockRequestPost(['patch', 'post', 'put']); $this->_mockFlash(); $this->Trait->request->data = [ @@ -206,9 +206,9 @@ public function testEditPostHappy() ->method('success') ->with('The User has been saved'); - $this->Trait->edit(1); + $this->Trait->edit('00000000-0000-0000-0000-000000000001'); - $this->assertEquals('newtestuser@test.com', $this->table->get(1)->email); + $this->assertEquals('newtestuser@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); } /** @@ -218,7 +218,7 @@ public function testEditPostHappy() */ public function testEditPostErrors() { - $this->assertEquals('user-1@test.com', $this->table->get(1)->email); + $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); $this->_mockRequestPost(['patch', 'post', 'put']); $this->_mockFlash(); $this->Trait->request->data = [ @@ -229,9 +229,9 @@ public function testEditPostErrors() ->method('error') ->with('The User could not be saved'); - $this->Trait->edit(1); + $this->Trait->edit('00000000-0000-0000-0000-000000000001'); - $this->assertEquals('user-1@test.com', $this->table->get(1)->email); + $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); } /** @@ -242,7 +242,7 @@ public function testEditPostErrors() */ public function testDeleteHappy() { - $this->assertNotEmpty($this->table->get(1)); + $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); $this->_mockRequestPost(); $this->Trait->request->expects($this->any()) ->method('allow') @@ -254,9 +254,9 @@ public function testDeleteHappy() ->method('success') ->with('The User has been deleted'); - $this->Trait->delete(1); + $this->Trait->delete('00000000-0000-0000-0000-000000000001'); - $this->table->get(1); + $this->table->get('00000000-0000-0000-0000-000000000001'); } /** @@ -267,7 +267,7 @@ public function testDeleteHappy() */ public function testDeleteNotFound() { - $this->assertNotEmpty($this->table->get(1)); + $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); $this->_mockRequestPost(); $this->Trait->request->expects($this->any()) ->method('allow') @@ -276,6 +276,6 @@ public function testDeleteNotFound() $this->Trait->delete('not-found'); - $this->assertNotEmpty($this->table->get(1)); + $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); } } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 19bb55e2c..79df58c67 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -207,7 +207,7 @@ public function testValidateRegisterNoTosRequired() */ public function testActivateUser() { - $user = $this->Table->find()->where(['id' => 1])->first(); + $user = $this->Table->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); $result = $this->Table->activateUser($user); $this->assertTrue($result->active); } @@ -253,7 +253,7 @@ public function testValidateNotExistingUser() */ public function testActiveUserRemoveValidationToken() { - $user = $this->Table->find()->where(['id' => 1])->first(); + $user = $this->Table->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') ->setMethods(['_removeValidationToken']) ->setConstructorArgs([$this->Table]) diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index 4e5382595..f6436bc7c 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -134,7 +134,7 @@ public function testAfterSaveSocialNotActiveUserNotActive() public function testAfterSaveSocialActiveUserActive() { $event = new Event('eventName'); - $entity = $this->Table->findById(3)->first(); + $entity = $this->Table->findById('00000000-0000-0000-0000-000000000003')->first(); $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); } @@ -147,7 +147,7 @@ public function testAfterSaveSocialActiveUserActive() public function testAfterSaveSocialActiveUserNotActive() { $event = new Event('eventName'); - $entity = $this->Table->findById(2)->first(); + $entity = $this->Table->findById('00000000-0000-0000-0000-000000000002')->first(); $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 55a1230e5..3582addd3 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -173,7 +173,7 @@ public function testValidateRegisterNoTosRequired() */ public function testActivateUser() { - $user = $this->Users->find()->where(['id' => 1])->first(); + $user = $this->Users->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); $result = $this->Users->activateUser($user); $this->assertTrue($result->active); } From 2be70310765eb52684182c91f47db7fe25f005eb Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:08:13 +0000 Subject: [PATCH 0253/1476] fix uuid types for passing postgresql tests --- tests/Fixture/SocialAccountsFixture.php | 2 +- tests/TestCase/Auth/RememberMeAuthenticateTest.php | 5 +++-- tests/TestCase/Controller/Traits/ProfileTraitTest.php | 4 ++-- tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php | 6 ++---- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 19fdbde4e..6f3d9dda8 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -18,7 +18,7 @@ class SocialAccountsFixture extends TestFixture // @codingStandardsIgnoreStart public $fields = [ 'id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'user_id' => ['type' => 'string', 'length' => 36, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => 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], diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php index 8e3b5d6ca..b0d60f4bb 100644 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -115,7 +115,8 @@ public function testAuthenticateBadUser() ->method('read') ->with('remember_me') ->will($this->returnValue([ - 'id' => 'bad-user', + //bad-user + 'id' => '00000000-0000-0000-0000-000000000000', 'user_agent' => 'user-agent' ])); $registry = new ComponentRegistry($this->controller); @@ -149,7 +150,7 @@ public function testAuthenticateBadAgent() ->method('read') ->with('remember_me') ->will($this->returnValue([ - 'id' => 1, + 'id' => '00000000-0000-0000-0000-000000000001', 'user_agent' => 'bad-agent' ])); $registry = new ComponentRegistry($this->controller); diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index 8ac352971..e4a2efdf0 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -46,7 +46,7 @@ public function setUp() */ public function testProfileGetNotLoggedInUserNotFound() { - $userId = 'not-found'; + $userId = '00000000-0000-0000-0000-000000000000'; //not found $this->_mockRequestGet(); $this->_mockAuth(); $this->_mockFlash(); @@ -63,7 +63,7 @@ public function testProfileGetNotLoggedInUserNotFound() */ public function testProfileGetLoggedInUserNotFound() { - $userId = 'not-found'; + $userId = '00000000-0000-0000-0000-000000000000'; //not found $this->_mockRequestGet(); $this->_mockAuthLoggedIn(); $this->_mockFlash(); diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index c155947d4..570d2d50f 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -101,7 +101,7 @@ public function testView() */ public function testViewNotFound() { - $this->Trait->view('not-found'); + $this->Trait->view('00000000-0000-0000-0000-000000000000'); } /** @@ -274,8 +274,6 @@ public function testDeleteNotFound() ->with(['post', 'delete']) ->will($this->returnValue(true)); - $this->Trait->delete('not-found'); - - $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); + $this->Trait->delete('00000000-0000-0000-0000-000000000000'); } } From f719c84dc0fecbaf30ab10d2bf44a31f8068a3ca Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:17:17 +0000 Subject: [PATCH 0254/1476] fix docblock --- src/Auth/RememberMeAuthenticate.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Auth/RememberMeAuthenticate.php b/src/Auth/RememberMeAuthenticate.php index f92cf4582..3ae70dff7 100644 --- a/src/Auth/RememberMeAuthenticate.php +++ b/src/Auth/RememberMeAuthenticate.php @@ -28,7 +28,6 @@ class RememberMeAuthenticate extends BaseAuthenticate * * @param Request $request Cake request object. * @param Response $response Cake response object. - * @param array $cookie Array with value, key cookie. * @return mixed */ public function authenticate(Request $request, Response $response) From 51a3b354b36fec5a685c2e07033df79b8e0c359a Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:21:54 +0000 Subject: [PATCH 0255/1476] fix phpcs --- src/Model/Behavior/RegisterBehavior.php | 13 +++++++------ src/Model/Entity/User.php | 2 +- src/View/Helper/UserHelper.php | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index d5ff87812..efced02a6 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -11,6 +11,11 @@ namespace CakeDC\Users\Model\Behavior; +use CakeDC\Users\Exception\TokenExpiredException; +use CakeDC\Users\Exception\UserAlreadyActiveException; +use CakeDC\Users\Exception\UserNotFoundException; +use CakeDC\Users\Model\Behavior\Behavior; +use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Event\Event; @@ -18,11 +23,6 @@ use Cake\Validation\Validator; use DateTime; use InvalidArgumentException; -use CakeDC\Users\Exception\TokenExpiredException; -use CakeDC\Users\Exception\UserAlreadyActiveException; -use CakeDC\Users\Exception\UserNotFoundException; -use CakeDC\Users\Model\Behavior\Behavior; -use CakeDC\Users\Model\Entity\User; /** @@ -125,7 +125,8 @@ public function activateUser(EntityInterface $user) * @param string $name name * @return Validator */ - public function buildValidator(Event $event, Validator $validator, $name){ + public function buildValidator(Event $event, Validator $validator, $name) + { if ($name === 'default') { return $this->_emailValidator($validator, $this->validateEmail); } diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 37d36afe4..f33b5e51d 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -81,7 +81,7 @@ protected function _setTos($tos) * Hash a password using the configured password hasher, * use DefaultPasswordHasher if no one was configured * - * @param $password + * @param string $password password to be hashed * @return mixed */ public function hashPassword($password) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index aa713ab4c..f1abb3417 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -11,11 +11,11 @@ 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\View\Helper; -use CakeDC\Users\Controller\Component\UsersAuthComponent; /** * User helper From d62bf8caf2b4a56d1e7615e4bc93d059b051174a Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:26:05 +0000 Subject: [PATCH 0256/1476] fix phpcs --- src/Model/Behavior/PasswordBehavior.php | 10 +++++----- src/Model/Behavior/SocialAccountBehavior.php | 10 +++++----- src/Model/Behavior/SocialBehavior.php | 1 - 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index de3794c76..76b4a2d42 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -11,14 +11,14 @@ namespace CakeDC\Users\Model\Behavior; -use Cake\Datasource\EntityInterface; -use Cake\Network\Email\Email; -use Cake\Utility\Hash; -use InvalidArgumentException; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; use CakeDC\Users\Model\Behavior\Behavior; +use Cake\Datasource\EntityInterface; +use Cake\Network\Email\Email; +use Cake\Utility\Hash; +use InvalidArgumentException; /** * Covers the password management features @@ -89,7 +89,7 @@ protected function _getUser($reference) * instance * @return array email send result */ - public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template) + public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template = 'CakeDC/Users.reset_password') { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $subject = __d('Users', '{0}Your reset password link', $firstName); diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 046c70749..e9cf6d3eb 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -12,6 +12,11 @@ namespace CakeDC\Users\Model\Behavior; use ArrayObject; +use CakeDC\Users\Exception\AccountAlreadyActiveException; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Model\Behavior\Behavior; +use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Datasource\Exception\RecordNotFoundException; @@ -19,11 +24,6 @@ use Cake\Network\Email\Email; use Cake\ORM\Entity; use InvalidArgumentException; -use CakeDC\Users\Exception\AccountAlreadyActiveException; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Model\Behavior\Behavior; -use CakeDC\Users\Model\Entity\User; /** * Covers social account features diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index fa43fe77b..0a062f88e 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -155,7 +155,6 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['username'] = strtolower($firstName . $lastName); $userData['username'] = preg_replace('/[^A-Za-z0-9]/i', '', Hash::get($userData, 'username')); } - } $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); if ($useEmail) { From 73dedd2a093a528c1f97e878c4d853b5c718c385 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:37:04 +0000 Subject: [PATCH 0257/1476] fix phpcs --- src/Controller/Component/UsersAuthComponent.php | 2 +- src/Controller/SocialAccountsController.php | 4 ++-- src/Controller/Traits/LoginTrait.php | 4 ++-- src/Controller/Traits/PasswordManagementTrait.php | 4 ++-- src/Controller/Traits/ProfileTrait.php | 2 +- src/Controller/Traits/RegisterTrait.php | 2 +- src/Controller/Traits/SimpleCrudTrait.php | 3 ++- src/Controller/Traits/SocialTrait.php | 2 +- src/Controller/Traits/UserValidationTrait.php | 6 +++--- src/Controller/UsersController.php | 7 ++++--- src/Model/Behavior/SocialBehavior.php | 11 +++++++---- src/Model/Table/SocialAccountsTable.php | 5 ++--- src/Model/Table/UsersTable.php | 4 ++-- 13 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index cf5bd907e..c75ed3d51 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Controller\Component; +use CakeDC\Users\Exception\BadConfigurationException; use Cake\Controller\Component; use Cake\Core\Configure; use Cake\Event\Event; use Cake\Network\Request; use Cake\Routing\Router; use Cake\Utility\Hash; -use CakeDC\Users\Exception\BadConfigurationException; class UsersAuthComponent extends Component { diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 5a6b0207c..5606f204b 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -11,11 +11,11 @@ namespace CakeDC\Users\Controller; -use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\Network\Response; use CakeDC\Users\Controller\AppController; use CakeDC\Users\Exception\AccountAlreadyActiveException; use CakeDC\Users\Model\Table\SocialAccountsTable; +use Cake\Datasource\Exception\RecordNotFoundException; +use Cake\Network\Response; /** * SocialAccounts Controller diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 88e86980e..afde464af 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,11 +11,11 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Core\Configure; -use Cake\Utility\Hash; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; +use Cake\Core\Configure; +use Cake\Utility\Hash; /** * Covers the login, logout and social login diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index b91f3abb8..ed6008da7 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Core\Configure; -use Exception; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; +use Cake\Core\Configure; +use Exception; /** * Covers the password management: reset, change diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 72f6562e7..a9edbdd47 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -36,7 +36,7 @@ public function profile($id = null) } try { $appContain = (array)Configure::read('Auth.authenticate.' . \Cake\Controller\Component\AuthComponent::ALL . '.contain'); - $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; + $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; $user = $this->getUsersTable()->get($id, [ 'contain' => array_merge((array)$appContain, (array)$socialContain) ]); diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index ed033a600..b572b6811 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Controller\Component\UsersAuthComponent; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Network\Exception\NotFoundException; use Cake\Network\Response; use InvalidArgumentException; -use CakeDC\Users\Controller\Component\UsersAuthComponent; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index 71280f225..34b0b7634 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Network\Exception\NotFoundException; +use Cake\Network\Response; use Cake\ORM\TableRegistry; use Cake\Utility\Inflector; @@ -112,7 +113,7 @@ public function edit($id = null) * Delete method * * @param string|null $id User id. - * @return void Redirects to index. + * @return Response Redirects to index. * @throws NotFoundException When record not found. */ public function delete($id = null) diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 2a5f9bf26..ba788c7d8 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Auth\Factory\OpauthFactory; use Cake\Core\Configure; use Cake\Network\Exception\NotFoundException; use Cake\Routing\Router; -use CakeDC\Users\Auth\Factory\OpauthFactory; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 23d0a2134..8846c72a6 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Exception\TokenExpiredException; +use CakeDC\Users\Exception\UserAlreadyActiveException; +use CakeDC\Users\Exception\UserNotFoundException; use Cake\Core\Configure; use Cake\Network\Response; use Exception; use InvalidArgumentException; -use CakeDC\Users\Exception\TokenExpiredException; -use CakeDC\Users\Exception\UserAlreadyActiveException; -use CakeDC\Users\Exception\UserNotFoundException; /** * Covers the user validation diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 8467444f1..a0337b31a 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -19,6 +19,7 @@ use CakeDC\Users\Controller\Traits\SocialTrait; use CakeDC\Users\Model\Table\UsersTable; use Cake\Core\Configure; +use Cake\ORM\Table; /** * Users Controller @@ -35,9 +36,9 @@ class UsersController extends AppController /** * Override loadModel to load specific users table - * @param null $modelClass - * @param string $type - * @return object + * @param string $modelClass model class + * @param string $type type + * @return Table */ public function loadModel($modelClass = null, $type = 'Table') { diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 0a062f88e..44290ad3b 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -11,15 +11,15 @@ namespace CakeDC\Users\Model\Behavior; -use Cake\Datasource\EntityInterface; -use Cake\Utility\Hash; -use DateTime; -use InvalidArgumentException; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Model\Behavior\Behavior; use CakeDC\Users\Model\Table\SocialAccountsTable; use CakeDC\Users\Traits\RandomStringTrait; +use Cake\Datasource\EntityInterface; +use Cake\Utility\Hash; +use DateTime; +use InvalidArgumentException; /** * Covers social features @@ -185,6 +185,9 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail /** * Create a link for facebook profile + * + * @param array $raw raw data array returned by Facebook + * @return string url to facebook profile */ protected function _getFacebookLink($raw = []) { diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 0531617fd..50f953e0f 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -11,8 +11,9 @@ namespace CakeDC\Users\Model\Table; -use App\Model\Entity\Account; use ArrayObject; +use CakeDC\Users\Exception\AccountAlreadyActiveException; +use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Datasource\Exception\RecordNotFoundException; @@ -22,8 +23,6 @@ use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; -use CakeDC\Users\Exception\AccountAlreadyActiveException; -use CakeDC\Users\Model\Entity\User; /** * SocialAccounts Model diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index cd62306a6..1c33e92f6 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -11,14 +11,14 @@ namespace CakeDC\Users\Model\Table; +use CakeDC\Users\Exception\WrongPasswordException; +use CakeDC\Users\Model\Entity\User; use Cake\Datasource\EntityInterface; use Cake\Network\Email\Email; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Utility\Hash; use Cake\Validation\Validator; -use CakeDC\Users\Exception\WrongPasswordException; -use CakeDC\Users\Model\Entity\User; /** * Users Model From eb87cdb75788e5f3fd5e9be378242df1ab798574 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:41:30 +0000 Subject: [PATCH 0258/1476] fix phpcs --- src/Shell/UsersShell.php | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index f24952bbc..630e06ae1 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -11,11 +11,11 @@ namespace CakeDC\Users\Shell; +use CakeDC\Users\Model\Entity\User; use Cake\Auth\DefaultPasswordHasher; use Cake\Console\Shell; use Cake\Core\Configure; use Cake\Utility\Hash; -use CakeDC\Users\Model\Entity\User; /** * Shell with utilities for the Users Plugin @@ -64,8 +64,7 @@ public function getOptionParser() 'username' => ['short' => 'u', 'help' => 'The username for the new user'], 'password' => ['short' => 'p', 'help' => 'The password for the new user'], 'email' => ['short' => 'e', 'help' => 'The email for the new user'] - ]) - ; + ]); return $parser; } @@ -226,7 +225,6 @@ public function activateUser() { $user = $this->_changeUserActive(true); $this->out(__d('Users', 'User was activated: {0}', $user->username)); - } /** @@ -272,7 +270,8 @@ public function passwordEmail() /** * Change user active field * - * @param $active + * @param $active active value + * @return bool */ protected function _changeUserActive($active) { @@ -289,12 +288,12 @@ protected function _changeUserActive($active) /** * Update user by username * - * @param $username - * @param $data + * @param string $username username + * @param array $data data + * @return bool */ protected function _updateUser($username, $data) { - /** @var \Users\Model\Entity\User */ $user = $this->Users->find()->where(['Users.username' => $username])->first(); if (empty($user)) { $this->error(__d('Users', 'The user was not found.')); @@ -333,7 +332,7 @@ public function deleteUser() /** * Generates a random password. * - * @return void + * @return string */ protected function _generateRandomPassword() { @@ -343,7 +342,7 @@ protected function _generateRandomPassword() /** * Generates a random username based on a list of preexisting ones. * - * @return void + * @return string */ protected function _generateRandomUsername() { @@ -353,8 +352,8 @@ protected function _generateRandomUsername() /** * Hash a password * - * @param password - * @return void + * @param string $password password + * @return string */ protected function _generatedHashedPassword($password) { From 0205ce20f7412291e08583fc8c44249608c7906e Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:46:39 +0000 Subject: [PATCH 0259/1476] fix phpcs --- tests/TestCase/Auth/RememberMeAuthenticateTest.php | 4 ++-- tests/TestCase/Auth/SimpleRbacAuthorizeTest.php | 2 +- tests/TestCase/Auth/SuperuserAuthorizeTest.php | 2 +- .../Controller/Component/RememberMeComponentTest.php | 2 +- .../Controller/Component/UsersAuthComponentTest.php | 6 +++--- tests/TestCase/Controller/Traits/LoginTraitTest.php | 8 ++++---- tests/TestCase/Controller/Traits/ProfileTraitTest.php | 2 +- tests/TestCase/Controller/Traits/RegisterTraitTest.php | 2 +- tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php | 2 +- .../Controller/Traits/UserValidationTraitTest.php | 2 +- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 4 ++-- .../TestCase/Model/Behavior/SocialAccountBehaviorTest.php | 2 +- tests/TestCase/Model/Entity/UserTest.php | 2 +- tests/TestCase/Model/Table/SocialAccountsTableTest.php | 4 ++-- tests/TestCase/Model/Table/UsersTableTest.php | 8 ++++---- tests/TestCase/View/Helper/UserHelperTest.php | 2 +- 16 files changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php index b0d60f4bb..960a573c2 100644 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -11,14 +11,14 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use CakeDC\Users\Auth\RememberMeAuthenticate; +use CakeDC\Users\Auth\SuperuserAuthorize; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; use Cake\Event\EventManager; use Cake\Network\Request; use Cake\Network\Response; use Cake\TestSuite\TestCase; -use CakeDC\Users\Auth\RememberMeAuthenticate; -use CakeDC\Users\Auth\SuperuserAuthorize; class RememberMeAuthenticateTest extends TestCase { diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index 3f758bd1f..9ab9f8ab5 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use CakeDC\Users\Auth\SimpleRbacAuthorize; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; use Cake\Event\EventManager; @@ -19,7 +20,6 @@ use Cake\TestSuite\TestCase; use Cake\Utility\Hash; use ReflectionClass; -use CakeDC\Users\Auth\SimpleRbacAuthorize; class SimpleRbacAuthorizeTest extends TestCase { diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php index 153ac9158..bde73f341 100644 --- a/tests/TestCase/Auth/SuperuserAuthorizeTest.php +++ b/tests/TestCase/Auth/SuperuserAuthorizeTest.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use CakeDC\Users\Auth\SuperuserAuthorize; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; use Cake\Event\EventManager; use Cake\Network\Request; use Cake\Network\Response; use Cake\TestSuite\TestCase; -use CakeDC\Users\Auth\SuperuserAuthorize; class SuperuserAuthorizeTest extends TestCase { diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 6f453f6fa..701bdf587 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; +use CakeDC\Users\Controller\Component\RememberMeComponent; use Cake\Controller\ComponentRegistry; use Cake\Controller\Component\AuthComponent; use Cake\Controller\Component\CookieComponent; @@ -22,7 +23,6 @@ use Cake\TestSuite\TestCase; use Cake\Utility\Security; use InvalidArgumentException; -use CakeDC\Users\Controller\Component\RememberMeComponent; /** * Users\Controller\Component\RememberMeComponent Test Case diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index c68968e71..2c45e2f9c 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -11,6 +11,9 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; +use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Exception\UserNotFoundException; use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Core\Plugin; @@ -22,9 +25,6 @@ use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\Utility\Security; -use CakeDC\Users\Controller\Component\UsersAuthComponent; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Exception\UserNotFoundException; /** * Users\Controller\Component\UsersAuthComponent Test Case diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 73c7b7645..88bac68f5 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -11,16 +11,16 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Controller\Traits\LoginTrait; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\MissingEmailException; use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Event\Event; use Cake\Network\Request; use Cake\TestSuite\TestCase; use Opauth\Opauth\Response; -use CakeDC\Users\Controller\Component\UsersAuthComponent; -use CakeDC\Users\Controller\Traits\LoginTrait; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; class LoginTraitTest extends TestCase { diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index e4a2efdf0..c88a45cb1 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -11,9 +11,9 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\ORM\TableRegistry; 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 fb4022b50..7d737f45b 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -11,11 +11,11 @@ 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\Network\Email\Email; use Cake\ORM\TableRegistry; -use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; class RegisterTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 570d2d50f..2e807ebda 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\Network\Request; use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; +use Cake\Network\Request; class SimpleCrudTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index b15197a0e..e84d208bb 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\Network\Request; use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; +use Cake\Network\Request; class UserValidationTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 6960a849b..3ae02dfb2 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; +use CakeDC\Users\Exception\UserAlreadyActiveException; +use CakeDC\Users\Model\Table\UsersTable; use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; use InvalidArgumentException; -use CakeDC\Users\Exception\UserAlreadyActiveException; -use CakeDC\Users\Model\Table\UsersTable; /** * Test Case diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index f6436bc7c..d341d6927 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; +use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Event\Event; use Cake\Network\Email\Email; use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; use InvalidArgumentException; -use CakeDC\Users\Model\Table\SocialAccountsTable; /** * Test Case diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index 00f4f89c6..2788aa8ad 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -1,9 +1,9 @@ Date: Tue, 22 Sep 2015 01:51:30 +0000 Subject: [PATCH 0260/1476] fix phpcs --- src/Model/Behavior/RegisterBehavior.php | 1 - src/Shell/UsersShell.php | 2 +- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 1 - tests/TestCase/Shell/UsersShellTest.php | 5 ----- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index efced02a6..ab95edc72 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -24,7 +24,6 @@ use DateTime; use InvalidArgumentException; - /** * Covers the user registration */ diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 630e06ae1..634b21462 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -270,7 +270,7 @@ public function passwordEmail() /** * Change user active field * - * @param $active active value + * @param bool $active active value * @return bool */ protected function _changeUserActive($active) diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 3ae02dfb2..85defd0f8 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -209,5 +209,4 @@ public function testSendResetPasswordEmail() Router::fullBaseUrl($this->fullBaseBackup); Email::dropTransport('test'); } - } diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 89176be30..35592090e 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -111,7 +111,6 @@ public function testAddUser() //TODO: Add assertions with 'out' $this->Shell->runCommand(['addUser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email']]); - } /** @@ -160,7 +159,6 @@ public function testAddUserWithNoParams() //TODO: Add assertions with 'out' $this->Shell->runCommand(['addUser']); - } /** @@ -203,7 +201,6 @@ public function testAddSuperuser() ->will($this->returnValue($userSaved)); $this->Shell->runCommand(['addSuperuser']); - } /** @@ -222,7 +219,6 @@ public function testResetAllPasswords() ->with(['password' => 'hashedPasssword'], ['id IS NOT NULL']); $this->Shell->runCommand(['resetAllPasswords', '123']); - } /** @@ -237,6 +233,5 @@ public function testResetAllPasswordsNoPassingParams() ->with('Please enter a password.'); $this->Shell->runCommand(['resetAllPasswords']); - } } From 4f668f6a9aabb96f868b1a921a3865539c8466a9 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:52:11 +0000 Subject: [PATCH 0261/1476] fix phpcs --- tests/App/Controller/AppController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/App/Controller/AppController.php b/tests/App/Controller/AppController.php index 9f88e565a..5899a4e41 100644 --- a/tests/App/Controller/AppController.php +++ b/tests/App/Controller/AppController.php @@ -21,5 +21,4 @@ public function initialize() // $this->loadComponent('CakeDC/Users.UsersAuth'); $this->loadComponent('RequestHandler'); } - } From 49d8a0a6380d276aa0b702e1b5bc1d797d1920c4 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 01:56:01 +0000 Subject: [PATCH 0262/1476] fix phpcs --- .../TestCase/Controller/SocialAccountsControllerTest.php | 2 +- tests/TestCase/Model/Table/UsersTableTest.php | 8 ++++---- tests/TestCase/Shell/UsersShellTest.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 27501e316..7f4c6a714 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -12,8 +12,8 @@ namespace CakeDC\Users\Test\TestCase\Controller; use CakeDC\Users\Controller\SocialAccountsController; -use CakeDC\Users\Model\Table\SocialAccountsTable; use CakeDC\Users\Model\Behavior\SocialAccountBehavior; +use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; use Cake\Event\EventManager; use Cake\Network\Email\Email; diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 51b83d3dc..216bf7c84 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -178,7 +178,7 @@ public function testActivateUser() $this->assertTrue($result->active); } - public function _testSocialLogin() + public function testSocialLogin() { $raw = [ 'id' => 'reference-2-1', @@ -205,7 +205,7 @@ public function _testSocialLogin() * * @expectedException CakeDC\Users\Exception\AccountNotActiveException */ - public function _testSocialLoginInactiveAccount() + public function testSocialLoginInactiveAccount() { $raw = [ 'id' => 'reference-2-2', @@ -231,7 +231,7 @@ public function _testSocialLoginInactiveAccount() * * @expectedException InvalidArgumentException */ - public function _testSocialLoginddCreateNewAccountWithNoCredentials() + public function testSocialLoginddCreateNewAccountWithNoCredentials() { $raw = [ 'id' => 'reference-not-existing', @@ -254,7 +254,7 @@ public function _testSocialLoginddCreateNewAccountWithNoCredentials() * Test socialLogin * */ - public function _testSocialLoginCreateNewAccount() + public function testSocialLoginCreateNewAccount() { $raw = [ 'id' => 'no-existing-reference', diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 35592090e..2980a2dce 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -214,7 +214,7 @@ public function testResetAllPasswords() ->method('_generatedHashedPassword') ->will($this->returnValue('hashedPasssword')); - $this->Shell->Users->expects($this->once()) + $this->Shell->Users->expects($this->once()) ->method('updateAll') ->with(['password' => 'hashedPasssword'], ['id IS NOT NULL']); From 1406eb6fa322b147a0f92411cf74313efd1eabaa Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 02:28:59 +0000 Subject: [PATCH 0263/1476] fix opauth dependency --- tests/TestCase/Model/Table/UsersTableTest.php | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 216bf7c84..e73977cac 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -21,7 +21,6 @@ use Cake\Routing\Router; use Cake\TestSuite\TestCase; use InvalidArgumentException; -use Opauth\Opauth\Response; /** * Users\Model\Table\UsersTable Test Case @@ -188,8 +187,11 @@ public function testSocialLogin() 'user_email' => 'user-2@test.com', 'link' => 'link' ]; - $data = new Response(SocialAccountsTable::PROVIDER_FACEBOOK, $raw); - $data->setData('uid', 'id'); + $data = new \Cake\Network\Response(); + $data->provider = SocialAccountsTable::PROVIDER_FACEBOOK; + $data->email = 'user-2@test.com'; + $data->raw = $raw; + $data->uid = 'reference-2-1'; $options = [ 'use_email' => 1, 'validate_email' => 1, @@ -214,8 +216,11 @@ public function testSocialLoginInactiveAccount() 'verified' => 1, 'user_email' => 'hello@test.com', ]; - $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); - $data->setData('uid', 'id'); + $data = new \Cake\Network\Response(); + $data->provider = SocialAccountsTable::PROVIDER_TWITTER; + $data->email = 'hello@test.com'; + $data->raw = $raw; + $data->uid = 'reference-2-2'; $options = [ 'use_email' => 1, 'validate_email' => 1, @@ -239,8 +244,11 @@ public function testSocialLoginddCreateNewAccountWithNoCredentials() 'gender' => 'male', 'user_email' => 'user@test.com', ]; - $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); - $data->setData('uid', 'id'); + $data = new \Cake\Network\Response(); + $data->provider = SocialAccountsTable::PROVIDER_TWITTER; + $data->email = 'user@test.com'; + $data->raw = $raw; + $data->uid = 'reference-not-existing'; $options = [ 'use_email' => 0, 'validate_email' => 1, @@ -265,11 +273,16 @@ public function testSocialLoginCreateNewAccount() 'twitter' => 'link' ]; - $data = new Response(SocialAccountsTable::PROVIDER_TWITTER, $raw); - $data->setData('uid', 'id'); - $data->setData('info.first_name', 'first_name'); - $data->setData('info.last_name', 'last_name'); - $data->setData('info.urls.twitter', 'twitter'); + $data = new \Cake\Network\Response(); + $data->provider = SocialAccountsTable::PROVIDER_TWITTER; + $data->email = 'user-2@test.com'; + $data->raw = $raw; + $data->uid = 'no-existing-reference'; + $data->info = [ + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'urls' => ['twitter' => 'twitter'], + ]; $data->email = 'username@test.com'; $data->credentials = [ From e7cb1a36589f3ef346996845efd17ec38daa9f62 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 02:30:07 +0000 Subject: [PATCH 0264/1476] fix array cast for Hash::get --- src/Auth/SocialAuthenticate.php | 2 +- src/Model/Behavior/SocialBehavior.php | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 80de3834d..46bc12e12 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -38,7 +38,7 @@ public function authenticate(Request $request, Response $response) if (empty($data)) { return false; } - $socialMail = Hash::get($data->info, Configure::read('Users.Key.Data.email')); + $socialMail = Hash::get((array)$data->info, Configure::read('Users.Key.Data.email')); if (!empty($socialMail)) { $data->email = $socialMail; diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 44290ad3b..0da027e8c 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -113,17 +113,17 @@ protected function _createSocialUser($data, $options = []) protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) { $accountData['provider'] = $data->provider; - $accountData['username'] = Hash::get($data->info, 'nickname'); + $accountData['username'] = Hash::get((array)$data->info, 'nickname'); $accountData['reference'] = $data->uid; - $accountData['avatar'] = Hash::get($data->info, 'image'); + $accountData['avatar'] = Hash::get((array)$data->info, 'image'); /* @todo make a pull request to Opauth Facebook Strategy because it does not include link on info array */ if ($data->provider == SocialAccountsTable::PROVIDER_TWITTER) { - $accountData['link'] = Hash::get($data->info, 'urls.twitter'); + $accountData['link'] = Hash::get((array)$data->info, 'urls.twitter'); } elseif ($data->provider == SocialAccountsTable::PROVIDER_FACEBOOK) { $accountData['link'] = $this->_getFacebookLink($data->raw); } $accountData['avatar'] = str_replace('square', 'large', $accountData['avatar']); - $accountData['description'] = Hash::get($data->info, 'description'); + $accountData['description'] = Hash::get((array)$data->info, 'description'); $accountData['token'] = Hash::get((array)$data->credentials, 'token'); $accountData['token_secret'] = Hash::get((array)$data->credentials, 'secret'); $expires = Hash::get((array)$data->credentials, 'expires'); @@ -132,8 +132,8 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $accountData['active'] = true; if (empty($existingUser)) { - $firstName = Hash::get($data->info, 'first_name'); - $lastName = Hash::get($data->info, 'last_name'); + $firstName = Hash::get((array)$data->info, 'first_name'); + $lastName = Hash::get((array)$data->info, 'last_name'); if (!empty($firstName) && !empty($lastName)) { $userData['first_name'] = $firstName; $userData['last_name'] = $lastName; @@ -143,7 +143,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail array_shift($name); $userData['last_name'] = implode(' ', $name); } - $userData['username'] = Hash::get($data->info, 'nickname'); + $userData['username'] = Hash::get((array)$data->info, 'nickname'); $username = Hash::get($userData, 'username'); if (empty($username)) { if (!empty($data->email)) { @@ -164,7 +164,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail } } $userData['password'] = $this->randomString(); - $userData['avatar'] = Hash::get($data->info, 'image'); + $userData['avatar'] = Hash::get((array)$data->info, 'image'); $userData['validated'] = $data->validated; $userData['tos_date'] = date("Y-m-d H:i:s"); $userData['gender'] = Hash::get($data->raw, 'gender'); From a3ce4d700070e051d412a6b6a270a7091bd15231 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 02:36:18 +0000 Subject: [PATCH 0265/1476] fix social login test --- tests/TestCase/Model/Table/UsersTableTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index e73977cac..8940ab26d 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -221,6 +221,9 @@ public function testSocialLoginInactiveAccount() $data->email = 'hello@test.com'; $data->raw = $raw; $data->uid = 'reference-2-2'; + $data->info = [ + 'first_name' => 'User 2', + ]; $options = [ 'use_email' => 1, 'validate_email' => 1, @@ -249,6 +252,9 @@ public function testSocialLoginddCreateNewAccountWithNoCredentials() $data->email = 'user@test.com'; $data->raw = $raw; $data->uid = 'reference-not-existing'; + $data->info = [ + 'first_name' => 'Not existing user', + ]; $options = [ 'use_email' => 0, 'validate_email' => 1, @@ -283,6 +289,7 @@ public function testSocialLoginCreateNewAccount() 'last_name' => 'Last Name', 'urls' => ['twitter' => 'twitter'], ]; + $data->validated = true; $data->email = 'username@test.com'; $data->credentials = [ From fc9a7c3e622761a9e5d4bf888ba8e6ce5e10e651 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 02:38:55 +0000 Subject: [PATCH 0266/1476] fix social login test --- tests/TestCase/Model/Table/UsersTableTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 8940ab26d..a420943c1 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -255,6 +255,7 @@ public function testSocialLoginddCreateNewAccountWithNoCredentials() $data->info = [ 'first_name' => 'Not existing user', ]; + $data->credentials = []; $options = [ 'use_email' => 0, 'validate_email' => 1, From fa40b7a2a2e58758bf73799aa1a50b7ef1b88ef0 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 02:41:32 +0000 Subject: [PATCH 0267/1476] fix social login test --- tests/TestCase/Model/Table/UsersTableTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index a420943c1..a16b11c67 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -256,6 +256,7 @@ public function testSocialLoginddCreateNewAccountWithNoCredentials() 'first_name' => 'Not existing user', ]; $data->credentials = []; + $data->name = ''; $options = [ 'use_email' => 0, 'validate_email' => 1, From 5e6dc234cafeedb5e96a218545f5ba5a8a88f0ae Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 02:43:38 +0000 Subject: [PATCH 0268/1476] fix social login test --- tests/TestCase/Model/Table/UsersTableTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index a16b11c67..05011fbf7 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -239,7 +239,7 @@ public function testSocialLoginInactiveAccount() * * @expectedException InvalidArgumentException */ - public function testSocialLoginddCreateNewAccountWithNoCredentials() + public function testSocialLoginCreateNewAccountWithNoCredentials() { $raw = [ 'id' => 'reference-not-existing', @@ -251,6 +251,7 @@ public function testSocialLoginddCreateNewAccountWithNoCredentials() $data->provider = SocialAccountsTable::PROVIDER_TWITTER; $data->email = 'user@test.com'; $data->raw = $raw; + $data->validated = true; $data->uid = 'reference-not-existing'; $data->info = [ 'first_name' => 'Not existing user', From 6bb95a3c679f57473ce93dd391a265210441ff70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 22 Sep 2015 03:48:47 +0100 Subject: [PATCH 0269/1476] fix travis to ignore phpcs warnings --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1aea05fd3..b9669e624 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ before_script: script: - sh -c "if [ '$DEFAULT' = '1' ]; then phpunit --stderr; fi" - - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" + - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p -n --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then phpunit --stderr --coverage-clover build/logs/clover.xml; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then php vendor/bin/coveralls -c .coveralls.yml -v; fi" From 684f0c5d131ebce544808668165b49eceff6956f Mon Sep 17 00:00:00 2001 From: David Albrecht Date: Tue, 22 Sep 2015 12:22:56 +0200 Subject: [PATCH 0270/1476] new German translations --- Locale/deu/LC_MESSAGES/users.mo | Bin 9265 -> 11745 bytes Locale/deu/LC_MESSAGES/users.po | 313 ++++++++++++-------------------- 2 files changed, 120 insertions(+), 193 deletions(-) diff --git a/Locale/deu/LC_MESSAGES/users.mo b/Locale/deu/LC_MESSAGES/users.mo index 67ba5d6917bde5f70d7433d1f3c2472bf888ab8a..295f39e21fb3a5f53ec3501020ffb9f5ad89d545 100644 GIT binary patch delta 5096 zcmaKtdvIMv8NfFw&?ceprfEY1+m=8IY1)Ps`lL2Z+6I~up~SXe>&d;Fdk?+$oN&&$ zNfRDdv49vT>OnELn!N~PFHG~Qbjd`P9qa*p=_`p%7-Bog|35h;N5oq zK`0xHLVjwDM-6<|@+g$|Z^9YyJt+H~g!AEtkUOecUe<8Fs;48DJqMl&S6W^OWuuL- z7H+lN3uV0zMd2Y>50Ah~_+!XVJ;Y-sd=heL^*rQk^?N&h7p~=e^*$XrpqbT8uno?J z2cdj$1C$$%KsorEcKm%P8$WEvV^B=}YbY0a5z38^L9xJJp}62AY=9rZqI4Q?u=sWZ zlmqrdIXDZ&R0B{pzRteC11zv$6{1cRQS2HQDG>|*1L$k5} z20FJgAs>wM5R<+PMe{$y1+apz>R>&T;A@2`*aI~jgIB}X;5xW=u2L7k0LsA+KsoTI zP|kVUj$fFI{l&CzFoBZlIOM1P%|lE$3vDC@=0kbk0N214JD;}m2jME_uZIiaBTy86 z7Pi1Q;c_?=Kg)O%l;F-4=`_)~4a!Y_1{cHUp?q)xo(Ips9CyHNa3wqnTj8mkA}(AD zHSB@nvOy?5zaEOK4nuL_SD{$s9w>?w@24X-J!<(Xlnvg5vcWrW89V{S^mS+{2XBCz zpa*5+hu|9cI2?f|;5l#zbBIOm<#84qgL3m%;YE`F|D+=at{{g*v(<1L+yuuf&>TuE z?BFZe@POqlaG3GKP+Zi688DVw0kO8~fU@5{NLZ+pogaX*egs}9`TsRKV$$cJZ168A zF)`~*QW7qLTt;<5*|690AS8oS1SO~rLoxL?pd4@?l$iMm6iYq{#kJ#5EcOnZE&2a< zIudl1*hgG3ABsg5LD^_Al=n^W9Jmomnx>$JdB{&4;UNX+5hyo))bf{5EOHFW1^)s? z;YyAD*VCCt2QR40proSp1U!)_xYO)g>plIF&<)$fkD)jAq0ba~_ z1j@$0g;U^5umc{0B!p@>S1H0ut%p)a_FCQw*D?M%#3-uxH#$-X<}{TG$rdQSIRMwd z+u-@|8Tb%94rTq_EFyo^Z{T_GBgo~{c?_n(ZYUSn3*~|a%Eb;rape(+B1QEbI`YBG z@D%tuoC@ED)$lkJ1x{KnVX&F;F4zu_z#8}x+zQ`---b(@mBJh9X-Gz^x1lIlfjPuN z=fc&J|Lt@{fgxB0Z-Tqw?XUt$!~KaF2jPfJOlrGq|H!1d4E;|bcOo2-G|40}y~K-L zvhtB_u&7-NSY)S(37S zK~XB3H1YN1wx7WYJMl%!R)`mpoW32Nj(CVfy0q;jB+nt+#~VqieQDCW&GfrV<6`0q z-@d#9N>E9=43WSoH>vdnL|k+bxdf4R6C!?=){Imm68WD+ZbQC|xCn`nq@1``YQTla zG;xkpz)FNfNOJmWC;=mFHPVE99x1n*>0F8&K&BuUAX!8sUqI4G53&i_ihK^KM?Q^6 zE!l?jBa%f|aDLKO^4y3lD-DynFI|b)9mo>o8ssy`JVe^{NPsxVUZfrAMXp6|MQ%Z+ zB2q8P?FQTFg!_<&Lp-jtlWSogawQ_U+7aicJu$_EVZ6Aid2uRoeJ@m7(rMjpBFD`o z-77;ANQYPP?y3>9H84(Ow4*&Us560I=vSqwv}!jw6B Hd0Y}0PSRN(f@Ijl;K zC_$%_Ph|_44dee*Eh*X+9ceczecq85rM9^ym*$y^P;8qYWc)}E`Gr9DJ7GBJ2kFgf zyQmdvH;mil5D zru_^mb~&DtF}f}Aopj3Kt1D7|zfoPu9YWRRr`U#S;1HtR6!54v7PH>L_fV7#aiqo#07sQp5etW2>B(~%!J zIo3x`5XlF=XIJ7SnPV^GrR|$Wx{Yc=JL!!6s^;R#-G1mM5!D^|eQwU^5X+}q)a53{ z*}AuE%aEBIp_?un<#J+JXtAP`rJO?|Si~88>gYv5B&|wDt%y%w5`CcZ*&4nW>my))z&WC z>3Ep}4p`5=2iiNT_blITJQFyPAFS8izLDHn)v~r_b$qh+t<&}uGOUk}&2PSF%R#Z3 zDd(Ziy54Z1Z~UnYQ*Fj8M8oJhdD51Ey1FMW=x{wl`WFnAEcEvigI>%^snkWG8F1VrCNg|Fv*4IbmQ3bMAL(w@$yiOP- z#AL(96`PgsFflP<{fU_^ULHdf$mmZLhQP?agARp|%8^`nrb$y2+l&+R8aFagJh*Uw zOCbz(-u2SNxA8*i#6E*+TrEd1=nzX#V8o?~D)Ea87p=6O+V!!IsRks-gvpX&pv$_( zA1vHcyh4sF*8_1$QX2k$L6Bvx7vfMSA5k!py3kDWxaAUnrTWm5PYQk*p`ZkbeJ)%fA8SDLe)P}l(tDmgA@iXW_7dXaA9W#W#oAlqXp6ObVs+HTjmIXzei()=fUtkUSS z4a=s~QW?s23$g7{>9_7Nr7RC|g@-d)oqq(iY0rQlQY%maQ#|6w6i|I+tORS?VkW8f27+ z27xB#B8fy3ZGy&#iP%68`66f{2`(RqA%;j06k-fPKcLY_{6EtRF`n?w@0{B^_nh;d z_YOC=oL-UmA!pd@hSp6?BIc$Ua|m0XaRf?B{^ScPY>5^uZX z9P+N(X+Wj63$^f9uo&M)-G33w@jf2KiP_|T7M=H*eKvlNN_7V5uy6({#jVKcn02UB zZbdD`M(yMn>ZnfObR0ls>I&+)_i-_nl7BtNgW6~yhx{L=Gr)x@SVeyFa03=$2(`0* zticbk1#jV3DeQ*x(oy|MB~HaG268_3;Wku}UPB%2J=ZkSIiGQEf{rq<26f{LsIxkb z6*z#}@i)jO%r)fL%`d3b{(;(29{FZXW-=-xweGkcRjligJ({hkg@jS_C0?SV2cN(? zJcSGKj(bBX>0l1C0CnFw)C0Rw69-W#--FdSfYhD2iaNRu8~wnEYpoQJGkbTF7?XkB8jr>73s##^uprY!{5)#G7cdRKz(Tx?s`9(8_dH_%o-}bjabgOA62ZMpcZliweY*B+IWbXcqD1j z-8$jyoz)2J=}oT zF$LB1w*0qgVJdhv-jqc0bpoK5E)U?BEVN5_KMC)#vZEmPf+zo~UW}1Z~r9@3z*u-*--CHxG7=UYVK~ z3Geg=Y%A*NwY^nly&X(`-)gg+zsDRLyfXGos&jlo)8J1N&ZanT<~h#d{13CMD`(BE zoLy_po>MoccE+sg!N2k|Q_5RCAz$3%v+Jzob|mNtjp(dg8@9dvSmm;CJQR!URJ7~5!v;;}wEV(s#W`rQmVEcDCtETo3E-Wic Sb6za(8vM2VXsUChvg2PbyiuP3 diff --git a/Locale/deu/LC_MESSAGES/users.po b/Locale/deu/LC_MESSAGES/users.po index 7324227d0..3793729a7 100644 --- a/Locale/deu/LC_MESSAGES/users.po +++ b/Locale/deu/LC_MESSAGES/users.po @@ -12,16 +12,16 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users Plugin\n" "POT-Creation-Date: 2010-09-15 15:48+0200\n" -"PO-Revision-Date: 2011-04-28 23:38+0100\n" +"PO-Revision-Date: 2015-09-22 12:21+0200\n" "Last-Translator: Florian Krämer \n" "Language-Team: Cake Development Corporation \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-Poedit-Language: German\n" -"X-Poedit-Country: GERMANY\n" "X-Poedit-SourceCharset: utf-8\n" +"Language: de_DE\n" +"X-Generator: Poedit 1.8.4\n" #: /controllers/details_controller.php:57;138 msgid "Invalid Detail." @@ -37,23 +37,23 @@ msgstr "%s Details gespeichert" #: /controllers/details_controller.php:113;196 msgid "Invalid id for Detail" -msgstr "" +msgstr "Ungültige Id für Detail" #: /controllers/details_controller.php:117;200 msgid "Detail deleted" -msgstr "" +msgstr "Detail gelöscht" #: /controllers/details_controller.php:152;175 msgid "The Detail has been saved" -msgstr "" +msgstr "Das Detail wurde gespeichert" #: /controllers/details_controller.php:155;178 msgid "The Detail could not be saved. Please, try again." -msgstr "" +msgstr "Das Detail konnte nicht gespeichert werden. Bitte versuche es erneut." #: /controllers/details_controller.php:170 msgid "Invalid Detail" -msgstr "" +msgstr "Ungültiges Detail" #: /controllers/users_controller.php:157 msgid "Profile saved." @@ -77,10 +77,9 @@ msgstr "Benutzer gespeichert." #: /controllers/users_controller.php:247 msgid "User deleted" -msgstr "" +msgstr "Benutzer gelöscht" -#: /controllers/users_controller.php:249 -#: /models/user.php:703 +#: /controllers/users_controller.php:249 /models/user.php:703 msgid "Invalid User" msgstr "Ungültiger Benutzer" @@ -268,245 +267,181 @@ msgstr "" msgid "floriank you have successfully logged out" msgstr "" -#: /views/details/add.ctp:4 -#: /views/details/admin_add.ctp:4 +#: /views/details/add.ctp:4 /views/details/admin_add.ctp:4 msgid "Add Detail" -msgstr "" +msgstr "Detail hinzufügen" -#: /views/details/add.ctp:17 -#: /views/details/admin_add.ctp:17 -#: /views/details/admin_edit.ctp:19 -#: /views/details/admin_view.ctp:45 +#: /views/details/add.ctp:17 /views/details/admin_add.ctp:17 +#: /views/details/admin_edit.ctp:19 /views/details/admin_view.ctp:45 #: /views/details/view.ctp:45 msgid "List Details" -msgstr "" +msgstr "Details anzeigen" -#: /views/details/add.ctp:18 -#: /views/details/admin_add.ctp:18 -#: /views/details/admin_edit.ctp:20 -#: /views/details/admin_index.ctp:67 -#: /views/details/admin_view.ctp:47 -#: /views/details/view.ctp:47 -#: /views/users/add.ctp:15 -#: /views/users/admin_add.ctp:13 -#: /views/users/admin_edit.ctp:15 -#: /views/users/admin_view.ctp:25 +#: /views/details/add.ctp:18 /views/details/admin_add.ctp:18 +#: /views/details/admin_edit.ctp:20 /views/details/admin_index.ctp:67 +#: /views/details/admin_view.ctp:47 /views/details/view.ctp:47 +#: /views/users/add.ctp:15 /views/users/admin_add.ctp:13 +#: /views/users/admin_edit.ctp:15 /views/users/admin_view.ctp:25 msgid "List Users" -msgstr "" +msgstr "Benutzer anzeigen" -#: /views/details/add.ctp:19 -#: /views/details/admin_add.ctp:19 -#: /views/details/admin_edit.ctp:21 -#: /views/details/admin_index.ctp:68 -#: /views/details/admin_view.ctp:48 -#: /views/details/view.ctp:48 -#: /views/users/admin_view.ctp:26 -#: /views/users/index.ctp:46 +#: /views/details/add.ctp:19 /views/details/admin_add.ctp:19 +#: /views/details/admin_edit.ctp:21 /views/details/admin_index.ctp:68 +#: /views/details/admin_view.ctp:48 /views/details/view.ctp:48 +#: /views/users/admin_view.ctp:26 /views/users/index.ctp:46 msgid "New User" -msgstr "" +msgstr "Neuer Benutzer" -#: /views/details/add.ctp:20 -#: /views/details/admin_add.ctp:20 -#: /views/details/admin_edit.ctp:22 -#: /views/details/admin_index.ctp:69 -#: /views/details/admin_view.ctp:49 -#: /views/details/view.ctp:49 +#: /views/details/add.ctp:20 /views/details/admin_add.ctp:20 +#: /views/details/admin_edit.ctp:22 /views/details/admin_index.ctp:69 +#: /views/details/admin_view.ctp:49 /views/details/view.ctp:49 msgid "List Groups" -msgstr "" +msgstr "Gruppen anzeigen" -#: /views/details/add.ctp:21 -#: /views/details/admin_add.ctp:21 -#: /views/details/admin_edit.ctp:23 -#: /views/details/admin_index.ctp:70 -#: /views/details/admin_view.ctp:50;95 -#: /views/details/view.ctp:50;95 +#: /views/details/add.ctp:21 /views/details/admin_add.ctp:21 +#: /views/details/admin_edit.ctp:23 /views/details/admin_index.ctp:70 +#: /views/details/admin_view.ctp:50;95 /views/details/view.ctp:50;95 msgid "New Group" -msgstr "" +msgstr "Neue Gruppe" -#: /views/details/admin_edit.ctp:4 -#: /views/details/admin_view.ctp:43 -#: /views/details/edit.ctp:5 -#: /views/details/view.ctp:43 +#: /views/details/admin_edit.ctp:4 /views/details/admin_view.ctp:43 +#: /views/details/edit.ctp:5 /views/details/view.ctp:43 msgid "Edit Detail" -msgstr "" +msgstr "Detail bearbeiten" -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:86 -#: /views/details/view.ctp:86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/groups.ctp:38 -#: /views/users/index.ctp:33 +#: /views/details/admin_edit.ctp:18 /views/details/admin_index.ctp:53 +#: /views/details/admin_view.ctp:86 /views/details/view.ctp:86 +#: /views/users/admin_edit.ctp:14 /views/users/admin_index.ctp:47 +#: /views/users/groups.ctp:38 /views/users/index.ctp:33 msgid "Delete" msgstr "Löschen" -#: /views/details/admin_edit.ctp:18 -#: /views/details/admin_index.ctp:53 -#: /views/details/admin_view.ctp:44;86 -#: /views/details/view.ctp:44;86 -#: /views/users/admin_edit.ctp:14 -#: /views/users/admin_index.ctp:47 -#: /views/users/admin_view.ctp:24 -#: /views/users/index.ctp:33 +#: /views/details/admin_edit.ctp:18 /views/details/admin_index.ctp:53 +#: /views/details/admin_view.ctp:44;86 /views/details/view.ctp:44;86 +#: /views/users/admin_edit.ctp:14 /views/users/admin_index.ctp:47 +#: /views/users/admin_view.ctp:24 /views/users/index.ctp:33 msgid "Are you sure you want to delete # %s?" msgstr "Bist Du Dir sicher das Du %s löschen möchtest?" -#: /views/details/admin_index.ctp:2 -#: /views/users/register.ctp:4 +#: /views/details/admin_index.ctp:2 /views/users/register.ctp:4 msgid "Details" -msgstr "" +msgstr "Details" -#: /views/details/admin_index.ctp:6 -#: /views/users/index.ctp:6 +#: /views/details/admin_index.ctp:6 /views/users/index.ctp:6 msgid "Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%" -msgstr "" +msgstr "Seite %page% von %pages%, showing %current% records von insgesamt %count%, bei %start% anfangend und bei %end% endend" -#: /views/details/admin_index.ctp:18 -#: /views/details/admin_view.ctp:65 -#: /views/details/view.ctp:65 -#: /views/users/admin_index.ctp:21 -#: /views/users/groups.ctp:15;50 -#: /views/users/index.ctp:13 +#: /views/details/admin_index.ctp:18 /views/details/admin_view.ctp:65 +#: /views/details/view.ctp:65 /views/users/admin_index.ctp:21 +#: /views/users/groups.ctp:15;50 /views/users/index.ctp:13 msgid "Actions" -msgstr "" +msgstr "Aktionen" -#: /views/details/admin_index.ctp:51 -#: /views/details/admin_view.ctp:84 -#: /views/details/view.ctp:84 -#: /views/users/admin_index.ctp:45 +#: /views/details/admin_index.ctp:51 /views/details/admin_view.ctp:84 +#: /views/details/view.ctp:84 /views/users/admin_index.ctp:45 #: /views/users/index.ctp:31 msgid "View" -msgstr "" +msgstr "Ansicht" -#: /views/details/admin_index.ctp:52 -#: /views/details/admin_view.ctp:85 -#: /views/details/view.ctp:85 -#: /views/users/admin_index.ctp:46 -#: /views/users/groups.ctp:33 -#: /views/users/index.ctp:32 +#: /views/details/admin_index.ctp:52 /views/details/admin_view.ctp:85 +#: /views/details/view.ctp:85 /views/users/admin_index.ctp:46 +#: /views/users/groups.ctp:33 /views/users/index.ctp:32 msgid "Edit" msgstr "Bearbeiten" -#: /views/details/admin_index.ctp:60 -#: /views/users/index.ctp:40 +#: /views/details/admin_index.ctp:60 /views/users/index.ctp:40 msgid "previous" -msgstr "" +msgstr "vorherige" -#: /views/details/admin_index.ctp:62 -#: /views/users/index.ctp:42 +#: /views/details/admin_index.ctp:62 /views/users/index.ctp:42 msgid "next" -msgstr "" +msgstr "nächste" -#: /views/details/admin_index.ctp:66 -#: /views/details/admin_view.ctp:46 +#: /views/details/admin_index.ctp:66 /views/details/admin_view.ctp:46 #: /views/details/view.ctp:46 msgid "New Detail" -msgstr "" +msgstr "Neues Detail" -#: /views/details/admin_view.ctp:2 -#: /views/details/view.ctp:2 +#: /views/details/admin_view.ctp:2 /views/details/view.ctp:2 msgid "Detail" -msgstr "" +msgstr "Detail" -#: /views/details/admin_view.ctp:4;58 -#: /views/details/view.ctp:4;58 +#: /views/details/admin_view.ctp:4;58 /views/details/view.ctp:4;58 msgid "Id" -msgstr "" +msgstr "Id" -#: /views/details/admin_view.ctp:9 -#: /views/details/view.ctp:9 -#: /views/users/admin_view.ctp:2 -#: /views/users/view.ctp:2 +#: /views/details/admin_view.ctp:9 /views/details/view.ctp:9 +#: /views/users/admin_view.ctp:2 /views/users/view.ctp:2 msgid "User" msgstr "Benutzer" -#: /views/details/admin_view.ctp:14 -#: /views/details/view.ctp:14 +#: /views/details/admin_view.ctp:14 /views/details/view.ctp:14 msgid "Position" -msgstr "" +msgstr "Position" -#: /views/details/admin_view.ctp:19 -#: /views/details/view.ctp:19 +#: /views/details/admin_view.ctp:19 /views/details/view.ctp:19 msgid "Field" -msgstr "" +msgstr "Feld" -#: /views/details/admin_view.ctp:24 -#: /views/details/view.ctp:24 +#: /views/details/admin_view.ctp:24 /views/details/view.ctp:24 msgid "Value" -msgstr "" +msgstr "Wert" -#: /views/details/admin_view.ctp:29;63 -#: /views/details/view.ctp:29;63 -#: /views/users/admin_view.ctp:9 -#: /views/users/view.ctp:9 +#: /views/details/admin_view.ctp:29;63 /views/details/view.ctp:29;63 +#: /views/users/admin_view.ctp:9 /views/users/view.ctp:9 msgid "Created" -msgstr "" +msgstr "Erstellt" -#: /views/details/admin_view.ctp:34;64 -#: /views/details/view.ctp:34;64 +#: /views/details/admin_view.ctp:34;64 /views/details/view.ctp:34;64 #: /views/users/admin_view.ctp:14 msgid "Modified" -msgstr "" +msgstr "Bearbeitet" -#: /views/details/admin_view.ctp:44 -#: /views/details/view.ctp:44 +#: /views/details/admin_view.ctp:44 /views/details/view.ctp:44 msgid "Delete Detail" -msgstr "" +msgstr "Detail löschen" -#: /views/details/admin_view.ctp:54 -#: /views/details/view.ctp:54 +#: /views/details/admin_view.ctp:54 /views/details/view.ctp:54 msgid "Related Groups" -msgstr "" +msgstr "Ähnliche Gruppen" -#: /views/details/admin_view.ctp:59 -#: /views/details/view.ctp:59 +#: /views/details/admin_view.ctp:59 /views/details/view.ctp:59 msgid "User Id" -msgstr "" +msgstr "Benutzer Id" -#: /views/details/admin_view.ctp:60 -#: /views/details/view.ctp:60 +#: /views/details/admin_view.ctp:60 /views/details/view.ctp:60 msgid "Is Public" -msgstr "" +msgstr "Ist öffentlich" -#: /views/details/admin_view.ctp:61 -#: /views/details/view.ctp:61 -#: /views/users/groups.ctp:13;47 -#: /views/users/search.ctp:9 +#: /views/details/admin_view.ctp:61 /views/details/view.ctp:61 +#: /views/users/groups.ctp:13;47 /views/users/search.ctp:9 msgid "Name" msgstr "Name" -#: /views/details/admin_view.ctp:62 -#: /views/details/view.ctp:62 +#: /views/details/admin_view.ctp:62 /views/details/view.ctp:62 #: /views/users/groups.ctp:48 msgid "Description" msgstr "Beschreibung" -#: /views/details/index.ctp:17 -#: /views/users/change_password.ctp:16 -#: /views/users/login.ctp:13 -#: /views/users/register.ctp:33;89 +#: /views/details/index.ctp:17 /views/users/change_password.ctp:16 +#: /views/users/login.ctp:13 /views/users/register.ctp:33;89 #: /views/users/request_password_change.ctp:12 #: /views/users/reset_password.ctp:14 msgid "Submit" msgstr "Absenden" -#: /views/elements/login.ctp:11 -#: /views/users/admin_index.ctp:10 -#: /views/users/login.ctp:8 -#: /views/users/register.ctp:71;78 +#: /views/elements/login.ctp:11 /views/users/admin_index.ctp:10 +#: /views/users/login.ctp:8 /views/users/register.ctp:71;78 #: /views/users/search.ctp:7 msgid "Email" msgstr "Email" -#: /views/elements/login.ctp:13 -#: /views/users/login.ctp:10 +#: /views/elements/login.ctp:13 /views/users/login.ctp:10 #: /views/users/register.ctp:19 msgid "Password" msgstr "Passwort" -#: /views/elements/login.ctp:15 -#: /views/users/login.ctp:1;3 +#: /views/elements/login.ctp:15 /views/users/login.ctp:1;3 msgid "Login" msgstr "Anmeldung" @@ -522,36 +457,30 @@ msgstr "um Deinen Account zu aktivieren mußt Du diese URL innerhalb von 24 Stun msgid "A request to reset your password was sent. To change your password click the link below." msgstr "Eine Anfrage um Dein Passwort zu resetten wurde gesendet. Um Dein Passwort zu ändern klicke auf den unten stehenden Link." -#: /views/users/add.ctp:4 -#: /views/users/admin_add.ctp:4 +#: /views/users/add.ctp:4 /views/users/admin_add.ctp:4 msgid "Add User" msgstr "Benutzer hinzufügen" -#: /views/users/admin_edit.ctp:4 -#: /views/users/admin_view.ctp:23 +#: /views/users/admin_edit.ctp:4 /views/users/admin_view.ctp:23 #: /views/users/edit.ctp:3 msgid "Edit User" msgstr "Benutzer bearbeiten" -#: /views/users/admin_index.ctp:2 -#: /views/users/index.ctp:2 +#: /views/users/admin_index.ctp:2 /views/users/index.ctp:2 msgid "Users" msgstr "Benutzer" #: /views/users/admin_index.ctp:4 msgid "Filter" -msgstr "" +msgstr "Filter" -#: /views/users/admin_index.ctp:8 -#: /views/users/admin_view.ctp:4 -#: /views/users/register.ctp:57;63 -#: /views/users/search.ctp:5 +#: /views/users/admin_index.ctp:8 /views/users/admin_view.ctp:4 +#: /views/users/register.ctp:57;63 /views/users/search.ctp:5 #: /views/users/view.ctp:4 msgid "Username" msgstr "Benutzername" -#: /views/users/admin_index.ctp:11 -#: /views/users/search.ctp:10 +#: /views/users/admin_index.ctp:11 /views/users/search.ctp:10 msgid "Search" msgstr "Suche" @@ -571,13 +500,11 @@ msgstr "Bitte gib Dein altes Passwort aus Sicherheitsgründen ein und dann gib D msgid "Old Password" msgstr "Altes Passwort" -#: /views/users/change_password.ctp:11 -#: /views/users/reset_password.ctp:9 +#: /views/users/change_password.ctp:11 /views/users/reset_password.ctp:9 msgid "New Password" msgstr "Neues Passwort" -#: /views/users/change_password.ctp:14 -#: /views/users/reset_password.ctp:12 +#: /views/users/change_password.ctp:14 /views/users/reset_password.ctp:12 msgid "Confirm" msgstr "Bestätigen" @@ -587,7 +514,7 @@ msgstr "Willkommen" #: /views/users/dashboard.ctp:3 msgid "Recent broadcasts" -msgstr "" +msgstr "Kürzliche Broadcast" #: /views/users/groups.ctp:2 msgid "My Groups" @@ -595,7 +522,7 @@ msgstr "Meine Gruppen" #: /views/users/groups.ctp:5 msgid "Create a new group" -msgstr "" +msgstr "Eine neue Gruppe anlegen" #: /views/users/groups.ctp:6 msgid "Invite a user" @@ -603,11 +530,11 @@ msgstr "Lade einen Benutzer ein" #: /views/users/groups.ctp:7 msgid "Requests to join" -msgstr "" +msgstr "Beitrittsanfragen" #: /views/users/groups.ctp:10 msgid "My own groups" -msgstr "" +msgstr "Meine Gruppen" #: /views/users/groups.ctp:14;49 msgid "Members" @@ -619,23 +546,23 @@ msgstr "Benutzer einladen" #: /views/users/groups.ctp:35 msgid "Manage Broadcast Scope" -msgstr "" +msgstr "Broadcast Score verwalten" #: /views/users/groups.ctp:36 msgid "Access" -msgstr "" +msgstr "Zugang" #: /views/users/groups.ctp:37 msgid "Addons" -msgstr "" +msgstr "Addons" #: /views/users/groups.ctp:44 msgid "Groups im a member in" -msgstr "" +msgstr "Gruppen von denen ich ein Mitglied bin" #: /views/users/groups.ctp:68 msgid "Leave group" -msgstr "" +msgstr "Gruppe verlassen" #: /views/users/login.ctp:11 msgid "Remember Me" @@ -675,7 +602,7 @@ msgstr "Ein Account mit dieser Email-Adresse existiert bereits" #: /views/users/register.ctp:21 msgid "Must be at least 5 characters long" -msgstr "" +msgstr "Muss mindestens 5 Zeichen lang sein" #: /views/users/register.ctp:23 msgid "Password (confirm)" @@ -687,7 +614,7 @@ msgstr "Die Passwörter müssen gleich sein" #: /views/users/register.ctp:29;85 msgid "I have read and agreed to " -msgstr "" +msgstr "Ich habe gelesen und stimme zu " #: /views/users/register.ctp:29;85 msgid "Terms of Service" @@ -723,4 +650,4 @@ msgstr "Nach Benutzern suchen" #: View/Users/login.ctp:26 msgid "I forgot my password" -msgstr "Ich habe mein Passwort vergessen" \ No newline at end of file +msgstr "Ich habe mein Passwort vergessen" From 4b25a032a1c3aab5ea00b0b89606e64fe6d1f92a Mon Sep 17 00:00:00 2001 From: David Albrecht Date: Tue, 22 Sep 2015 14:12:42 +0200 Subject: [PATCH 0271/1476] fixed typo in German message --- Locale/deu/LC_MESSAGES/users.mo | Bin 11745 -> 11745 bytes Locale/deu/LC_MESSAGES/users.po | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Locale/deu/LC_MESSAGES/users.mo b/Locale/deu/LC_MESSAGES/users.mo index 295f39e21fb3a5f53ec3501020ffb9f5ad89d545..9c71ac3b704cc96f6c06df1b9d186dc57138e03f 100644 GIT binary patch delta 24 gcmaDD{V;mNXDJpFD?_8r-=%s58JBEs)rnyQ0E!w3(*OVf delta 24 gcmaDD{V;mNXDJpVD\n" "Language-Team: Cake Development Corporation \n" "MIME-Version: 1.0\n" @@ -90,7 +90,7 @@ msgstr "Du bist bereits registriert und angemeldet!" #: /controllers/users_controller.php:282 #: /tests/cases/controllers/users_controller.test.php:194 msgid "Your account has been created. You should receive an e-mail shortly to authenticate your account. Once validated you will be able to login." -msgstr "Dein Account wurde angelegt. Du solltest in Kürze eine Email erhalten um Deinen Account zu bestötigen. Einmal bestätigt wirst Du Dich anmelden können." +msgstr "Dein Account wurde angelegt. Du solltest in Kürze eine Email erhalten um Deinen Account zu bestätigen. Einmal bestätigt wirst Du Dich anmelden können." #: /controllers/users_controller.php:287 #: /tests/cases/controllers/users_controller.test.php:205 From 473b6f2d0c651028f204eeadc0f069947d9d3c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 22 Sep 2015 14:58:39 +0100 Subject: [PATCH 0272/1476] fix composer to stick to 3.0.x --- composer.json | 2 +- composer.lock | 42 +++++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index 461dbe3b2..e08bc9d95 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "cakephp-plugin", "require": { "php": ">=5.4.16", - "cakephp/cakephp": "~3.0" + "cakephp/cakephp": "~3.0.0" }, "require-dev": { "phpunit/phpunit": "*", diff --git a/composer.lock b/composer.lock index 223a588a9..78faa3434 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "042aacec48115d299cbb935ebe2d8985", + "hash": "213cd391e4c8a30ce4a23852a0e1f543", "packages": [ { "name": "aura/installer-default", @@ -127,16 +127,16 @@ }, { "name": "cakephp/cakephp", - "version": "3.0.13", + "version": "3.0.14", "source": { "type": "git", "url": "https://github.com/cakephp/cakephp.git", - "reference": "5921b2facedbc4cdcdc4daa5f736118838796bad" + "reference": "3d7c826a780f6545056f351bc5aa1623b386f0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/cakephp/zipball/5921b2facedbc4cdcdc4daa5f736118838796bad", - "reference": "5921b2facedbc4cdcdc4daa5f736118838796bad", + "url": "https://api.github.com/repos/cakephp/cakephp/zipball/3d7c826a780f6545056f351bc5aa1623b386f0c4", + "reference": "3d7c826a780f6545056f351bc5aa1623b386f0c4", "shasum": "" }, "require": { @@ -198,7 +198,7 @@ "keywords": [ "framework" ], - "time": "2015-09-07 01:53:22" + "time": "2015-09-22 02:12:36" }, { "name": "ircmaxell/password-compat", @@ -634,16 +634,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c" + "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2d7c03c0e4e080901b8f33b2897b0577be18a13c", - "reference": "2d7c03c0e4e080901b8f33b2897b0577be18a13c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef1ca6835468857944d5c3b48fa503d5554cff2f", + "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f", "shasum": "" }, "require": { @@ -692,7 +692,7 @@ "testing", "xunit" ], - "time": "2015-08-04 03:42:39" + "time": "2015-09-14 06:51:16" }, { "name": "phpunit/php-file-iterator", @@ -825,16 +825,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.6", + "version": "1.4.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b" + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3ab72c62e550370a6cd5dc873e1a04ab57562f5b", - "reference": "3ab72c62e550370a6cd5dc873e1a04ab57562f5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", "shasum": "" }, "require": { @@ -870,20 +870,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-08-16 08:51:00" + "time": "2015-09-15 10:49:45" }, { "name": "phpunit/phpunit", - "version": "4.8.6", + "version": "4.8.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2246830f4a1a551c67933e4171bf2126dc29d357" + "reference": "73fad41adb5b7bc3a494bb930d90648df1d5e74b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357", - "reference": "2246830f4a1a551c67933e4171bf2126dc29d357", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/73fad41adb5b7bc3a494bb930d90648df1d5e74b", + "reference": "73fad41adb5b7bc3a494bb930d90648df1d5e74b", "shasum": "" }, "require": { @@ -942,7 +942,7 @@ "testing", "xunit" ], - "time": "2015-08-24 04:09:38" + "time": "2015-09-20 12:56:44" }, { "name": "phpunit/phpunit-mock-objects", From 09ebdc5fd6f86d5def8f50abd759723057c1fab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 22 Sep 2015 14:59:18 +0100 Subject: [PATCH 0273/1476] remove lock file --- composer.lock | 1433 ------------------------------------------------- 1 file changed, 1433 deletions(-) delete mode 100644 composer.lock diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 78faa3434..000000000 --- a/composer.lock +++ /dev/null @@ -1,1433 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "hash": "213cd391e4c8a30ce4a23852a0e1f543", - "packages": [ - { - "name": "aura/installer-default", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/auraphp/installer-default.git", - "reference": "52f8de3670cc1ef45a916f40f732937436d028c8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/auraphp/installer-default/zipball/52f8de3670cc1ef45a916f40f732937436d028c8", - "reference": "52f8de3670cc1ef45a916f40f732937436d028c8", - "shasum": "" - }, - "type": "composer-installer", - "extra": { - "class": "Aura\\Composer\\DefaultInstaller" - }, - "autoload": { - "psr-0": { - "Aura\\Composer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Paul M. Jones", - "email": "pmjones88@gmail.com", - "homepage": "http://paul-m-jones.com" - } - ], - "description": "Installs Aura packages using the Composer defaults.", - "keywords": [ - "aura", - "installer" - ], - "time": "2012-11-26 21:35:57" - }, - { - "name": "aura/intl", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/auraphp/Aura.Intl.git", - "reference": "c5fe620167550ad6fa77dd3570fba2efc77a2a21" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/auraphp/Aura.Intl/zipball/c5fe620167550ad6fa77dd3570fba2efc77a2a21", - "reference": "c5fe620167550ad6fa77dd3570fba2efc77a2a21", - "shasum": "" - }, - "require": { - "aura/installer-default": "1.0.*", - "php": ">=5.4.0" - }, - "type": "aura-package", - "extra": { - "aura": { - "type": "library", - "config": { - "common": "Aura\\Intl\\_Config\\Common" - } - }, - "branch-alias": { - "dev-develop": "1.1.x-dev" - } - }, - "autoload": { - "psr-0": { - "Aura\\Intl": "src/" - }, - "psr-4": { - "Aura\\Intl\\_Config\\": "config/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Paul M. Jones", - "email": "pmjones88@gmail.com", - "homepage": "http://paul-m-jones.com" - }, - { - "name": "Aura.Intl Contributors", - "homepage": "https://github.com/auraphp/Aura.Intl/contributors" - }, - { - "name": "Pascal Borreli", - "email": "pascal@borreli.com" - }, - { - "name": "Mapthegod", - "email": "mapthegod@gmail.com" - }, - { - "name": "Jose Lorenzo Rodriguez", - "email": "jose.zap@gmail.com" - } - ], - "description": "The Aura.Intl package provides internationalization (I18N) tools, specifically\npackage-oriented per-locale message translation.", - "homepage": "http://auraphp.com/Aura.Intl", - "keywords": [ - "g11n", - "globalization", - "i18n", - "internationalization", - "intl", - "l10n", - "localization" - ], - "time": "2014-08-24 00:00:00" - }, - { - "name": "cakephp/cakephp", - "version": "3.0.14", - "source": { - "type": "git", - "url": "https://github.com/cakephp/cakephp.git", - "reference": "3d7c826a780f6545056f351bc5aa1623b386f0c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cakephp/cakephp/zipball/3d7c826a780f6545056f351bc5aa1623b386f0c4", - "reference": "3d7c826a780f6545056f351bc5aa1623b386f0c4", - "shasum": "" - }, - "require": { - "aura/intl": "1.1.*", - "ext-intl": "*", - "ext-mbstring": "*", - "ircmaxell/password-compat": "1.0.*", - "nesbot/carbon": "1.13.*", - "php": ">=5.4.16", - "psr/log": "1.0" - }, - "replace": { - "cakephp/cache": "self.version", - "cakephp/collection": "self.version", - "cakephp/core": "self.version", - "cakephp/database": "self.version", - "cakephp/datasource": "self.version", - "cakephp/event": "self.version", - "cakephp/filesystem": "self.version", - "cakephp/i18n": "self.version", - "cakephp/log": "self.version", - "cakephp/orm": "self.version", - "cakephp/utility": "self.version", - "cakephp/validation": "self.version" - }, - "require-dev": { - "cakephp/cakephp-codesniffer": "dev-master", - "phpunit/phpunit": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Cake\\": "src" - }, - "files": [ - "src/Core/functions.php", - "src/Collection/functions.php", - "src/I18n/functions.php", - "src/Utility/bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "CakePHP Community", - "homepage": "https://github.com/cakephp/cakephp/graphs/contributors" - } - ], - "description": "The CakePHP framework", - "homepage": "http://cakephp.org", - "keywords": [ - "framework" - ], - "time": "2015-09-22 02:12:36" - }, - { - "name": "ircmaxell/password-compat", - "version": "v1.0.4", - "source": { - "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", - "shasum": "" - }, - "require-dev": { - "phpunit/phpunit": "4.*" - }, - "type": "library", - "autoload": { - "files": [ - "lib/password.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthony Ferrara", - "email": "ircmaxell@php.net", - "homepage": "http://blog.ircmaxell.com" - } - ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", - "keywords": [ - "hashing", - "password" - ], - "time": "2014-11-20 16:49:30" - }, - { - "name": "nesbot/carbon", - "version": "1.13.0", - "source": { - "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "5cb6e71055f7b0b57956b73d324cc4de31278f42" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/5cb6e71055f7b0b57956b73d324cc4de31278f42", - "reference": "5cb6e71055f7b0b57956b73d324cc4de31278f42", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Carbon": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Brian Nesbitt", - "email": "brian@nesbot.com", - "homepage": "http://nesbot.com" - } - ], - "description": "A simple API extension for DateTime.", - "homepage": "https://github.com/briannesbitt/Carbon", - "keywords": [ - "date", - "datetime", - "time" - ], - "time": "2014-09-26 02:52:02" - }, - { - "name": "psr/log", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-0": { - "Psr\\Log\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2012-12-21 11:40:51" - } - ], - "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-06-14 21:17:01" - }, - { - "name": "opauth/facebook", - "version": "0.2.1", - "source": { - "type": "git", - "url": "https://github.com/opauth/facebook.git", - "reference": "28c0e53393a03a66cbfea03073d1d6aacfaddb69" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opauth/facebook/zipball/28c0e53393a03a66cbfea03073d1d6aacfaddb69", - "reference": "28c0e53393a03a66cbfea03073d1d6aacfaddb69", - "shasum": "" - }, - "require": { - "opauth/opauth": ">=0.2.0", - "php": ">=5.2.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "U-Zyn Chua", - "email": "chua@uzyn.com", - "homepage": "http://uzyn.com" - } - ], - "description": "Facebook strategy for Opauth", - "homepage": "http://opauth.org", - "keywords": [ - "Authentication", - "auth", - "facebook" - ], - "time": "2012-09-21 04:47:35" - }, - { - "name": "opauth/opauth", - "version": "0.4.4", - "source": { - "type": "git", - "url": "https://github.com/opauth/opauth.git", - "reference": "436fb98c2374c9e8ae4d8adddf83214bee4d9c72" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opauth/opauth/zipball/436fb98c2374c9e8ae4d8adddf83214bee4d9c72", - "reference": "436fb98c2374c9e8ae4d8adddf83214bee4d9c72", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "suggest": { - "opauth/facebook": "Allows Facebook authentication", - "opauth/google": "Allows Google authentication", - "opauth/twitter": "Allows Twitter authentication" - }, - "type": "library", - "autoload": { - "classmap": [ - "lib/Opauth/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "U-Zyn Chua", - "email": "chua@uzyn.com", - "homepage": "http://uzyn.com" - } - ], - "description": "Multi-provider authentication framework for PHP", - "homepage": "http://opauth.org", - "keywords": [ - "Authentication", - "OpenId", - "auth", - "facebook", - "google", - "oauth", - "omniauth", - "twitter" - ], - "time": "2013-05-10 09:01:52" - }, - { - "name": "opauth/twitter", - "version": "0.3.1", - "source": { - "type": "git", - "url": "https://github.com/opauth/twitter.git", - "reference": "24792d512ccc67e7d11e9249737616f039551c11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/opauth/twitter/zipball/24792d512ccc67e7d11e9249737616f039551c11", - "reference": "24792d512ccc67e7d11e9249737616f039551c11", - "shasum": "" - }, - "require": { - "opauth/opauth": ">=0.2.0", - "php": ">=5.2.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "U-Zyn Chua", - "email": "chua@uzyn.com", - "homepage": "http://uzyn.com" - } - ], - "description": "Twitter strategy for Opauth", - "homepage": "http://opauth.org", - "keywords": [ - "Authentication", - "auth", - "twitter" - ], - "time": "2013-06-12 07:50:11" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "phpDocumentor": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" - } - ], - "time": "2015-02-03 12:10:50" - }, - { - "name": "phpspec/prophecy", - "version": "v1.5.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", - "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1" - }, - "require-dev": { - "phpspec/phpspec": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2015-08-13 10:07:40" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef1ca6835468857944d5c3b48fa503d5554cff2f", - "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-09-14 06:51:16" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2015-06-21 13:08:43" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21 13:50:34" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.7", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2015-06-21 08:01:12" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2015-09-15 10:49:45" - }, - { - "name": "phpunit/phpunit", - "version": "4.8.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "73fad41adb5b7bc3a494bb930d90648df1d5e74b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/73fad41adb5b7bc3a494bb930d90648df1d5e74b", - "reference": "73fad41adb5b7bc3a494bb930d90648df1d5e74b", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": ">=1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.8.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2015-09-20 12:56:44" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.7", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5e2645ad49d196e020b85598d7c97e482725786a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5e2645ad49d196e020b85598d7c97e482725786a", - "reference": "5e2645ad49d196e020b85598d7c97e482725786a", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-08-19 09:14:08" - }, - { - "name": "sebastian/comparator", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2015-07-26 15:48:44" - }, - { - "name": "sebastian/diff", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "http://www.github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2015-02-22 15:13:53" - }, - { - "name": "sebastian/environment", - "version": "1.3.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", - "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2015-08-03 06:14:51" - }, - { - "name": "sebastian/exporter", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2015-06-21 07:55:53" - }, - { - "name": "sebastian/global-state", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", - "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2014-10-06 09:23:50" - }, - { - "name": "sebastian/recursion-context", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", - "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-06-21 08:04:50" - }, - { - "name": "sebastian/version", - "version": "1.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" - }, - { - "name": "symfony/yaml", - "version": "v2.7.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "2dc7b06c065df96cc686c66da2705e5e18aef661" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/2dc7b06c065df96cc686c66da2705e5e18aef661", - "reference": "2dc7b06c065df96cc686c66da2705e5e18aef661", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2015-08-24 07:13:45" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=5.4.16" - }, - "platform-dev": [] -} From 6c6f2c7d7ee68a12d4dfa33fae17341960a774e0 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 22 Sep 2015 17:33:16 -0500 Subject: [PATCH 0274/1476] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad114812f..995bc29d1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ CakeDC Users Plugin =================== -[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=3.x)](http://travis-ci.org/CakeDC/users) +[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=3.0.x)](http://travis-ci.org/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 2871193cd8620e278e7c4088e5e83bcfe8ccf5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 22 Sep 2015 23:53:37 +0100 Subject: [PATCH 0275/1476] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 995bc29d1..3f49668bd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ CakeDC Users Plugin [![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) -IMPORTANT: 3.x version is BETA status now, we are still improving and testing it. +IMPORTANT: 3.0.x version is BETA status now, we are still improving and testing it. The **Users** plugin is back! @@ -34,7 +34,7 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.0+ +* CakePHP 3.0.* * PHP 5.4.16+ Documentation @@ -45,15 +45,15 @@ For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory Roadmap ------ -* 3.0.0 Migration to CakePHP 3.x -* 3.0.1 General improvements +* 3.0.2 Add google authentication + * Improve unit test coverage +* YOU ARE HERE > 3.0.1 General improvements * Unit test coverage improvements * Refactor UsersTable to Behavior * Add google authentication * Add reCaptcha * Link social accounts in profile -* 3.0.2 Add google authentication - * Improve unit test coverage +* 3.0.0 Migration to CakePHP 3.0 Support ------- From ced51e0c63a585ba59372354115644d81de5ee00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 22 Sep 2015 23:54:28 +0100 Subject: [PATCH 0276/1476] Update Home.md --- Docs/Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Home.md b/Docs/Home.md index 3ae1db423..293762fda 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -13,7 +13,7 @@ That it works out of the box doesn't mean it is thought to be used exactly like Requirements ------------ -* CakePHP 3.0+ +* CakePHP 3.0.* * PHP 5.4.16+ Documentation From 7d255656a244fe720565e075b1023feac11474e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 22 Sep 2015 23:55:53 +0100 Subject: [PATCH 0277/1476] Update Installation.md --- 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 f44ff1148..c6c16960f 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -5,7 +5,7 @@ Composer ------ ``` -composer require cakedc/users:~3.0 +composer require cakedc/users:3.0.* ``` if you want to use social login features... From 930a6834b31365d89170ec697bdb584057018a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 23 Sep 2015 00:01:00 +0100 Subject: [PATCH 0278/1476] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3f49668bd..37482c153 100644 --- a/README.md +++ b/README.md @@ -45,15 +45,16 @@ For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory Roadmap ------ -* 3.0.2 Add google authentication +* 3.0.2 + * Add Google authentication + * Add Instagram authentication * Improve unit test coverage -* YOU ARE HERE > 3.0.1 General improvements +* YOU ARE HERE > 3.0.0 Migration to CakePHP 3.0 * Unit test coverage improvements * Refactor UsersTable to Behavior * Add google authentication * Add reCaptcha * Link social accounts in profile -* 3.0.0 Migration to CakePHP 3.0 Support ------- From be4b189e17b84b97481b5c4557d4ad49cd623292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 23 Sep 2015 00:13:43 +0100 Subject: [PATCH 0279/1476] update composer to use cake 3.1 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e08bc9d95..cb6dfb871 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,10 @@ { "name": "cakedc/users", - "description": "Users plugin for CakePHP 3.x", + "description": "Users plugin for CakePHP 3.1", "type": "cakephp-plugin", "require": { "php": ">=5.4.16", - "cakephp/cakephp": "~3.0.0" + "cakephp/cakephp": "~3.1.0" }, "require-dev": { "phpunit/phpunit": "*", From 4b497519014fe2171a3d225e5287777dcb54893a Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Tue, 22 Sep 2015 23:32:36 +0000 Subject: [PATCH 0280/1476] fix Email class for cake 3.1 and new flash message structure --- src/Model/Behavior/Behavior.php | 2 +- src/Model/Behavior/PasswordBehavior.php | 2 +- src/Model/Behavior/SocialAccountBehavior.php | 2 +- src/Model/Table/SocialAccountsTable.php | 2 +- src/Model/Table/UsersTable.php | 2 +- .../Controller/SocialAccountsControllerTest.php | 16 ++++++++-------- .../TestCase/Controller/Traits/BaseTraitTest.php | 2 +- .../Controller/Traits/RegisterTraitTest.php | 2 +- .../Model/Behavior/PasswordBehaviorTest.php | 2 +- .../Model/Behavior/RegisterBehaviorTest.php | 2 +- .../Model/Behavior/SocialAccountBehaviorTest.php | 2 +- .../Model/Table/SocialAccountsTableTest.php | 2 +- tests/TestCase/Model/Table/UsersTableTest.php | 2 +- 13 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index a8379b076..d0307d980 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -13,7 +13,7 @@ use Cake\Datasource\EntityInterface; use Cake\I18n\Time; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\Behavior as BaseBehavior; /** diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 76b4a2d42..fc87c150d 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -16,7 +16,7 @@ use CakeDC\Users\Exception\WrongPasswordException; use CakeDC\Users\Model\Behavior\Behavior; use Cake\Datasource\EntityInterface; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\Utility\Hash; use InvalidArgumentException; diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index e9cf6d3eb..8b37502b2 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -21,7 +21,7 @@ use Cake\Datasource\EntityInterface; use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Event\Event; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\Entity; use InvalidArgumentException; diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 50f953e0f..4b139e415 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -18,7 +18,7 @@ use Cake\Datasource\EntityInterface; use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Event\Event; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\Entity; use Cake\ORM\RulesChecker; use Cake\ORM\Table; diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 1c33e92f6..ca088f1e2 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -14,7 +14,7 @@ use CakeDC\Users\Exception\WrongPasswordException; use CakeDC\Users\Model\Entity\User; use Cake\Datasource\EntityInterface; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Utility\Hash; diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 7f4c6a714..7b269638a 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -16,7 +16,7 @@ use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; use Cake\Event\EventManager; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\Network\Request; use Cake\TestSuite\TestCase; @@ -95,7 +95,7 @@ public function testValidateAccountHappy() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-1234'); - $this->assertEquals('Account validated successfully', $this->Controller->request->session()->read('Flash.flash.message')); + $this->assertEquals('Account validated successfully', $this->Controller->request->session()->read('Flash.flash.0.message')); } /** @@ -109,7 +109,7 @@ public function testValidateAccountInvalidToken() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-not-found'); - $this->assertEquals('Invalid token and/or social account', $this->Controller->request->session()->read('Flash.flash.message')); + $this->assertEquals('Invalid token and/or social account', $this->Controller->request->session()->read('Flash.flash.0.message')); } /** @@ -123,7 +123,7 @@ public function testValidateAccountAlreadyActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.message')); + $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.0.message')); } /** @@ -146,7 +146,7 @@ public function testResendValidationHappy() ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->resendValidation('Facebook', 'reference-1-1234'); - $this->assertEquals('Email sent successfully', $this->Controller->request->session()->read('Flash.flash.message')); + $this->assertEquals('Email sent successfully', $this->Controller->request->session()->read('Flash.flash.0.message')); } /** @@ -169,7 +169,7 @@ public function testResendValidationEmailError() ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->resendValidation('Facebook', 'reference-1-1234'); - $this->assertEquals('Email could not be sent', $this->Controller->request->session()->read('Flash.flash.message')); + $this->assertEquals('Email could not be sent', $this->Controller->request->session()->read('Flash.flash.0.message')); } /** @@ -183,7 +183,7 @@ public function testResendValidationInvalid() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->resendValidation('Facebook', 'reference-invalid'); - $this->assertEquals('Invalid account', $this->Controller->request->session()->read('Flash.flash.message')); + $this->assertEquals('Invalid account', $this->Controller->request->session()->read('Flash.flash.0.message')); } /** @@ -197,6 +197,6 @@ public function testResendValidationAlreadyActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.message')); + $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.0.message')); } } diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 5905c7ee6..131d58aa5 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Event\Event; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use PHPUnit_Framework_MockObject_RuntimeException; diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 7d737f45b..0ea8e721e 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -14,7 +14,7 @@ use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; use Cake\Core\Configure; use Cake\Core\Plugin; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\TableRegistry; class RegisterTraitTest extends BaseTraitTest diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 85defd0f8..f782e0d0c 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -13,7 +13,7 @@ use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Model\Table\UsersTable; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 79df58c67..5148525ce 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use InvalidArgumentException; diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index d341d6927..2c0344bb7 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -13,7 +13,7 @@ use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Event\Event; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index 40e99c912..e57156cec 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -14,7 +14,7 @@ use CakeDC\Users\Model\Table\SocialAccountsTable; use CakeDC\Users\Model\Table\UsersTable; use Cake\Event\Event; -use Cake\Network\Email\Email; +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 05011fbf7..ecafc1817 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -16,7 +16,7 @@ use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Plugin; -use Cake\Network\Email\Email; +use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; From 257efa5f75298237a8129a8dc838057e0eca988d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 23 Sep 2015 00:41:24 +0100 Subject: [PATCH 0281/1476] fix docs for 3.1 --- Docs/Documentation/Installation.md | 2 +- Docs/Home.md | 2 +- README.md | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index c6c16960f..cf93f6d14 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -5,7 +5,7 @@ Composer ------ ``` -composer require cakedc/users:3.0.* +composer require cakedc/users:3.1.* ``` if you want to use social login features... diff --git a/Docs/Home.md b/Docs/Home.md index 293762fda..4250dea39 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -13,7 +13,7 @@ That it works out of the box doesn't mean it is thought to be used exactly like Requirements ------------ -* CakePHP 3.0.* +* CakePHP 3.1.* * PHP 5.4.16+ Documentation diff --git a/README.md b/README.md index 37482c153..23fbad85f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ CakeDC Users Plugin =================== -[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=3.0.x)](http://travis-ci.org/CakeDC/users) +[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=3.1.x)](http://travis-ci.org/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) -IMPORTANT: 3.0.x version is BETA status now, we are still improving and testing it. +IMPORTANT: 3.1.x version is BETA status now, we are still improving and testing it. The **Users** plugin is back! @@ -34,7 +34,7 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.0.* +* CakePHP 3.1.* * PHP 5.4.16+ Documentation @@ -45,11 +45,11 @@ For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory Roadmap ------ -* 3.0.2 +* 3.1.2 * Add Google authentication * Add Instagram authentication * Improve unit test coverage -* YOU ARE HERE > 3.0.0 Migration to CakePHP 3.0 +* YOU ARE HERE > 3.1.0 Migration to CakePHP 3.0 * Unit test coverage improvements * Refactor UsersTable to Behavior * Add google authentication From 6a9cba6e4d52911ca5847d41dff22188b3798b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 23 Sep 2015 13:21:43 +0100 Subject: [PATCH 0282/1476] Update .semver --- .semver | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.semver b/.semver index c8cec4bb8..daa667f3f 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- -:major: 2 +:major: 3 :minor: 1 -:patch: 1 +:patch: 0 :special: '' From 3c52743074cdd666c40e4e6312c6c8d294122dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 23 Sep 2015 23:00:57 +0100 Subject: [PATCH 0283/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index c8cec4bb8..d834cab69 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 2 :minor: 1 -:patch: 1 +:patch: 2 :special: '' From 3af374571db877e2ee1f8eff978f0a58b8458917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 23 Sep 2015 23:13:25 +0100 Subject: [PATCH 0284/1476] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ca37d52c..fc81262aa 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,14 @@ CakeDC Users Plugin [![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) -**IMPORTANT: 3.x version is ALPHA status now and you can check it out from [CakeDC Users Plugin for CakePHP 3.x](https://github.com/cakedc/users/tree/3.x)!, we are constantly improving and testing it now.** +Versions and branches +--------------------- + +| CakePHP | CakeDC Users Plugin | Tag | Notes | +| :-------------: | :------------------------: | :--: | :---- | +| 2.x | [master](https://github.com/cakedc/users/tree/master) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | +| 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stability is beta, but pretty stable now | +| 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stability is beta, but pretty stable now | The **Users** plugin is for allowing users to register and login manage their profile. It also allows admins to manage the users. From 0ddd715a61292d5a29b11962ba5026ff236d8f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 23 Sep 2015 23:17:42 +0100 Subject: [PATCH 0285/1476] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 23fbad85f..72a95e3b7 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,15 @@ CakeDC Users Plugin IMPORTANT: 3.1.x version is BETA status now, we are still improving and testing it. +Versions and branches +--------------------- + +| CakePHP | CakeDC Users Plugin | Tag | Notes | +| :-------------: | :------------------------: | :--: | :---- | +| 2.x | [master](https://github.com/cakedc/users/tree/master) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | +| 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stability is beta, but pretty stable now | +| 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stability is beta, but pretty stable now | + The **Users** plugin is back! It covers the following features: From b8c71a97037c76d2a673d99271cbb6459a735de2 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Thu, 24 Sep 2015 00:01:15 +0000 Subject: [PATCH 0286/1476] fix validation to notBlank per 2.7 deprecation of notEmpty --- Model/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Model/User.php b/Model/User.php index 67fa27003..a4b2e2e22 100644 --- a/Model/User.php +++ b/Model/User.php @@ -86,7 +86,7 @@ class User extends UsersAppModel { public $validate = array( 'username' => array( 'required' => array( - 'rule' => array('notEmpty'), + 'rule' => array('notBlank'), 'required' => true, 'allowEmpty' => false, 'message' => 'Please enter a username.' ), @@ -120,7 +120,7 @@ class User extends UsersAppModel { 'message' => 'The password must have at least 6 characters.' ), 'required' => array( - 'rule' => 'notEmpty', + 'rule' => 'notBlank', 'message' => 'Please enter a password.' ) ), From 6f07c11742ee4b356376e9efbce3da4acebc0ab7 Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Thu, 24 Sep 2015 00:10:42 +0000 Subject: [PATCH 0287/1476] fix notBlank to be backward compatible --- Model/User.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Model/User.php b/Model/User.php index a4b2e2e22..cb8c2456c 100644 --- a/Model/User.php +++ b/Model/User.php @@ -86,8 +86,9 @@ class User extends UsersAppModel { public $validate = array( 'username' => array( 'required' => array( - 'rule' => array('notBlank'), - 'required' => true, 'allowEmpty' => false, + 'rule' => array('minLength', 1), + 'required' => true, + 'allowEmpty' => false, 'message' => 'Please enter a username.' ), 'alpha' => array( @@ -120,7 +121,7 @@ class User extends UsersAppModel { 'message' => 'The password must have at least 6 characters.' ), 'required' => array( - 'rule' => 'notBlank', + 'rule' => array('minLength', 1), 'message' => 'Please enter a password.' ) ), From 5b0f7671f14fe7d37c1428b53c539a6d6ff179ae Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Thu, 24 Sep 2015 00:33:36 +0000 Subject: [PATCH 0288/1476] add test and checking notEmpty backward compatible --- Model/User.php | 6 +----- Test/Case/Model/UserTest.php | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Model/User.php b/Model/User.php index cb8c2456c..a73ab8c56 100644 --- a/Model/User.php +++ b/Model/User.php @@ -86,7 +86,7 @@ class User extends UsersAppModel { public $validate = array( 'username' => array( 'required' => array( - 'rule' => array('minLength', 1), + 'rule' => array('custom', '/.+/'), 'required' => true, 'allowEmpty' => false, 'message' => 'Please enter a username.' @@ -120,10 +120,6 @@ class User extends UsersAppModel { 'rule' => array('minLength', '6'), 'message' => 'The password must have at least 6 characters.' ), - 'required' => array( - 'rule' => array('minLength', 1), - 'message' => 'Please enter a password.' - ) ), 'temppassword' => array( 'rule' => 'confirmPassword', diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index ac5750bd7..1cb06c46c 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -256,6 +256,28 @@ public function testRegister() { $this->assertEquals(array_keys($this->User->invalidFields()), array( 'password')); + $postData = array('User' => array( + 'username' => ' ', + 'email' => 'test@test.com', + 'password' => '123456', + 'temppassword' => '123456', + 'tos' => 1)); + $result = $this->User->register($postData); + $this->assertFalse($result); + $this->assertEquals(array_keys($this->User->invalidFields()), array( + 'username')); + + $postData = array('User' => array( + 'username' => ' ', + 'email' => 'test@test.com', + 'password' => '123456', + 'temppassword' => '123456', + 'tos' => 1)); + $result = $this->User->register($postData); + $this->assertFalse($result); + $this->assertEquals(array_keys($this->User->invalidFields()), array( + 'username')); + $postData = array('User' => array( 'username' => 'imanewuser', 'email' => 'foo@bar.com', From e8e2b65c96e552d46066229c72f754d43ae2d7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 24 Sep 2015 01:49:11 +0100 Subject: [PATCH 0289/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index d834cab69..f7db3a29f 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 2 :minor: 1 -:patch: 2 +:patch: 3 :special: '' From 4d775c00f8f3b02f575bf4cbe6e3340f2a1fed5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 24 Sep 2015 01:52:26 +0100 Subject: [PATCH 0290/1476] Update CHANGELOG.md --- CHANGELOG.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7346d789c..85b29decc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,21 @@ Changelog ========= +Release 2.1.3 +------------- + +https://github.com/CakeDC/users/tree/2.1.3 + +* Fixed unit tests for compatibility with CakePHP 2.7 + +Release 2.1.2 +------------- + +https://github.com/CakeDC/users/tree/2.1.2 + +* Minor improvements +* New translations (german and portuguese) + Release 2.1.1 ------------- @@ -43,4 +58,4 @@ https://github.com/CakeDC/users/tree/2.1.0 * [f93ce41](https://github.com/CakeDC/users/commit/f93ce41) Minor improvement to the flash message that shows the username in the UsersController.php * [b6ee0ad](https://github.com/CakeDC/users/commit/b6ee0ad) Refs https://github.com/CakeDC/users/issues/145, fixing the links in the sidebar when not used from the plugin * [720ebb5](https://github.com/CakeDC/users/commit/720ebb5) Refs https://github.com/CakeDC/users/pull/146 - * [46d6321](https://github.com/CakeDC/users/commit/46d6321) Renamed locale fre => fra, since 2.3 CakePHP uses ISO standard. \ No newline at end of file + * [46d6321](https://github.com/CakeDC/users/commit/46d6321) Renamed locale fre => fra, since 2.3 CakePHP uses ISO standard. From 811d810476022c27e42ab95aee6973370b736a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 24 Sep 2015 01:55:04 +0100 Subject: [PATCH 0291/1476] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fc81262aa..6b2217e3c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| 2.x | [master](https://github.com/cakedc/users/tree/master) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | +| 2.x | [master](https://github.com/cakedc/users/tree/master) | 2.1.3 | Note CakePHP 2.7 is currently not supported, we are working on it now | | 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stability is beta, but pretty stable now | | 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stability is beta, but pretty stable now | From 4174e9369ae156a875c6a092ca1448c65b57120e Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sat, 26 Sep 2015 02:08:30 +0000 Subject: [PATCH 0292/1476] fix migration to use boolean type correctly in Postgresql --- config/Migrations/20150513201111_initial.php | 11 ++--- tests/Fixture/SocialAccountsFixture.php | 12 +++--- tests/Fixture/UsersFixture.php | 44 ++++++++++---------- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php index b55ab65cf..d1e11e0ec 100644 --- a/config/Migrations/20150513201111_initial.php +++ b/config/Migrations/20150513201111_initial.php @@ -73,8 +73,7 @@ public function up() 'null' => true, ]) ->addColumn('active', 'boolean', [ - 'default' => 1, - 'limit' => 1, + 'default' => true, 'null' => false, ]) ->addColumn('data', 'text', [ @@ -151,13 +150,11 @@ public function up() 'null' => true, ]) ->addColumn('active', 'boolean', [ - 'default' => 0, - 'limit' => 1, + 'default' => false, 'null' => false, ]) - ->addColumn('is_superuser', 'integer', [ - 'default' => 0, - 'limit' => 1, + ->addColumn('is_superuser', 'boolean', [ + 'default' => false, 'null' => false, ]) ->addColumn('role', 'string', [ diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 6f3d9dda8..7e014fa58 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -27,7 +27,7 @@ class SocialAccountsFixture extends TestFixture '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' => '1', '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], @@ -58,7 +58,7 @@ class SocialAccountsFixture extends TestFixture 'token' => 'token-1234', 'token_secret' => 'Lorem ipsum dolor sit amet', 'token_expires' => '2015-05-22 21:52:44', - 'active' => 0, + 'active' => false, 'data' => '', 'created' => '2015-05-22 21:52:44', 'modified' => '2015-05-22 21:52:44' @@ -74,7 +74,7 @@ class SocialAccountsFixture extends TestFixture 'token' => 'token-1234', 'token_secret' => 'Lorem ipsum dolor sit amet', 'token_expires' => '2015-05-22 21:52:44', - 'active' => 1, + 'active' => true, 'data' => '', 'created' => '2015-05-22 21:52:44', 'modified' => '2015-05-22 21:52:44' @@ -90,7 +90,7 @@ class SocialAccountsFixture extends TestFixture 'token' => 'token-reference-2-1', 'token_secret' => 'Lorem ipsum dolor sit amet', 'token_expires' => '2015-05-22 21:52:44', - 'active' => 1, + 'active' => true, 'data' => '', 'created' => '2015-05-22 21:52:44', 'modified' => '2015-05-22 21:52:44' @@ -106,7 +106,7 @@ class SocialAccountsFixture extends TestFixture 'token' => 'token-reference-2-2', 'token_secret' => 'Lorem ipsum dolor sit amet', 'token_expires' => '2015-05-22 21:52:44', - 'active' => 0, + 'active' => false, 'data' => '', 'created' => '2015-05-22 21:52:44', 'modified' => '2015-05-22 21:52:44' @@ -122,7 +122,7 @@ class SocialAccountsFixture extends TestFixture 'token' => 'token-reference-2-2', 'token_secret' => 'Lorem ipsum dolor sit amet', 'token_expires' => '2015-05-22 21:52:44', - 'active' => 0, + 'active' => false, 'data' => '', 'created' => '2015-05-22 21:52:44', 'modified' => '2015-05-22 21:52:44' diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 8ba1b1d9a..4521f5270 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -38,8 +38,8 @@ class UsersFixture extends TestFixture '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], 'tos_date' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'active' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => '0', 'comment' => '', 'precision' => null], - 'is_superuser' => ['type' => 'integer', 'length' => 1, 'unsigned' => false, 'null' => false, 'default' => '0', 'comment' => '', 'precision' => null, 'autoIncrement' => 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], @@ -71,8 +71,8 @@ class UsersFixture extends TestFixture 'api_token' => 'yyy', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 0, - 'is_superuser' => 1, + 'active' => false, + 'is_superuser' => true, 'role' => 'admin', 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54' @@ -89,8 +89,8 @@ class UsersFixture extends TestFixture 'api_token' => 'xxx', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 1, + 'active' => true, + 'is_superuser' => true, 'role' => 'admin', 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54' @@ -107,8 +107,8 @@ class UsersFixture extends TestFixture 'api_token' => 'xxx', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 0, - 'is_superuser' => 1, + 'active' => false, + 'is_superuser' => true, 'role' => 'admin', 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54' @@ -125,8 +125,8 @@ class UsersFixture extends TestFixture 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 4, + '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' @@ -143,8 +143,8 @@ class UsersFixture extends TestFixture 'api_token' => '', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 0, - 'is_superuser' => 0, + 'active' => true, + 'is_superuser' => false, 'role' => 'user', 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54' @@ -161,8 +161,8 @@ class UsersFixture extends TestFixture 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 6, + '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' @@ -179,8 +179,8 @@ class UsersFixture extends TestFixture 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 7, + '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' @@ -197,8 +197,8 @@ class UsersFixture extends TestFixture 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 8, + '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' @@ -215,8 +215,8 @@ class UsersFixture extends TestFixture 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 9, + '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' @@ -233,8 +233,8 @@ class UsersFixture extends TestFixture 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', - 'active' => 1, - 'is_superuser' => 10, + '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 146d781456572cb2c8442c17a0c0c6b7e98c4c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 2 Oct 2015 13:47:21 +0100 Subject: [PATCH 0293/1476] Update Installation.md --- Docs/Documentation/Installation.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index cf93f6d14..db8527cff 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -16,6 +16,18 @@ composer require opauth/facebook:1.0.x-dev composer require opauth/twitter:1.0.x-dev ``` +IMPORTANT: We have a fork adding some fixes to the facebook strategy, please add to your composer.json file: + +``` + "repositories": + [ + { + "type": "vcs", + "url": "https://github.com/CakeDC/facebook.git" + } + ], +``` + Creating Required Tables ------------------------ If you want to use the Users tables to store your users and social accounts: From a549b81cfd369467b99cec35d9714354c6ff158a Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Mon, 5 Oct 2015 10:33:22 -0430 Subject: [PATCH 0294/1476] Emails refactoring based on the new Mailer features in cakephp 3.1 --- src/Email/EmailSender.php | 83 +++++++++ src/Mailer/UserMailer.php | 88 ++++++++++ src/Model/Behavior/Behavior.php | 42 ----- src/Model/Behavior/PasswordBehavior.php | 36 ++-- src/Model/Behavior/RegisterBehavior.php | 4 +- src/Model/Behavior/SocialAccountBehavior.php | 17 +- tests/TestCase/Email/EmailSenderTest.php | 159 ++++++++++++++++++ .../Model/Behavior/PasswordBehaviorTest.php | 11 +- .../Behavior/SocialAccountBehaviorTest.php | 16 +- 9 files changed, 360 insertions(+), 96 deletions(-) create mode 100644 src/Email/EmailSender.php create mode 100644 src/Mailer/UserMailer.php create mode 100644 tests/TestCase/Email/EmailSenderTest.php diff --git a/src/Email/EmailSender.php b/src/Email/EmailSender.php new file mode 100644 index 000000000..3f75f6765 --- /dev/null +++ b/src/Email/EmailSender.php @@ -0,0 +1,83 @@ +getMailer('CakeDC/Users.User', + $this->_getEmailInstance($email))->send('validation', [$user, __d('Users', 'Your account validation link')] + ); + } + + /** + * Send the reset password email + * + * @param EntityInterface $user User entity + * @param Email $email instance, if null the default email configuration with the + * @param string $template email template + * Users.validation template will be used, so set a ->template() if you pass an Email + * instance + * @return array email send result + */ + public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template = 'CakeDC/Users.reset_password') + { + $this->getMailer('CakeDC/Users.User', + $this->_getEmailInstance($email))->send('resetPassword', [$user, $template] + ); + } + + /** + * Send social validation email to the user + * + * @param EntityInterface $socialAccount social account + * @param EntityInterface $user user + * @param Email $email Email instance or null to use 'default' configuration + * @return mixed + */ + public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) + { + if (empty($email)) { + $template = 'CakeDC/Users.social_account_validation'; + } else { + $template = $email->template()['template']; + } + $this->getMailer('CakeDC/Users.User', + $this->_getEmailInstance($email))->send('socialAccountValidation', [$user, $socialAccount, $template] + ); + } + + /** + * Get or initialize the email instance. Used for mocking. + * + * @param Email $email if email provided, we'll use the instance instead of creating a new one + * @return Email + */ + protected function _getEmailInstance(Email $email = null) + { + if ($email === null) { + $email = new Email('default'); + $email->emailFormat('both'); + } + return $email; + } +} \ No newline at end of file diff --git a/src/Mailer/UserMailer.php b/src/Mailer/UserMailer.php new file mode 100644 index 000000000..519f094c8 --- /dev/null +++ b/src/Mailer/UserMailer.php @@ -0,0 +1,88 @@ +to($user['email']) + ->subject($firstName . $subject) + ->viewVars($user->toArray()) + ->template('CakeDC/Users.validation'); + + if (!empty($template)) { + $this->template($template); + } + + } + + /** + * Send the reset password email to the user + * + * @param EntityInterface $user User entity + * @param string $template string, note the first_name of the user will be prepended if exists + * + * @return array email send result + */ + protected function resetPassword(EntityInterface $user, $template = 'CakeDC/Users.reset_password') + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + $subject = __d('Users', '{0}Your reset password link', $firstName); + + $this + ->to($user['email']) + ->template($template) + ->subject($subject) + ->viewVars($user->toArray()); + } + + /** + * Send account validation email to the user + * + * @param EntityInterface $user User entity + * @param EntityInterface $socialAccount SocialAccount entity + * + * @return array email send result + */ + protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + //note: we control the space after the username in the previous line + $subject = __d('Users', '{0}Your social account validation link', $firstName); + $this + ->to($user['email']) + ->subject($subject) + ->viewVars(compact('user', 'socialAccount')); + } +} + diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index d0307d980..75752974f 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -13,7 +13,6 @@ use Cake\Datasource\EntityInterface; use Cake\I18n\Time; -use Cake\Mailer\Email; use Cake\ORM\Behavior as BaseBehavior; /** @@ -21,47 +20,6 @@ */ class Behavior extends BaseBehavior { - - /** - * Send the templated email to the user - * - * @param EntityInterface $user User entity - * @param string $subject Subject, note the first_name of the user will be prepended if exists - * @param Email $email instance, if null the default email configuration with the - * Users.validation template will be used, so set a ->template() if you pass an Email - * instance - * - * @return array email send result - */ - protected function _sendEmail(EntityInterface $user, $subject, Email $email = null) - { - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $emailInstance = $this->_getEmailInstance($email) - ->to($user['email']) - ->subject($firstName . $subject) - ->viewVars($user->toArray()); - if (empty($email)) { - $emailInstance->template('CakeDC/Users.validation'); - } - return $emailInstance->send(); - } - - /** - * Get or initialize the email instance. Used for mocking. - * - * @param Email $email if email provided, we'll use the instance instead of creating a new one - * @return Email - */ - protected function _getEmailInstance(Email $email = null) - { - if ($email === null) { - $email = new Email('default'); - $email->emailFormat('both'); - } - - return $email; - } - /** * DRY for update active and token based on validateEmail flag * diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index fc87c150d..6f5d62346 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Model\Behavior; +use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; @@ -25,6 +26,17 @@ */ class PasswordBehavior extends Behavior { + /** + * Constructor hook method. + * + * @param array $config The configuration settings provided to this behavior. + * @return void + */ + public function initialize(array $config) + { + parent::initialize($config); + $this->Email = new EmailSender(); + } /** * Resets user token * @@ -63,7 +75,7 @@ public function resetToken($reference, array $options = []) $saveResult = $this->_table->save($user); $template = !empty($options['emailTemplate']) ? $options['emailTemplate'] : 'CakeDC/Users.reset_password'; if (Hash::get($options, 'sendEmail')) { - $this->sendResetPasswordEmail($saveResult, null, $template); + $this->Email->sendResetPasswordEmail($saveResult, null, $template); } return $saveResult; } @@ -79,28 +91,6 @@ protected function _getUser($reference) return $this->_table->findAllByUsernameOrEmail($reference, $reference)->first(); } - /** - * Send the reset password email - * - * @param EntityInterface $user User entity - * @param Email $email instance, if null the default email configuration with the - * @param string $template email template - * Users.validation template will be used, so set a ->template() if you pass an Email - * instance - * @return array email send result - */ - public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template = 'CakeDC/Users.reset_password') - { - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $subject = __d('Users', '{0}Your reset password link', $firstName); - return $this->_getEmailInstance($email) - ->template($template) - ->to($user['email']) - ->subject($subject) - ->viewVars($user->toArray()) - ->send(); - } - /** * Change password method * diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index ab95edc72..d64c17d25 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Model\Behavior; +use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\TokenExpiredException; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; @@ -40,6 +41,7 @@ public function initialize(array $config) parent::initialize($config); $this->validateEmail = (bool)Configure::read('Users.Email.validate'); $this->useTos = (bool)Configure::read('Users.Tos.required'); + $this->Email = new EmailSender(); } /** @@ -63,7 +65,7 @@ public function register($user, $data, $options) $this->_table->isValidateEmail = $validateEmail; $userSaved = $this->_table->save($user); if ($userSaved && $validateEmail) { - $this->_sendEmail($user, __d('Users', 'Your account validation link'), $emailClass); + $this->Email->sendValidationEmail($user, $emailClass); } return $userSaved; } diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 8b37502b2..1c8cf8b7d 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Model\Behavior; use ArrayObject; +use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\AccountAlreadyActiveException; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -45,6 +46,8 @@ public function initialize(array $config) 'joinType' => 'INNER', 'className' => Configure::read('Users.table') ]); + $this->Email = new EmailSender(); + } /** @@ -77,18 +80,8 @@ public function afterSave(Event $event, Entity $entity, $options) */ public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) { - $emailInstance = $this->_getEmailInstance($email); - if (empty($email)) { - $emailInstance->template('CakeDC/Users.social_account_validation'); - } - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - //note: we control the space after the username in the previous line - $subject = __d('Users', '{0}Your social account validation link', $firstName); - return $emailInstance - ->to($user['email']) - ->subject($subject) - ->viewVars(compact('user', 'socialAccount')) - ->send(); + $this->Email = new EmailSender(); + $this->Email->sendSocialValidationEmail($socialAccount, $user, $email); } /** diff --git a/tests/TestCase/Email/EmailSenderTest.php b/tests/TestCase/Email/EmailSenderTest.php new file mode 100644 index 000000000..0129389b3 --- /dev/null +++ b/tests/TestCase/Email/EmailSenderTest.php @@ -0,0 +1,159 @@ +EmailSender = $this->getMockBuilder('CakeDC\Users\Email\EmailSender') + ->setMethods(['_getEmailInstance', 'getMailer']) + ->getMock(); + + $this->UserMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UserMailer') + ->setMethods(['send']) + ->getMock(); + + $this->fullBaseBackup = Router::fullBaseUrl(); + Router::fullBaseUrl('http://users.test'); + + Email::configTransport('test', [ + 'className' => 'Debug' + ]); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + Email::drop('default'); + Email::dropTransport('test'); + parent::tearDown(); + } + + /** + * test sendValidationEmail + * + * @return void + */ + public function testSendEmailValidation() + { + $table = TableRegistry::get('CakeDC/Users.Users'); + $user = $table->newEntity([ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]); + + $email = new Email([ + 'from' => 'test@example.com', + 'transport' => 'test', + 'emailFormat' => 'both', + ]); + + $this->EmailSender->expects($this->once()) + ->method('getMailer') + ->with('CakeDC/Users.User') + ->will($this->returnValue($this->UserMailer)); + + $this->UserMailer->expects($this->once()) + ->method('send') + ->with('validation', [$user, 'Your account validation link']); + + $this->EmailSender->sendValidationEmail($user, $email); + } + + /** + * test sendResetPasswordEmail + * + * @return void + */ + public function testSendResetPasswordEmailMailer() + { + $table = TableRegistry::get('CakeDC/Users.Users'); + $user = $table->newEntity([ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]); + + $email = new Email([ + 'from' => 'test@example.com', + 'transport' => 'test', + 'template' => 'CakeDC/Users.reset_password', + 'emailFormat' => 'both', + ]); + + $this->EmailSender->expects($this->once()) + ->method('getMailer') + ->with('CakeDC/Users.User') + ->will($this->returnValue($this->UserMailer)); + + $this->UserMailer->expects($this->once()) + ->method('send') + ->with('resetPassword', [$user, 'CakeDC/Users.reset_password']); + + $this->EmailSender->sendResetPasswordEmail($user, $email); + } + + /** + * test sendSocialValidationEmail + * + * @return void + */ + public function testSendSocialValidationEmailMailer() + { + $this->Table = TableRegistry::get('CakeDC/Users.SocialAccounts'); + $user = $this->Table->find()->contain('Users')->first(); + $email = new Email([ + 'from' => 'test@example.com', + 'transport' => 'test', + 'template' => 'CakeDC/Users.my_template', + 'emailFormat' => 'both', + ]); + + $this->EmailSender->expects($this->once()) + ->method('getMailer') + ->with('CakeDC/Users.User') + ->will($this->returnValue($this->UserMailer)); + + $this->UserMailer->expects($this->once()) + ->method('send') + ->with('socialAccountValidation', [$user->user, $user, 'CakeDC/Users.my_template']); + + $this->EmailSender->sendSocialValidationEmail($user, $user->user, $email); + } +} diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index f782e0d0c..7fe78fe90 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -46,6 +46,9 @@ public function setUp() ->setMethods(['sendResetPasswordEmail']) ->setConstructorArgs([$this->table]) ->getMock(); + $this->Behavior->Email = $this->getMockBuilder('CakeDC\Users\Email\EmailSender') + ->setMethods(['sendResetPasswordEmail']) + ->getMock(); } /** @@ -68,7 +71,7 @@ public function testResetToken() { $user = $this->table->findAllByUsername('user-1')->first(); $token = $user->token; - $this->Behavior->expects($this->never()) + $this->Behavior->Email->expects($this->never()) ->method('sendResetPasswordEmail') ->with($user); $result = $this->Behavior->resetToken('user-1', [ @@ -89,7 +92,7 @@ public function testResetTokenSendEmail() $user = $this->table->findAllByUsername('user-1')->first(); $token = $user->token; $tokenExpires = $user->token_expires; - $this->Behavior->expects($this->once()) + $this->Behavior->Email->expects($this->once()) ->method('sendResetPasswordEmail'); $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, @@ -149,7 +152,7 @@ public function testResetTokenUserAlreadyActive() * * @return void */ - public function testSendResetPasswordEmail() + /* public function testSendResetPasswordEmail() { $behavior = $this->table->behaviors()->Password; $this->fullBaseBackup = Router::fullBaseUrl(); @@ -208,5 +211,5 @@ public function testSendResetPasswordEmail() Router::fullBaseUrl($this->fullBaseBackup); Email::dropTransport('test'); - } + }*/ } diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index 2c0344bb7..e7924891b 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -44,16 +44,6 @@ public function setUp() parent::setUp(); $this->Table = TableRegistry::get('CakeDC/Users.SocialAccounts'); $this->Behavior = $this->Table->behaviors()->SocialAccount; - $this->fullBaseBackup = Router::fullBaseUrl(); - Router::fullBaseUrl('http://users.test'); - Email::configTransport('test', [ - 'className' => 'Debug' - ]); - $this->Email = new Email([ - 'from' => 'test@example.com', - 'transport' => 'test', - 'template' => 'CakeDC/Users.social_account_validation', - ]); } /** @@ -64,8 +54,6 @@ public function setUp() public function tearDown() { unset($this->Table, $this->Behavior, $this->Email); - Router::fullBaseUrl($this->fullBaseBackup); - Email::dropTransport('test'); parent::tearDown(); } @@ -156,7 +144,7 @@ public function testAfterSaveSocialActiveUserNotActive() * * @return void */ - public function testSendSocialValidationEmail() + /* public function testSendSocialValidationEmail() { $user = $this->Table->find()->contain('Users')->first(); $this->Email->emailFormat('both'); @@ -167,5 +155,5 @@ public function testSendSocialValidationEmail() $this->assertTextContains('Hi first1,', $result['message']); $this->assertTextContains('Activate your social login here', $result['message']); $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234', $result['message']); - } + }*/ } From 741721255b8d998f27c9fa7dd0f2504dfbc49495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 8 Oct 2015 14:26:50 +0100 Subject: [PATCH 0295/1476] refs #prefixes add prefix matcher for RBAC permission rules --- Docs/Documentation/SimpleRbacAuthorize.md | 11 ++- config/permissions.php | 11 ++- src/Auth/SimpleRbacAuthorize.php | 6 ++ .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 95 +++++++++++++++++++ 4 files changed, 113 insertions(+), 10 deletions(-) diff --git a/Docs/Documentation/SimpleRbacAuthorize.md b/Docs/Documentation/SimpleRbacAuthorize.md index d029bcca5..3eb2a109f 100644 --- a/Docs/Documentation/SimpleRbacAuthorize.md +++ b/Docs/Documentation/SimpleRbacAuthorize.md @@ -54,11 +54,12 @@ Permission rules syntax * Each rule is defined: ```php [ - 'role' => 'REQUIRED_NAME_OF_THE_ROLE_OR_*', - 'plugin' => 'OPTIONAL_NAME_OF_THE_PLUGIN_OR_*_DEFAULT_NULL', - 'controller' => 'REQUIRED_NAME_OF_THE_CONTROLLER_OR_*' - 'action' => 'REQUIRED_NAME_OF_ACTION_OR_*', - 'allowed' => 'OPTIONAL_BOOLEAN_DEFAULT_TRUE_OR_CALLABLE' + 'role' => 'REQUIRED_NAME_OF_THE_ROLE_OR_[]_OR_*', + 'prefix' => 'OPTIONAL_PREFIX_USED_OR_[]_OR_*_DEFAULT_NULL', + 'plugin' => 'OPTIONAL_NAME_OF_THE_PLUGIN_OR_[]_OR_*_DEFAULT_NULL', + 'controller' => 'REQUIRED_NAME_OF_THE_CONTROLLER_OR_[]_OR_*' + 'action' => 'REQUIRED_NAME_OF_ACTION_OR_[]_OR_*', + 'allowed' => 'OPTIONAL_BOOLEAN_OR_CALLABLE_DEFAULT_TRUE' ] ``` * If no rule allowed = true is matched for a given user role and url, default return value will be false diff --git a/config/permissions.php b/config/permissions.php index 1b76eed6c..0f8451259 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -17,12 +17,13 @@ * This is a quick roles-permissions implementation * Rules are evaluated top-down, first matching rule will apply * Each line define - * 'role-name' => * [ - * 'plugin', (default = null) - * 'controller', - * 'action', - * 'allowed' (default = true) + * 'role' => 'role' | ['roles'] | '*' + * 'prefix' => 'Prefix' | , (default = null) + * 'plugin' => 'Plugin' | , (default = null) + * 'controller' => 'Controller' | ['Controllers'] | '*', + * 'action' => 'action' | ['actions'] | '*', + * 'allowed' => true | false | callback (default = true) * ] * You could use '*' to match anything * 'allowed' will be considered true if not defined. It allows a callable to manage complex diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 47256aa6d..aec17e4c3 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -44,6 +44,7 @@ class SimpleRbacAuthorize extends BaseAuthorize * [ * 'role' => 'admin', * 'plugin', (optional, default = null) + * 'prefix', (optional, default = null) * 'controller', * 'action', * 'allowed' (optional, default = true) @@ -195,7 +196,12 @@ protected function _matchRule($permission, $user, $role, $request) $plugin = $request->plugin; $controller = $request->controller; $action = $request->action; + $prefix = null; + if (!empty($request->params['prefix'])) { + $prefix = $request->params['prefix']; + } if ($this->_matchOrAsterisk($permission, 'role', $role) && + $this->_matchOrAsterisk($permission, 'prefix', $prefix, true) && $this->_matchOrAsterisk($permission, 'plugin', $plugin, true) && $this->_matchOrAsterisk($permission, 'controller', $controller) && $this->_matchOrAsterisk($permission, 'action', $action)) { diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index 9ab9f8ab5..183611b7b 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -175,6 +175,10 @@ public function testAuthorize($permissions, $user, $requestParams, $expected, $m $request->plugin = Hash::get($requestParams, 'plugin'); $request->controller = $requestParams['controller']; $request->action = $requestParams['action']; + $prefix = Hash::get($requestParams, 'prefix'); + if ($prefix) { + $request->params = ['prefix' => $prefix]; + } $result = $this->simpleRbacAuthorize->authorize($user, $request); $this->assertSame($expected, $result, $msg); @@ -560,6 +564,97 @@ public function providerAuthorize() //expected false ], + 'happy-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['admin'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'deny-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['admin'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + 'star-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => '*', + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'array-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['one', 'admin'], + 'controller' => '*', + 'action' => '*', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], ]; } } From 6614dfb0a164a49dd854721e6f32d8d3b2e8e2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 8 Oct 2015 17:33:24 +0100 Subject: [PATCH 0296/1476] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index cb6dfb871..2071eb2b1 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "cakephp-plugin", "require": { "php": ">=5.4.16", - "cakephp/cakephp": "~3.1.0" + "cakephp/cakephp": "3.1.*" }, "require-dev": { "phpunit/phpunit": "*", From da66d90b80bb3f0329ccc9df6d462ba5d19afc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 15 Oct 2015 17:44:16 +0100 Subject: [PATCH 0297/1476] fix bug on rule calculation when negative rules matched --- src/Auth/SimpleRbacAuthorize.php | 7 ++-- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index aec17e4c3..5847e5e15 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -174,7 +174,8 @@ protected function _checkRules(array $user, $role, Request $request) { $permissions = $this->config('permissions'); foreach ($permissions as $permission) { - if ($allowed = $this->_matchRule($permission, $user, $role, $request)) { + $allowed = $this->_matchRule($permission, $user, $role, $request); + if ($allowed !== null) { return $allowed; } } @@ -189,7 +190,7 @@ protected function _checkRules(array $user, $role, Request $request) * @param array $user current user * @param string $role effective user role * @param Request $request request - * @return bool + * @return bool if rule matched, null if rule not matched */ protected function _matchRule($permission, $user, $role, $request) { @@ -216,7 +217,7 @@ protected function _matchRule($permission, $user, $role, $request) } } - return false; + return null; } /** diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index 183611b7b..7f84f7878 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -655,6 +655,38 @@ public function providerAuthorize() //expected true ], + 'array-prefix' => [ + //permissions + [ + [ + 'role' => ['test'], + 'prefix' => ['one', 'admin'], + 'controller' => '*', + 'action' => 'one', + 'allowed' => false, + ], + [ + 'role' => ['test'], + 'prefix' => ['one', 'admin'], + 'controller' => '*', + 'action' => '*', + ], + ], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], ]; } } From 81ee4f005f231a69bfaf38142be12507a8e52ab4 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 23 Oct 2015 06:26:50 -0430 Subject: [PATCH 0298/1476] Renaming UserMailer to UsersMailer --- src/Email/EmailSender.php | 6 +++--- src/Mailer/{UserMailer.php => UsersMailer.php} | 2 +- tests/TestCase/Email/EmailSenderTest.php | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) rename src/Mailer/{UserMailer.php => UsersMailer.php} (98%) diff --git a/src/Email/EmailSender.php b/src/Email/EmailSender.php index 3f75f6765..b32857bcb 100644 --- a/src/Email/EmailSender.php +++ b/src/Email/EmailSender.php @@ -24,7 +24,7 @@ class EmailSender public function sendValidationEmail(EntityInterface $user, Email $email = null) { - $this->getMailer('CakeDC/Users.User', + $this->getMailer('CakeDC/Users.Users', $this->_getEmailInstance($email))->send('validation', [$user, __d('Users', 'Your account validation link')] ); } @@ -41,7 +41,7 @@ public function sendValidationEmail(EntityInterface $user, Email $email = null) */ public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template = 'CakeDC/Users.reset_password') { - $this->getMailer('CakeDC/Users.User', + $this->getMailer('CakeDC/Users.Users', $this->_getEmailInstance($email))->send('resetPassword', [$user, $template] ); } @@ -61,7 +61,7 @@ public function sendSocialValidationEmail(EntityInterface $socialAccount, Entity } else { $template = $email->template()['template']; } - $this->getMailer('CakeDC/Users.User', + $this->getMailer('CakeDC/Users.Users', $this->_getEmailInstance($email))->send('socialAccountValidation', [$user, $socialAccount, $template] ); } diff --git a/src/Mailer/UserMailer.php b/src/Mailer/UsersMailer.php similarity index 98% rename from src/Mailer/UserMailer.php rename to src/Mailer/UsersMailer.php index 519f094c8..9fbad5dac 100644 --- a/src/Mailer/UserMailer.php +++ b/src/Mailer/UsersMailer.php @@ -18,7 +18,7 @@ * User Mailer * */ -class UserMailer extends Mailer +class UsersMailer extends Mailer { /** diff --git a/tests/TestCase/Email/EmailSenderTest.php b/tests/TestCase/Email/EmailSenderTest.php index 0129389b3..c61bd4104 100644 --- a/tests/TestCase/Email/EmailSenderTest.php +++ b/tests/TestCase/Email/EmailSenderTest.php @@ -86,7 +86,7 @@ public function testSendEmailValidation() $this->EmailSender->expects($this->once()) ->method('getMailer') - ->with('CakeDC/Users.User') + ->with('CakeDC/Users.Users') ->will($this->returnValue($this->UserMailer)); $this->UserMailer->expects($this->once()) @@ -119,7 +119,7 @@ public function testSendResetPasswordEmailMailer() $this->EmailSender->expects($this->once()) ->method('getMailer') - ->with('CakeDC/Users.User') + ->with('CakeDC/Users.Users') ->will($this->returnValue($this->UserMailer)); $this->UserMailer->expects($this->once()) @@ -147,7 +147,7 @@ public function testSendSocialValidationEmailMailer() $this->EmailSender->expects($this->once()) ->method('getMailer') - ->with('CakeDC/Users.User') + ->with('CakeDC/Users.Users') ->will($this->returnValue($this->UserMailer)); $this->UserMailer->expects($this->once()) From 47125f79560d028421b93056b806bd394e9fbdf1 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 23 Oct 2015 11:00:58 -0430 Subject: [PATCH 0299/1476] Adding unit tests to UsersMailer --- src/Mailer/UsersMailer.php | 14 +- tests/TestCase/Mailer/UsersMailerTest.php | 218 ++++++++++++++++++ .../Model/Behavior/PasswordBehaviorTest.php | 66 ------ .../Behavior/SocialAccountBehaviorTest.php | 18 -- 4 files changed, 222 insertions(+), 94 deletions(-) create mode 100644 tests/TestCase/Mailer/UsersMailerTest.php diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 9fbad5dac..027e9ed74 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -30,20 +30,14 @@ class UsersMailer extends Mailer * * @return array email send result */ - protected function validation(EntityInterface $user, $subject, $template = null) + protected function validation(EntityInterface $user, $subject, $template = 'CakeDC/Users.validation') { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $this ->to($user['email']) ->subject($firstName . $subject) ->viewVars($user->toArray()) - ->template('CakeDC/Users.validation'); - - if (!empty($template)) { - $this->template($template); - } - + ->template($template); } /** @@ -61,9 +55,9 @@ protected function resetPassword(EntityInterface $user, $template = 'CakeDC/User $this ->to($user['email']) - ->template($template) ->subject($subject) - ->viewVars($user->toArray()); + ->viewVars($user->toArray()) + ->template($template); } /** diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php new file mode 100644 index 000000000..6fdc8e19c --- /dev/null +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -0,0 +1,218 @@ +Email = $this->getMockBuilder('Cake\Mailer\Email') + ->setMethods(['to', 'subject', 'viewVars', 'template']) + ->getMock(); + + $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') + ->setConstructorArgs(array($this->Email)) + ->setMethods(['to', 'subject', 'viewVars', 'template']) + ->getMock(); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->UsersMailer); + unset($this->Email); + parent::tearDown(); + } + + /** + * test sendValidationEmail + * + * @return void + */ + public function testValidation() + { + $table = TableRegistry::get('CakeDC/Users.Users'); + $data = [ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]; + $user = $table->newEntity($data); + $this->UsersMailer->expects($this->once()) + ->method('to') + ->with($user['email']) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('subject') + ->with('FirstName, Validate your Account') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('viewVars') + ->with($data) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('template') + ->with('CakeDC/Users.validation') + ->will($this->returnValue($this->Email)); + + $this->invokeMethod($this->UsersMailer, 'validation', array($user, 'Validate your Account')); + } + + /** + * test sendValidationEmail including 'template' + * + * @return void + */ + public function testValidationWithTemplate() + { + $table = TableRegistry::get('CakeDC/Users.Users'); + $data = [ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]; + $user = $table->newEntity($data); + $this->UsersMailer->expects($this->once()) + ->method('to') + ->with($user['email']) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('subject') + ->with('FirstName, Validate your Account') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('viewVars') + ->with($data) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('template') + ->with('myTemplate') + ->will($this->returnValue($this->Email)); + + $this->invokeMethod($this->UsersMailer, 'validation', array($user, 'Validate your Account', 'myTemplate')); + } + + /** + * test SocialAccountValidation + * + * @return void + */ + public function testSocialAccountValidation() + { + $social = TableRegistry::get('CakeDC/Users.SocialAccounts')->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); + + $this->UsersMailer->expects($this->once()) + ->method('to') + ->with('user-1@test.com') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('subject') + ->with('first1, Your social account validation link') + ->will($this->returnValue($this->Email)); + + + $this->Email->expects($this->once()) + ->method('viewVars') + ->with(['user' => $social->user, 'socialAccount' => $social]) + ->will($this->returnValue($this->Email)); + + $this->invokeMethod($this->UsersMailer, 'socialAccountValidation', array($social->user, $social)); + } + + /** + * test sendValidationEmail including 'template' + * + * @return void + */ + public function testResetPassword() + { + $table = TableRegistry::get('CakeDC/Users.Users'); + $data = [ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]; + $user = $table->newEntity($data); + $this->UsersMailer->expects($this->once()) + ->method('to') + ->with($user['email']) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('subject') + ->with('FirstName, Your reset password link') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('viewVars') + ->with($data) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('template') + ->with('myTemplate') + ->will($this->returnValue($this->Email)); + + + $this->invokeMethod($this->UsersMailer, 'resetPassword', array($user, 'myTemplate')); + } + + /** + * Call protected/private method of a class. + * + * @param object &$object Instantiated object that we will run method on. + * @param string $methodName Method name to call + * @param array $parameters Array of parameters to pass into method. + * + * @return mixed Method return. + */ + public function invokeMethod(&$object, $methodName, array $parameters = array()) + { + $reflection = new \ReflectionClass(get_class($object)); + $method = $reflection->getMethod($methodName); + $method->setAccessible(true); + + return $method->invokeArgs($object, $parameters); + } +} diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 7fe78fe90..238a7923d 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -146,70 +146,4 @@ public function testResetTokenUserAlreadyActive() 'checkActive' => true, ]); } - - /** - * Test method - * - * @return void - */ - /* public function testSendResetPasswordEmail() - { - $behavior = $this->table->behaviors()->Password; - $this->fullBaseBackup = Router::fullBaseUrl(); - Router::fullBaseUrl('http://users.test'); - Email::configTransport('test', [ - 'className' => 'Debug' - ]); - $this->Email = new Email([ - 'from' => 'test@example.com', - 'transport' => 'test', - 'template' => 'CakeDC/Users.reset_password', - 'emailFormat' => 'both', - ]); - - $user = $this->table->newEntity([ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]); - - $result = $behavior->sendResetPasswordEmail($user, $this->Email, 'CakeDC/Users.reset_password'); - $this->assertTextContains('From: test@example.com', $result['headers']); - $this->assertTextContains('To: test@example.com', $result['headers']); - $this->assertTextContains('Subject: FirstName, Your reset password link', $result['headers']); - $this->assertTextContains('Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Hi FirstName, - -Please copy the following address in your web browser http://users.test/users/users/reset-password/12345 -Thank you, -', $result['message']); - $this->assertTextContains('Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: 8bit - - - - - Email/html - - -

-Hi FirstName, -

-

- Reset your password here -

-

- If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/users/reset-password/12345

-

- Thank you, -

- - -', $result['message']); - - Router::fullBaseUrl($this->fullBaseBackup); - Email::dropTransport('test'); - }*/ } diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index e7924891b..8bfc5b5a5 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -138,22 +138,4 @@ public function testAfterSaveSocialActiveUserNotActive() $entity = $this->Table->findById('00000000-0000-0000-0000-000000000002')->first(); $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); } - - /** - * Test sendSocialValidationEmail method - * - * @return void - */ - /* public function testSendSocialValidationEmail() - { - $user = $this->Table->find()->contain('Users')->first(); - $this->Email->emailFormat('both'); - $result = $this->Behavior->sendSocialValidationEmail($user, $user->user, $this->Email); - $this->assertTextContains('From: test@example.com', $result['headers']); - $this->assertTextContains('To: user-1@test.com', $result['headers']); - $this->assertTextContains('Subject: first1, Your social account validation link', $result['headers']); - $this->assertTextContains('Hi first1,', $result['message']); - $this->assertTextContains('Activate your social login here', $result['message']); - $this->assertTextContains('If the link is not correcly displayed, please copy the following address in your web browser http://users.test/users/social-accounts/validate-account/Facebook/reference-1-1234/token-1234', $result['message']); - }*/ } From 1863dc7fdbf37a33e5aae0948cc8ebb565211084 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 23 Oct 2015 11:18:59 -0430 Subject: [PATCH 0300/1476] Fixing code standards --- src/Email/EmailSender.php | 38 ++++++++++++++------ src/Mailer/UsersMailer.php | 2 -- src/Model/Behavior/SocialAccountBehavior.php | 1 - tests/TestCase/Email/EmailSenderTest.php | 6 ++-- tests/TestCase/Mailer/UsersMailerTest.php | 21 ++++++----- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/Email/EmailSender.php b/src/Email/EmailSender.php index b32857bcb..9b08f4121 100644 --- a/src/Email/EmailSender.php +++ b/src/Email/EmailSender.php @@ -10,9 +10,9 @@ */ namespace CakeDC\Users\Email; +use Cake\Datasource\EntityInterface; use Cake\Mailer\Email; use Cake\Mailer\MailerAwareTrait; -use Cake\Datasource\EntityInterface; /** * Email sender class @@ -22,11 +22,21 @@ class EmailSender { use MailerAwareTrait; + /** + * Send validation email + * + * @param EntityInterface $user User entity + * @param Email $email instance, if null the default email configuration with the + * @return void + */ public function sendValidationEmail(EntityInterface $user, Email $email = null) { - $this->getMailer('CakeDC/Users.Users', - $this->_getEmailInstance($email))->send('validation', [$user, __d('Users', 'Your account validation link')] - ); + $this + ->getMailer( + 'CakeDC/Users.Users', + $this->_getEmailInstance($email) + ) + ->send('validation', [$user, __d('Users', 'Your account validation link')]); } /** @@ -41,9 +51,12 @@ public function sendValidationEmail(EntityInterface $user, Email $email = null) */ public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template = 'CakeDC/Users.reset_password') { - $this->getMailer('CakeDC/Users.Users', - $this->_getEmailInstance($email))->send('resetPassword', [$user, $template] - ); + $this + ->getMailer( + 'CakeDC/Users.Users', + $this->_getEmailInstance($email) + ) + ->send('resetPassword', [$user, $template]); } /** @@ -61,9 +74,12 @@ public function sendSocialValidationEmail(EntityInterface $socialAccount, Entity } else { $template = $email->template()['template']; } - $this->getMailer('CakeDC/Users.Users', - $this->_getEmailInstance($email))->send('socialAccountValidation', [$user, $socialAccount, $template] - ); + $this + ->getMailer( + 'CakeDC/Users.Users', + $this->_getEmailInstance($email) + ) + ->send('socialAccountValidation', [$user, $socialAccount, $template]); } /** @@ -80,4 +96,4 @@ protected function _getEmailInstance(Email $email = null) } return $email; } -} \ No newline at end of file +} diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 027e9ed74..4f51359a5 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -20,7 +20,6 @@ */ class UsersMailer extends Mailer { - /** * Send the templated email to the user * @@ -79,4 +78,3 @@ protected function socialAccountValidation(EntityInterface $user, EntityInterfac ->viewVars(compact('user', 'socialAccount')); } } - diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 1c8cf8b7d..f6c87f01b 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -47,7 +47,6 @@ public function initialize(array $config) 'className' => Configure::read('Users.table') ]); $this->Email = new EmailSender(); - } /** diff --git a/tests/TestCase/Email/EmailSenderTest.php b/tests/TestCase/Email/EmailSenderTest.php index c61bd4104..a08755b5b 100644 --- a/tests/TestCase/Email/EmailSenderTest.php +++ b/tests/TestCase/Email/EmailSenderTest.php @@ -11,11 +11,13 @@ namespace CakeDC\Users\Test\TestCase\Email; use Cake\Mailer\Email; -use Cake\TestSuite\TestCase; use Cake\ORM\TableRegistry; -use CakeDC\Users\Mailer\UserMailer; use Cake\Routing\Router; +use Cake\TestSuite\TestCase; +/** + * Test Case + */ class EmailSenderTest extends TestCase { /** diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 6fdc8e19c..1aae78b62 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -11,11 +11,13 @@ namespace CakeDC\Users\Test\TestCase\Email; use Cake\Mailer\Email; -use Cake\TestSuite\TestCase; use Cake\ORM\TableRegistry; -use CakeDC\Users\Mailer\UserMailer; use Cake\Routing\Router; +use Cake\TestSuite\TestCase; +/** + * Test Case + */ class UsersMailerTest extends TestCase { /** @@ -41,7 +43,7 @@ public function setUp() ->getMock(); $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') - ->setConstructorArgs(array($this->Email)) + ->setConstructorArgs([$this->Email]) ->setMethods(['to', 'subject', 'viewVars', 'template']) ->getMock(); } @@ -92,7 +94,7 @@ public function testValidation() ->with('CakeDC/Users.validation') ->will($this->returnValue($this->Email)); - $this->invokeMethod($this->UsersMailer, 'validation', array($user, 'Validate your Account')); + $this->invokeMethod($this->UsersMailer, 'validation', [$user, 'Validate your Account']); } /** @@ -129,7 +131,7 @@ public function testValidationWithTemplate() ->with('myTemplate') ->will($this->returnValue($this->Email)); - $this->invokeMethod($this->UsersMailer, 'validation', array($user, 'Validate your Account', 'myTemplate')); + $this->invokeMethod($this->UsersMailer, 'validation', [$user, 'Validate your Account', 'myTemplate']); } /** @@ -139,7 +141,8 @@ public function testValidationWithTemplate() */ public function testSocialAccountValidation() { - $social = TableRegistry::get('CakeDC/Users.SocialAccounts')->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); + $social = TableRegistry::get('CakeDC/Users.SocialAccounts') + ->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); $this->UsersMailer->expects($this->once()) ->method('to') @@ -157,7 +160,7 @@ public function testSocialAccountValidation() ->with(['user' => $social->user, 'socialAccount' => $social]) ->will($this->returnValue($this->Email)); - $this->invokeMethod($this->UsersMailer, 'socialAccountValidation', array($social->user, $social)); + $this->invokeMethod($this->UsersMailer, 'socialAccountValidation', [$social->user, $social]); } /** @@ -195,7 +198,7 @@ public function testResetPassword() ->will($this->returnValue($this->Email)); - $this->invokeMethod($this->UsersMailer, 'resetPassword', array($user, 'myTemplate')); + $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user, 'myTemplate']); } /** @@ -207,7 +210,7 @@ public function testResetPassword() * * @return mixed Method return. */ - public function invokeMethod(&$object, $methodName, array $parameters = array()) + public function invokeMethod(&$object, $methodName, $parameters = []) { $reflection = new \ReflectionClass(get_class($object)); $method = $reflection->getMethod($methodName); From 0f6400e25b122ceb7a153c8da163b823f036cdc1 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 23 Oct 2015 11:42:43 -0500 Subject: [PATCH 0301/1476] Implement change from opauth to phpleague/oauth --- composer.json | 11 +- config/bootstrap.php | 7 ++ config/routes.php | 7 +- config/users.php | 36 +++--- src/Auth/Factory/OpauthFactory.php | 35 ------ src/Auth/Social/Mapper/AbstractMapper.php | 103 ++++++++++++++++++ src/Auth/Social/Mapper/Facebook.php | 31 ++++++ src/Auth/Social/Mapper/Instagram.php | 39 +++++++ src/Auth/Social/Mapper/LinkedIn.php | 15 +++ src/Auth/Social/Mapper/Twitter.php | 15 +++ src/Auth/Social/Util/SocialUtils.php | 25 +++++ src/Auth/SocialAuthenticate.php | 77 ++++++++----- .../Component/UsersAuthComponent.php | 24 +--- src/Controller/Traits/LoginTrait.php | 6 +- src/Controller/Traits/SocialTrait.php | 47 -------- src/Model/Behavior/SocialBehavior.php | 101 ++++++++--------- src/Model/Table/SocialAccountsTable.php | 2 + 17 files changed, 363 insertions(+), 218 deletions(-) delete mode 100644 src/Auth/Factory/OpauthFactory.php create mode 100644 src/Auth/Social/Mapper/AbstractMapper.php create mode 100644 src/Auth/Social/Mapper/Facebook.php create mode 100644 src/Auth/Social/Mapper/Instagram.php create mode 100644 src/Auth/Social/Mapper/LinkedIn.php create mode 100644 src/Auth/Social/Mapper/Twitter.php create mode 100644 src/Auth/Social/Util/SocialUtils.php diff --git a/composer.json b/composer.json index 2071eb2b1..a3bd60a99 100644 --- a/composer.json +++ b/composer.json @@ -7,15 +7,12 @@ "cakephp/cakephp": "3.1.*" }, "require-dev": { - "phpunit/phpunit": "*", - "opauth/opauth": "*", - "opauth/facebook": "*", - "opauth/twitter": "*" + "phpunit/phpunit": "*" }, "suggest": { - "opauth/opauth": "Used for Social Login, if you add Opauth, remember adding at least one strategy too", - "opauth/facebook": "Provide Social Login: Facebook Strategy, requires Opauth", - "opauth/twitter": "Provide Social Login: Twitter Strategy, requires Opauth", + "muffin/oauth2": "Provide Social Authentication", + "league/oauth2-facebook": "Provide Social Authentication with Facebook", + "league/oauth2-instagram": "Provide Social Authentication with Instagram", "google/recaptcha": "Provide reCAPTCHA validation for registration form" }, "autoload": { diff --git a/config/bootstrap.php b/config/bootstrap.php index 069ec6f16..19c9b5b6c 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -10,6 +10,9 @@ */ use Cake\Core\Configure; +use Cake\Core\Plugin; +use Cake\Event\EventManager; +use Cake\ORM\TableRegistry; Configure::load('CakeDC/Users.users'); collection((array)Configure::read('Users.config'))->each(function ($file) { @@ -19,3 +22,7 @@ if (Configure::check('Users.auth')) { Configure::write('Auth.authenticate.all.userModel', Configure::read('Users.table')); } + +if (Configure::read('Users.Social.login')) { + Plugin::load('Muffin/OAuth2'); +} diff --git a/config/routes.php b/config/routes.php index 712598f19..103c8a55d 100644 --- a/config/routes.php +++ b/config/routes.php @@ -16,12 +16,13 @@ $routes->fallbacks('DashedRoute'); }); -$oauthPath = Configure::read('Opauth.path'); +$oauthPath = Configure::read('OAuth.path'); if (is_array($oauthPath)) { Router::scope('/auth', function ($routes) use ($oauthPath) { $routes->connect( - '/*', - $oauthPath + '/:provider', + $oauthPath, + ['provider' => implode('|', array_keys(Configure::read('OAuth.providers')))] ); }); } diff --git a/config/users.php b/config/users.php index a9a602d45..c1ccbaa3b 100644 --- a/config/users.php +++ b/config/users.php @@ -99,24 +99,28 @@ 'CakeDC/Users.SimpleRbac', ], ], -//default Opauth configuration, you'll need to provide the strategy keys - 'Opauth' => [ - 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'opauthInit'], - 'callback_param' => 'callback', - 'complete_url' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], - 'Strategy' => [ - 'Facebook' => [ - 'scope' => ['public_profile', 'user_friends', 'email'], - //app_id => 'YOUR_APP_ID', - //app_secret = 'YOUR_APP_SECRET', + 'OAuth' => [ + 'path' => ['controller' => 'Users', 'action' => 'socialLogin'], + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5' + ], + 'mapFields' => [ + 'username' => 'login', + ], ], - 'Twitter' => [ - 'curl_cainfo' => false, - 'curl_capath' => false, - //'key' => 'YOUR_APP_KEY', - //'secret' => 'YOUR_APP_SECRET', + 'instagram' => [ + 'className' => 'League\OAuth2\Client\Provider\Instagram', + 'options' => [ + 'graphApiVersion' => 'v2.5' + ], + 'mapFields' => [ + 'username' => 'login', // maps the app's username to github's login + ], ] - ] + ], ] ]; diff --git a/src/Auth/Factory/OpauthFactory.php b/src/Auth/Factory/OpauthFactory.php deleted file mode 100644 index 15d61abcd..000000000 --- a/src/Auth/Factory/OpauthFactory.php +++ /dev/null @@ -1,35 +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 $rawData + * @param null $mapFields + */ + public function __construct($rawData, $mapFields = null) + { + $this->_rawData = $rawData; + if (!is_null($mapFields)) { + $this->_mapFields = $mapFields; + } + $this->_mapFields = array_merge($this->_defaultMapFields, $this->_mapFields); + } + /** + * Invoke method + */ + public function __invoke() + { + return $this->_map(); + } + + /** + * If email is present the user is validated + * @return bool + */ + protected function _validated() + { + return !empty($this->_rawData[$this->_mapFields['email']]); + } + + /** + * Maps raw data using mapFields + * + * @return mixed + */ + protected function _map() + { + $result = []; + collection($this->_mapFields)->each(function ($mappedField, $field) use (&$result) { + $value = Hash::get($this->_rawData, $mappedField); + $function = '_' . $field; + if (method_exists($this, $function)) { + $value = $this->{$function}(); + } + $result[$field] = $value; + }); + /** @var \League\OAuth2\Client\Token\AccessToken $token **/ + $token = Hash::get($this->_rawData, 'token'); + $result['credentials'] = [ + 'token' => $token->getToken(), + 'secret' => null, //todo check when twitter is available + 'expires' => $token->getExpires(), + ]; + $result['raw'] = $this->_rawData; + return $result; + } +} diff --git a/src/Auth/Social/Mapper/Facebook.php b/src/Auth/Social/Mapper/Facebook.php new file mode 100644 index 000000000..1dac33eab --- /dev/null +++ b/src/Auth/Social/Mapper/Facebook.php @@ -0,0 +1,31 @@ + 'name', + ]; + + /** + * Get avatar url + * @return string + */ + protected function _avatar() + { + return self::FB_GRAPH_BASE_URL . Hash::get($this->_rawData, 'id') . '/picture?type=normal'; + } +} diff --git a/src/Auth/Social/Mapper/Instagram.php b/src/Auth/Social/Mapper/Instagram.php new file mode 100644 index 000000000..0aaa90a82 --- /dev/null +++ b/src/Auth/Social/Mapper/Instagram.php @@ -0,0 +1,39 @@ + 'data.profile_picture', + 'id' => 'data.id', + 'full_name' => 'data.full_name', + 'username' => 'data.username' + ]; + + /** + * @return string + */ + protected function _link() + { + return self::INSTAGRAM_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); + } +} diff --git a/src/Auth/Social/Mapper/LinkedIn.php b/src/Auth/Social/Mapper/LinkedIn.php new file mode 100644 index 000000000..8d62ac3ca --- /dev/null +++ b/src/Auth/Social/Mapper/LinkedIn.php @@ -0,0 +1,15 @@ +getShortName(); + } +} \ No newline at end of file diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 46bc12e12..a7aca87fd 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -11,53 +11,40 @@ namespace CakeDC\Users\Auth; -use Cake\Auth\BaseAuthenticate; +use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; use Cake\Network\Request; -use Cake\Network\Response; use Cake\ORM\TableRegistry; -use Cake\Utility\Hash; +use CakeDC\Users\Auth\Social\Util\SocialUtils; +use Muffin\OAuth2\Auth\OAuthAuthenticate; /** * Class SocialAuthenticate */ -class SocialAuthenticate extends BaseAuthenticate +class SocialAuthenticate extends OAuthAuthenticate { /** - * Authenticate callback + * Constructor * - * @param Request $request Cake request object. - * @param Response $response Cake response object. - * @return bool|mixed + * @param \Cake\Controller\ComponentRegistry $registry The Component registry used on this request. + * @param array $config Array of config to use. + * @throws \Exception */ - public function authenticate(Request $request, Response $response) + public function __construct(ComponentRegistry $registry, array $config = []) { - $data = $request->session()->read(Configure::read('Users.Key.Session.social')); - - if (empty($data)) { - return false; - } - $socialMail = Hash::get((array)$data->info, Configure::read('Users.Key.Data.email')); - - if (!empty($socialMail)) { - $data->email = $socialMail; - $data->validated = true; - } else { - $data->email = $request->data(Configure::read('Users.Key.Data.email')); - $data->validated = false; - } - $user = $this->_findOrCreateUser($data); - return $user; + Configure::write('Muffin/OAuth2', Configure::read('OAuth')); + parent::__construct($registry, array_merge($config, Configure::read('OAuth'))); } /** - * Checks the social user against the database + * Finds or creates a local user. * - * @param array $data User data array. - * @return mixed + * @param array $data Mapped user data. + * @return array + * @throws \Muffin\OAuth2\Auth\Exception\MissingEventListenerException */ - protected function _findOrCreateUser($data) + protected function _touch(array $data) { $userModel = Configure::read('Users.table'); $User = TableRegistry::get($userModel); @@ -66,10 +53,40 @@ protected function _findOrCreateUser($data) 'validate_email' => Configure::read('Users.Email.validate'), 'token_expiration' => Configure::read('Users.Token.expiration') ]; - $user = $User->socialLogin($data, $options); + $user = $User->socialLogin($data, $options, $this->_provider); if (!empty($user->username)) { $user = $this->_findUser($user->username); } return $user; } + + /** + * Get a user based on information in the request. + * + * @param \Cake\Network\Request $request Request object. + * @return mixed Either false or an array of user information + * @throws \RuntimeException If the `Muffin/OAuth2.newUser` event is missing or returns empty. + */ + public function getUser(Request $request) + { + if (!$rawData = $this->_authenticate($request)) { + return false; + } + $provider = SocialUtils::getProvider($this->_provider); + $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; + $providerMapper = new $providerMapperClass($rawData); + $user = $providerMapper(); + + if (!$user || !$this->config('userModel')) { + return false; + } + + if (!$result = $this->_touch($user)) { + return false; + } + + $args = [$this->_provider, $result]; + $this->dispatchEvent('Muffin/OAuth2.afterIdentify', $args); + return $result; + } } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index c75ed3d51..b9b32a314 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -43,9 +43,6 @@ public function initialize(array $config) $this->_validateConfig(); $this->_initAuth(); - if (Configure::read('Users.Social.login') && Configure::read('Opauth')) { - $this->_configOpauthRoutes(); - } if (Configure::read('Users.Social.login')) { $this->_loadSocialLogin(); } @@ -106,10 +103,11 @@ protected function _initAuth() 'resendTokenValidation', 'login', 'socialEmail', - 'opauthInit', 'resetPassword', 'requestResetPassword', 'changePassword', + 'endpoint', + 'authenticated' ]); } @@ -158,22 +156,4 @@ protected function _validateConfig() throw new BadConfigurationException($message); } } - - /** - * Config Opauth urls - * - * @return void - */ - protected function _configOpauthRoutes() - { - $path = Configure::read('Opauth.path'); - Configure::write('Opauth.path', Router::url($path) . '/'); - //Generate callback url - if (is_array($path)) { - $path[] = Configure::read('Opauth.callback_param'); - } else { - $path = $path . Configure::read('Opauth.callback_param'); - } - Configure::write('Opauth.callback_url', Router::url($path)); - } } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index afde464af..fd1200574 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -25,6 +25,10 @@ trait LoginTrait { use CustomUsersTableTrait; + public function socialLogin() + { + + } /** * Login user * @@ -49,8 +53,6 @@ public function login() $user = $this->Auth->identify(); return $this->_afterIdentifyUser($user, $socialLogin); } catch (AccountNotActiveException $ex) { - $socialKey = Configure::read('Users.Key.Session.social'); - $this->request->session()->delete($socialKey); $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); $this->Flash->success($msg); } catch (MissingEmailException $ex) { diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index ba788c7d8..ecb5bba72 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -11,10 +11,8 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Auth\Factory\OpauthFactory; use Cake\Core\Configure; use Cake\Network\Exception\NotFoundException; -use Cake\Routing\Router; /** * Covers registration features and email token validation @@ -22,41 +20,6 @@ */ trait SocialTrait { - - /** - * Start Opauth authentication - * - * @param bool|false $callback callback - * @return void - */ - public function opauthInit($callback = null) - { - $this->autoRender = false; - $Opauth = $this->_getOpauthInstance(); - $response = $Opauth->run(); - if (empty($callback)) { - return; - } - $url = $this->_generateOpauthCompleteUrl(); - $this->request->session()->write(Configure::read('Users.Key.Session.social'), $response); - return $this->redirect($url); - } - - /** - * Generates the opauth callback url - * - * @return string Full translated URL with base path. - */ - protected function _generateOpauthCompleteUrl() - { - $url = Configure::read('Opauth.complete_url'); - if (!is_array($url)) { - $url = Router::parse($url); - } - $url['?'] = ['social' => $this->request->query('code')]; - return Router::url($url, true); - } - /** * Render the social email form * @@ -69,14 +32,4 @@ public function socialEmail() throw new NotFoundException(); } } - - /** - * Gets OpauthFactory instance - * - * @return OpauthFactory - */ - protected function _getOpauthInstance() - { - return OpauthFactory::create(Configure::read('Opauth')); - } } diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 0da027e8c..7e0d6d82b 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -11,6 +11,9 @@ namespace CakeDC\Users\Model\Behavior; +use Cake\Event\Event; +use Cake\Event\EventDispatcherTrait; +use CakeDC\Users\Auth\Social\Util\SocialUtils; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Model\Behavior\Behavior; @@ -20,6 +23,9 @@ use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; +use League\OAuth2\Client\Provider\AbstractProvider; +use League\OAuth2\Client\Provider\Facebook; +use ReflectionClass; /** * Covers social features @@ -28,28 +34,28 @@ class SocialBehavior extends Behavior { use RandomStringTrait; - - /** - * Used to create a default profile link if not available in raw data returned by FB - */ - const FACEBOOK_SCOPED_ID_URL = "https://www.facebook.com/app_scoped_user_id/"; + use EventDispatcherTrait; /** * Performs social login * * @param array $data Array social login. * @param array $options Array option data. + * @param AbstractProvider $provider Provider * @return bool|EntityInterface|mixed */ - public function socialLogin($data, $options = []) + public function socialLogin(array $data, array $options, AbstractProvider $provider) { - $provider = $data->provider; - $reference = $data->uid; + $data['provider'] = SocialUtils::getProvider($provider); + $reference = Hash::get($data, 'id'); $existingAccount = $this->_table->SocialAccounts->find() - ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $provider]) + ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $data['provider']]) ->contain(['Users']) ->first(); if (empty($existingAccount->user)) { + $event = 'Muffin/OAuth2.newUser'; + $args = [$provider, $data]; + $this->dispatchEvent($event, $args); $user = $this->_createSocialUser($data, $options); if (!empty($user->social_accounts[0])) { $existingAccount = $user->social_accounts[0]; @@ -86,11 +92,12 @@ protected function _createSocialUser($data, $options = []) $validateEmail = Hash::get($options, 'validate_email'); $tokenExpiration = Hash::get($options, 'token_expiration'); $existingUser = null; - if ($useEmail && empty($data->email)) { + $email = Hash::get($data, 'email'); + if ($useEmail && empty($email)) { throw new MissingEmailException(__d('Users', 'Email not present')); } else { $existingUser = $this->_table->find() - ->where([$this->_table->alias() . '.email' => $data->email]) + ->where([$this->_table->alias() . '.email' => $email]) ->first(); } $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); @@ -112,42 +119,38 @@ protected function _createSocialUser($data, $options = []) */ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) { - $accountData['provider'] = $data->provider; - $accountData['username'] = Hash::get((array)$data->info, 'nickname'); - $accountData['reference'] = $data->uid; - $accountData['avatar'] = Hash::get((array)$data->info, 'image'); - /* @todo make a pull request to Opauth Facebook Strategy because it does not include link on info array */ - if ($data->provider == SocialAccountsTable::PROVIDER_TWITTER) { - $accountData['link'] = Hash::get((array)$data->info, 'urls.twitter'); - } elseif ($data->provider == SocialAccountsTable::PROVIDER_FACEBOOK) { - $accountData['link'] = $this->_getFacebookLink($data->raw); - } + $accountData['provider'] = Hash::get($data, 'provider'); + $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('square', 'large', $accountData['avatar']); - $accountData['description'] = Hash::get((array)$data->info, 'description'); - $accountData['token'] = Hash::get((array)$data->credentials, 'token'); - $accountData['token_secret'] = Hash::get((array)$data->credentials, 'secret'); - $expires = Hash::get((array)$data->credentials, 'expires'); + $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'); $accountData['token_expires'] = !empty($expires) ? (new DateTime($expires))->format('Y-m-d H:i:s') : null; - $accountData['data'] = serialize($data->raw); + $accountData['data'] = serialize(Hash::get($data, 'raw')); $accountData['active'] = true; if (empty($existingUser)) { - $firstName = Hash::get((array)$data->info, 'first_name'); - $lastName = Hash::get((array)$data->info, 'last_name'); + $firstName = Hash::get($data, 'first_name'); + $lastName = Hash::get($data, 'last_name'); if (!empty($firstName) && !empty($lastName)) { $userData['first_name'] = $firstName; $userData['last_name'] = $lastName; } else { - $name = explode(' ', $data->name); + $name = explode(' ', Hash::get($data, 'full_name')); $userData['first_name'] = Hash::get($name, 0); array_shift($name); $userData['last_name'] = implode(' ', $name); } - $userData['username'] = Hash::get((array)$data->info, 'nickname'); + $userData['username'] = Hash::get($data, 'username'); $username = Hash::get($userData, 'username'); if (empty($username)) { - if (!empty($data->email)) { - $email = explode('@', $data->email); + if (!empty(Hash::get($data, 'email'))) { + $email = explode('@', Hash::get($data, 'email')); $userData['username'] = Hash::get($email, 0); } else { $firstName = Hash::get($userData, 'first_name'); @@ -157,23 +160,26 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail } } $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); + if ($useEmail) { - $userData['email'] = $data->email; - if (!$data->validated) { + $userData['email'] = Hash::get($data, 'email'); + if (empty(Hash::get($data, 'validated'))) { $accountData['active'] = false; } } $userData['password'] = $this->randomString(); - $userData['avatar'] = Hash::get((array)$data->info, 'image'); - $userData['validated'] = $data->validated; + $userData['avatar'] = Hash::get($data, 'avatar'); + $userData['validated'] = !empty(Hash::get($data, 'validated')); $userData['tos_date'] = date("Y-m-d H:i:s"); - $userData['gender'] = Hash::get($data->raw, 'gender'); - $userData['timezone'] = Hash::get($data->raw, 'timezone'); + $userData['gender'] = Hash::get($data, 'gender'); + //$userData['timezone'] = Hash::get($data, 'timezone'); $userData['social_accounts'][] = $accountData; + debug($userData); + die(); $user = $this->_table->newEntity($userData, ['associated' => ['SocialAccounts']]); $user = $this->_updateActive($user, false, $tokenExpiration); } else { - if ($useEmail && !$data->validated) { + if ($useEmail && empty(Hash::get($data, 'validated'))) { $accountData['active'] = false; } $user = $this->_table->patchEntity($existingUser, [ @@ -183,23 +189,6 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail return $user; } - /** - * Create a link for facebook profile - * - * @param array $raw raw data array returned by Facebook - * @return string url to facebook profile - */ - protected function _getFacebookLink($raw = []) - { - $link = Hash::get((array)$raw, 'link'); - if (!empty($link)) { - return $link; - } - - $id = Hash::get((array)$raw, 'id'); - return self::FACEBOOK_SCOPED_ID_URL . $id; - } - /** * Checks if username exists and generate a new one * diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 4b139e415..dc06716d2 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -35,6 +35,8 @@ class SocialAccountsTable extends Table */ const PROVIDER_TWITTER = 'Twitter'; const PROVIDER_FACEBOOK = 'Facebook'; + const PROVIDER_INSTAGRAM = 'Instagram'; + const PROVIDER_LINKEDIN = 'LinkedIn'; /** * Initialize method From e54d3d26638426cde20b8f7c926002cd0d3d711b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Sun, 25 Oct 2015 09:11:04 -0500 Subject: [PATCH 0302/1476] Continue switching oauth provider --- config/users.php | 16 +++++---------- src/Model/Behavior/SocialBehavior.php | 11 ++++++---- src/Model/Table/UsersTable.php | 2 +- src/Template/Users/login.ctp | 20 +++++++++++------- src/View/Helper/UserHelper.php | 29 +++++++++------------------ 5 files changed, 35 insertions(+), 43 deletions(-) diff --git a/config/users.php b/config/users.php index c1ccbaa3b..d96cd1bfa 100644 --- a/config/users.php +++ b/config/users.php @@ -100,25 +100,19 @@ ], ], 'OAuth' => [ - 'path' => ['controller' => 'Users', 'action' => 'socialLogin'], + 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin'], 'providers' => [ 'facebook' => [ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5' - ], - 'mapFields' => [ - 'username' => 'login', - ], + ] ], - 'instagram' => [ - 'className' => 'League\OAuth2\Client\Provider\Instagram', + 'linkedIn' => [ + 'className' => 'League\OAuth2\Client\Provider\LinkedIn', 'options' => [ 'graphApiVersion' => 'v2.5' - ], - 'mapFields' => [ - 'username' => 'login', // maps the app's username to github's login - ], + ] ] ], ] diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 7e0d6d82b..91d6e4b30 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -125,12 +125,17 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $accountData['avatar'] = Hash::get($data, 'avatar'); $accountData['link'] = Hash::get($data, 'link'); - $accountData['avatar'] = str_replace('square', 'large', $accountData['avatar']); + $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'); - $accountData['token_expires'] = !empty($expires) ? (new DateTime($expires))->format('Y-m-d H:i:s') : null; + if (!empty($expires)) { + $expiresTime = new DateTime(); + $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); + } else { + $accountData['token_expires'] = null; + } $accountData['data'] = serialize(Hash::get($data, 'raw')); $accountData['active'] = true; @@ -174,8 +179,6 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['gender'] = Hash::get($data, 'gender'); //$userData['timezone'] = Hash::get($data, 'timezone'); $userData['social_accounts'][] = $accountData; - debug($userData); - die(); $user = $this->_table->newEntity($userData, ['associated' => ['SocialAccounts']]); $user = $this->_updateActive($user, false, $tokenExpiration); } else { diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index ca088f1e2..6ffbb2e47 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -44,7 +44,7 @@ public function initialize(array $config) parent::initialize($config); $this->table('users'); - $this->displayField('id'); + $this->displayField('username'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); $this->addBehavior('CakeDC/Users.Register'); diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 927287985..3ea2712fc 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -30,20 +30,26 @@ use Cake\Core\Configure; ?>

Html->link(__d('users', 'Register'), ['action' => 'register']); } - if (Configure::check('Users.Email.required')) { - echo ' | '; + if (Configure::read('Users.Email.required')) { + if ($registrationActive) { + echo ' | '; + } echo $this->Html->link(__d('users', 'Reset Password'), ['action' => 'requestResetPassword']); } ?>

- - User->facebookLogin(); ?> - User->twitterLogin(); ?> + + + $options) : ?> + + User->socialLogin($provider); ?> + + Form->button(__d('Users', 'Login')); ?> diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index f1abb3417..1c5a18608 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\View\Helper; +use Cake\Utility\Inflector; use CakeDC\Users\Controller\Component\UsersAuthComponent; use Cake\Core\Configure; use Cake\Event\Event; @@ -46,31 +47,19 @@ public function beforeLayout(Event $event) } /** - * Facebook login link + * Social login link * + * @param string $name + * @param array $options * @return string */ - public function facebookLogin() + public function socialLogin($name, $options) { return $this->Html->link($this->Html->tag('i', '', [ - 'class' => 'fa fa-facebook' - ]) . __d('Users', 'Sign in with Facebook'), '/auth/facebook', [ - 'escape' => false, 'class' => 'btn btn-social btn-facebook' - ]); - } - - /** - * Twitter login link - * - * @return string - */ - public function twitterLogin() - { - return $this->Html->link($this->Html->tag('i', '', [ - 'class' => 'fa fa-twitter' - ]) . __d('Users', 'Sign in with Twitter'), '/auth/twitter', [ - 'escape' => false, 'class' => 'btn btn-social btn-twitter' - ]); + 'class' => __d('Users', 'fa fa-{0}', strtolower($name)), + ]) . __d('Users', 'Sign in with {0}', Inflector::camelize($name)), "/auth/$name", [ + 'escape' => false, 'class' => __d('Users', 'btn btn-social btn-{0} ' . $options['class'] ? :'', strtolower($name)) + ]); } /** From ebe01147523626958788520c695a62fc4bdd62dd Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 30 Oct 2015 20:44:27 -0500 Subject: [PATCH 0303/1476] Implement instagram/linkedin. Fix authenticate --- config/bootstrap.php | 1 + config/users.php | 6 +- src/Auth/Social/Mapper/LinkedIn.php | 13 +++- src/Auth/SocialAuthenticate.php | 51 +++++++++--- .../Component/RememberMeComponent.php | 2 +- .../Component/UsersAuthComponent.php | 1 + src/Controller/Traits/LoginTrait.php | 77 +++++++++++-------- src/Controller/Traits/SocialTrait.php | 10 +++ src/Controller/UsersController.php | 1 + src/Model/Behavior/SocialBehavior.php | 25 +++--- src/Model/Table/UsersTable.php | 6 ++ src/Template/Users/social_email.ctp | 4 +- 12 files changed, 133 insertions(+), 64 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 19c9b5b6c..9efc06c3e 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -25,4 +25,5 @@ if (Configure::read('Users.Social.login')) { Plugin::load('Muffin/OAuth2'); + EventManager::instance()->on(\CakeDC\Users\Controller\Component\UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, [new \CakeDC\Users\Controller\UsersController(), 'failedSocialLogin']); } diff --git a/config/users.php b/config/users.php index d96cd1bfa..57787a866 100644 --- a/config/users.php +++ b/config/users.php @@ -110,9 +110,9 @@ ], 'linkedIn' => [ 'className' => 'League\OAuth2\Client\Provider\LinkedIn', - 'options' => [ - 'graphApiVersion' => 'v2.5' - ] + ], + 'instagram' => [ + 'className' => 'League\OAuth2\Client\Provider\Instagram', ] ], ] diff --git a/src/Auth/Social/Mapper/LinkedIn.php b/src/Auth/Social/Mapper/LinkedIn.php index 8d62ac3ca..934f2b1b7 100644 --- a/src/Auth/Social/Mapper/LinkedIn.php +++ b/src/Auth/Social/Mapper/LinkedIn.php @@ -11,5 +11,16 @@ class LinkedIn extends AbstractMapper { - + /** + * Map for provider fields + * @var + */ + protected $_mapFields = [ + 'avatar' => 'pictureUrl', + 'first_name' => 'firstName', + 'last_name' => 'lastName', + 'email' => 'emailAddress', + 'bio' => 'headline', + 'link' => 'publicProfileUrl' + ]; } \ No newline at end of file diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index a7aca87fd..ca07a75cc 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -13,9 +13,15 @@ use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; +use Cake\Error\Debugger; +use Cake\Log\Log; use Cake\Network\Request; use Cake\ORM\TableRegistry; use CakeDC\Users\Auth\Social\Util\SocialUtils; +use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Exception\UserNotActiveException; use Muffin\OAuth2\Auth\OAuthAuthenticate; /** @@ -53,7 +59,25 @@ protected function _touch(array $data) 'validate_email' => Configure::read('Users.Email.validate'), 'token_expiration' => Configure::read('Users.Token.expiration') ]; - $user = $User->socialLogin($data, $options, $this->_provider); + try { + if (empty($data['provider']) && !empty($this->_provider)) { + $data['provider'] = SocialUtils::getProvider($this->_provider); + } + $user = $User->socialLogin($data, $options); + } catch (UserNotActiveException $ex) { + $exception = $ex; + } catch (AccountNotActiveException $ex) { + $exception = $ex; + } catch (MissingEmailException $ex) { + $exception = $ex; + } + if (!empty($exception)) { + $event = UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN; + $args = ['exception' => $exception, 'rawData' => $data]; + $event = $this->dispatchEvent($event, $args); + return $event->result; + } + if (!empty($user->username)) { $user = $this->_findUser($user->username); } @@ -69,14 +93,23 @@ protected function _touch(array $data) */ public function getUser(Request $request) { - if (!$rawData = $this->_authenticate($request)) { - return false; - } - $provider = SocialUtils::getProvider($this->_provider); - $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; - $providerMapper = new $providerMapperClass($rawData); - $user = $providerMapper(); + $data = $request->session()->read(Configure::read('Users.Key.Session.social')); + if (!empty($data) && (!empty($data['email'] || !empty($request->data('email'))))) { + if (!empty($request->data('email'))) { + $data['email'] = $request->data('email'); + } + $user = $data; + $request->session()->delete(Configure::read('Users.Key.Session.social')); + } else { + if (!$rawData = $this->_authenticate($request)) { + return false; + } + $provider = SocialUtils::getProvider($this->_provider); + $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; + $providerMapper = new $providerMapperClass($rawData); + $user = $providerMapper(); + } if (!$user || !$this->config('userModel')) { return false; } @@ -85,8 +118,6 @@ public function getUser(Request $request) return false; } - $args = [$this->_provider, $result]; - $this->dispatchEvent('Muffin/OAuth2.afterIdentify', $args); return $result; } } diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 4f318abe1..1293b1ede 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -133,7 +133,7 @@ public function destroy(Event $event) public function beforeFilter(Event $event) { $user = $this->Auth->user(); - if (!empty($user) || $this->request->is(['post', 'put']) || $this->request->action === 'logout' || $this->request->session()->check(Configure::read('Users.Key.Session.social'))) { + if (!empty($user) || $this->request->is(['post', 'put']) || $this->request->action === 'logout' || $this->request->session()->check(Configure::read('Users.Key.Session.social')) || $this->request->param('provider')) { return; } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index b9b32a314..f46092a67 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -24,6 +24,7 @@ class UsersAuthComponent extends Component const EVENT_IS_AUTHORIZED = 'Users.Component.UsersAuth.isAuthorized'; const EVENT_BEFORE_LOGIN = 'Users.Component.UsersAuth.beforeLogin'; const EVENT_AFTER_LOGIN = 'Users.Component.UsersAuth.afterLogin'; + const EVENT_FAILED_SOCIAL_LOGIN = 'Users.Component.UsersAuth.failedSocialLogin'; const EVENT_AFTER_COOKIE_LOGIN = 'Users.Component.UsersAuth.afterCookieLogin'; const EVENT_BEFORE_REGISTER = 'Users.Component.UsersAuth.beforeRegister'; const EVENT_AFTER_REGISTER = 'Users.Component.UsersAuth.afterRegister'; diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index fd1200574..380509fc7 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,11 +11,14 @@ namespace CakeDC\Users\Controller\Traits; +use Cake\Event\Event; +use Cake\Network\Exception\NotFoundException; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use Cake\Core\Configure; use Cake\Utility\Hash; +use CakeDC\Users\Exception\UserNotActiveException; /** * Covers the login, logout and social login @@ -25,8 +28,37 @@ trait LoginTrait { use CustomUsersTableTrait; + /** + * @param $event + */ + public function failedSocialLogin($event) { + if ($event->data['exception'] instanceof MissingEmailException) { + $this->Flash->success(__d('Users', 'Please enter your email')); + $this->request->session()->write(Configure::read('Users.Key.Session.social'), $event->data['rawData']); + return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); + } + if ($event->data['exception'] instanceof UserNotActiveException) { + $msg = __d('Users', 'Your user has not been validated yet. Please check your inbox for instructions'); + } elseif ($event->data['exception'] instanceof AccountNotActiveException) { + $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); + } + $this->Flash->success($msg); + return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + } + + /** + * @return array + */ public function socialLogin() { + $socialProvider = $this->request->param('provider'); + $socialUser = $this->request->session()->read(Configure::read('Users.Key.Session.social')); + + if (empty($socialProvider) && empty($socialUser)) { + throw new NotFoundException(); + } + $user = $this->Auth->user(); + return $this->_afterIdentifyUser($user, true); } /** @@ -43,21 +75,14 @@ public function login() if ($event->isStopped()) { return $this->redirect($event->result); } - $socialLogin = $this->_isSocialLogin(); - if (!$this->request->is('post') && !$socialLogin) { - return; + $socialLogin = $this->request->session()->check(Configure::read('Users.Key.Session.social')); + if (!empty($socialLogin)) { + $this->redirect(['action' => 'social-email']); } - - try { + if ($this->request->is('post')) { $user = $this->Auth->identify(); - return $this->_afterIdentifyUser($user, $socialLogin); - } catch (AccountNotActiveException $ex) { - $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); - $this->Flash->success($msg); - } catch (MissingEmailException $ex) { - $this->Flash->success(__d('Users', 'Please enter your email')); - return $this->redirect(['controller' => 'Users', 'action' => 'socialEmail']); + return $this->_afterIdentifyUser($user, false); } } @@ -69,36 +94,22 @@ public function login() */ protected function _afterIdentifyUser($user, $socialLogin = false) { - $socialKey = Configure::read('Users.Key.Session.social'); if (!empty($user)) { - $this->request->session()->delete($socialKey); $this->Auth->setUser($user); - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN); + + $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); } else { - $message = __d('Users', 'Username or password is incorrect'); - if ($socialLogin) { - $socialData = $this->request->session()->read($socialKey); - $socialDataEmail = null; - if (!empty($socialData->info)) { - $socialDataEmail = Hash::get((array)$socialData->info, Configure::read('data_email_key')); - } - $postedEmail = $this->request->data(Configure::read('Users.Key.Data.email')); - if (Configure::read('Users.Email.required') && - empty($socialDataEmail) && - empty($postedEmail)) { - return $this->redirect([ - 'controller' => 'Users', - 'action' => 'socialEmail' - ]); - } - $message = __d('Users', 'There was an error associating your social network account'); + if (!$socialLogin) { + $message = __d('Users', 'Username or password is incorrect'); + $this->Flash->error($message, 'default', [], 'auth'); } - $this->Flash->error($message, 'default', [], 'auth'); + + $this->redirect($this->Auth->redirectUrl()); } } diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index ecb5bba72..bb03f187b 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -31,5 +31,15 @@ public function socialEmail() if (!$this->request->session()->check(Configure::read('Users.Key.Session.social'))) { throw new NotFoundException(); } + + if ($this->request->is('post')) { + $validPost = $this->_validateRegisterPost(); + if (!$validPost) { + $this->Flash->error(__d('Users', 'The reCaptcha could not be validated')); + return; + } + $user = $this->Auth->identify(); + return $this->_afterIdentifyUser($user, true); + } } } diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index a0337b31a..45cd15827 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Controller; use CakeDC\Users\Controller\AppController; +use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Controller\Traits\ProfileTrait; use CakeDC\Users\Controller\Traits\RegisterTrait; diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 91d6e4b30..528069415 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -11,21 +11,15 @@ namespace CakeDC\Users\Model\Behavior; -use Cake\Event\Event; use Cake\Event\EventDispatcherTrait; -use CakeDC\Users\Auth\Social\Util\SocialUtils; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Model\Behavior\Behavior; -use CakeDC\Users\Model\Table\SocialAccountsTable; +use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Traits\RandomStringTrait; use Cake\Datasource\EntityInterface; use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; -use League\OAuth2\Client\Provider\AbstractProvider; -use League\OAuth2\Client\Provider\Facebook; -use ReflectionClass; /** * Covers social features @@ -41,21 +35,16 @@ class SocialBehavior extends Behavior * * @param array $data Array social login. * @param array $options Array option data. - * @param AbstractProvider $provider Provider * @return bool|EntityInterface|mixed */ - public function socialLogin(array $data, array $options, AbstractProvider $provider) + public function socialLogin(array $data, array $options) { - $data['provider'] = SocialUtils::getProvider($provider); $reference = Hash::get($data, 'id'); $existingAccount = $this->_table->SocialAccounts->find() ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $data['provider']]) ->contain(['Users']) ->first(); if (empty($existingAccount->user)) { - $event = 'Muffin/OAuth2.newUser'; - $args = [$provider, $data]; - $this->dispatchEvent($event, $args); $user = $this->_createSocialUser($data, $options); if (!empty($user->social_accounts[0])) { $existingAccount = $user->social_accounts[0]; @@ -68,7 +57,15 @@ public function socialLogin(array $data, array $options, AbstractProvider $provi } if (!empty($existingAccount)) { if ($existingAccount->active) { - return $user; + if ($user->active) { + return $user; + } else { + throw new UserNotActiveException([ + $existingAccount->provider, + $existingAccount->$user + ]); + } + } else { throw new AccountNotActiveException([ $existingAccount->provider, diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 6ffbb2e47..984628e5d 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -26,6 +26,12 @@ class UsersTable extends Table { + /** + * Role Constants + */ + const ROLE_USER = 'user'; + const ROLE_ADMIN = 'admin'; + /** * Flag to set email check in buildRules or not * diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp index c2e29be82..52cc6086e 100644 --- a/src/Template/Users/social_email.ctp +++ b/src/Template/Users/social_email.ctp @@ -10,8 +10,8 @@ */ ?>
- Flash->render('auth') ?> - Form->create('User', ['action' => 'login']) ?> + Flash->render() ?> + Form->create('User') ?>
Form->input('email') ?> From 4cbf2d1a22d2aa4b3017a8e86b9611acd512d914 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 30 Oct 2015 20:49:32 -0500 Subject: [PATCH 0304/1476] Add google login to config. Add new exception --- config/users.php | 3 +++ src/Exception/UserNotActiveException.php | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/Exception/UserNotActiveException.php diff --git a/config/users.php b/config/users.php index 57787a866..0ece1bf6d 100644 --- a/config/users.php +++ b/config/users.php @@ -113,6 +113,9 @@ ], 'instagram' => [ 'className' => 'League\OAuth2\Client\Provider\Instagram', + ], + 'google' => [ + 'className' => 'League\OAuth2\Client\Provider\Google', ] ], ] diff --git a/src/Exception/UserNotActiveException.php b/src/Exception/UserNotActiveException.php new file mode 100644 index 000000000..55b1a8fee --- /dev/null +++ b/src/Exception/UserNotActiveException.php @@ -0,0 +1,18 @@ + Date: Fri, 30 Oct 2015 22:38:16 -0500 Subject: [PATCH 0305/1476] Add Google, etc --- config/users.php | 3 +++ src/Auth/Social/Mapper/Google.php | 26 ++++++++++++++++++++++++++ src/Auth/Social/Mapper/Instagram.php | 1 - src/Auth/Social/Mapper/LinkedIn.php | 1 - src/Auth/SocialAuthenticate.php | 1 + 5 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/Auth/Social/Mapper/Google.php diff --git a/config/users.php b/config/users.php index 0ece1bf6d..1ce14c39d 100644 --- a/config/users.php +++ b/config/users.php @@ -116,6 +116,9 @@ ], 'google' => [ 'className' => 'League\OAuth2\Client\Provider\Google', + 'options' => [ + 'userFields' => ['url', 'aboutMe'], + ] ] ], ] diff --git a/src/Auth/Social/Mapper/Google.php b/src/Auth/Social/Mapper/Google.php new file mode 100644 index 000000000..5c9644ffe --- /dev/null +++ b/src/Auth/Social/Mapper/Google.php @@ -0,0 +1,26 @@ + 'image.url', + 'full_name' => 'displayName', + 'email' => 'emails.0.value', + 'first_name' => 'name.givenName', + 'last_name' => 'name.familyName', + 'bio' => 'aboutMe', + 'link' => 'url' + ]; +} diff --git a/src/Auth/Social/Mapper/Instagram.php b/src/Auth/Social/Mapper/Instagram.php index 0aaa90a82..c483c551e 100644 --- a/src/Auth/Social/Mapper/Instagram.php +++ b/src/Auth/Social/Mapper/Instagram.php @@ -8,7 +8,6 @@ namespace CakeDC\Users\Auth\Social\Mapper; - use Cake\Utility\Hash; class Instagram extends AbstractMapper diff --git a/src/Auth/Social/Mapper/LinkedIn.php b/src/Auth/Social/Mapper/LinkedIn.php index 934f2b1b7..faaf79e0a 100644 --- a/src/Auth/Social/Mapper/LinkedIn.php +++ b/src/Auth/Social/Mapper/LinkedIn.php @@ -8,7 +8,6 @@ namespace CakeDC\Users\Auth\Social\Mapper; - class LinkedIn extends AbstractMapper { /** diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index ca07a75cc..0bc472f5f 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -108,6 +108,7 @@ public function getUser(Request $request) $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; $providerMapper = new $providerMapperClass($rawData); $user = $providerMapper(); + $user['provider'] = $provider; } if (!$user || !$this->config('userModel')) { From af23eaca96356fd8ec80114c7c5b4bff765784b4 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 5 Nov 2015 16:19:31 -0430 Subject: [PATCH 0306/1476] Adding isAuthorized method in UserHelper --- src/View/Helper/UserHelper.php | 13 ++++++++++ tests/TestCase/View/Helper/UserHelperTest.php | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index f1abb3417..0cb5dc7af 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -108,6 +108,19 @@ public function link($title, $url = null, array $options = []) return false; } + /** + * Retunrs true if the target url is authorized for the logged in user + * + * @param type $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 = $this->_View->eventManager()->dispatch($event); + return $result->result; + } + /** * Welcome display * @return mixed diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 651d70ca0..bbdad73a3 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -147,6 +147,32 @@ public function testLinkAuthorized() $this->assertSame('before_title_after', $link); } + + /** + * Test isAuthorized + * + * @return void + */ + public function testIsAuthorizedHH() + { + $view = new View(); + $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') + ->setMethods(['dispatch']) + ->getMock(); + $view->eventManager($eventManagerMock); + $this->User = new UserHelper($view); + $result = new Event('dispatch-result'); + $result->result = true; + $eventManagerMock->expects($this->once()) + ->method('dispatch') + ->will($this->returnValue($result)); + + $link = $this->User->isAuthorized(['controller' => 'MyController', 'action' => 'myAction']); + $this->assertTrue($link); + } + + + /** * Test link * From 90ec40b5fa49e4d42dc6d027854c0e1c3d70511f Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 6 Nov 2015 06:55:44 -0500 Subject: [PATCH 0307/1476] Fix issues with validation --- src/Controller/Traits/LoginTrait.php | 2 +- src/Controller/Traits/UserValidationTrait.php | 2 +- src/Model/Behavior/RegisterBehavior.php | 1 - src/View/Helper/UserHelper.php | 5 ++++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 380509fc7..4e4492876 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -109,7 +109,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false) $this->Flash->error($message, 'default', [], 'auth'); } - $this->redirect($this->Auth->redirectUrl()); + $this->redirect(Configure::read('Auth.loginAction')); } } diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 8846c72a6..5a24003e8 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -62,7 +62,7 @@ public function validate($type = null, $token = null) $this->Flash->error(__d('Users', 'Invalid validation type')); } } catch (UserNotFoundException $ex) { - $this->Flash->error(__d('Users', 'Invalid token and/or email')); + $this->Flash->error(__d('Users', 'Invalid token or user account already validated')); } catch (TokenExpiredException $ex) { $this->Flash->error(__d('Users', 'Token already expired')); } diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index ab95edc72..87b4a77f1 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -108,7 +108,6 @@ public function activateUser(EntityInterface $user) if ($user->active) { throw new UserAlreadyActiveException(__d('Users', "User account already validated")); } - $user = $this->_removeValidationToken($user); $user->activation_date = new DateTime(); $user->active = true; $result = $this->_table->save($user); diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 1c5a18608..42e454cd5 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -55,9 +55,12 @@ public function beforeLayout(Event $event) */ public function socialLogin($name, $options) { + if (empty($options['label'])) { + $options['label'] = 'Sign in with'; + } return $this->Html->link($this->Html->tag('i', '', [ 'class' => __d('Users', 'fa fa-{0}', strtolower($name)), - ]) . __d('Users', 'Sign in with {0}', Inflector::camelize($name)), "/auth/$name", [ + ]) . __d('Users', '{0} {1}', $options['label'], Inflector::camelize($name)), "/auth/$name", [ 'escape' => false, 'class' => __d('Users', 'btn btn-social btn-{0} ' . $options['class'] ? :'', strtolower($name)) ]); } From 9fa059bf036ffc6edea7a110d49d6f2d67037233 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 6 Nov 2015 13:16:17 -0430 Subject: [PATCH 0308/1476] WIP Fixing unit tests --- src/Controller/Traits/LoginTrait.php | 30 ++- src/View/Helper/UserHelper.php | 6 +- .../Controller/Traits/LoginTraitTest.php | 236 ++++++++++-------- .../Controller/Traits/SocialTraitTest.php | 46 ---- .../Traits/UserValidationTraitTest.php | 2 +- tests/TestCase/Model/Table/UsersTableTest.php | 121 +++++---- tests/TestCase/View/Helper/UserHelperTest.php | 24 -- 7 files changed, 207 insertions(+), 258 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 4e4492876..7c31ffb26 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -32,15 +32,18 @@ trait LoginTrait * @param $event */ public function failedSocialLogin($event) { - if ($event->data['exception'] instanceof MissingEmailException) { - $this->Flash->success(__d('Users', 'Please enter your email')); - $this->request->session()->write(Configure::read('Users.Key.Session.social'), $event->data['rawData']); - return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); - } - if ($event->data['exception'] instanceof UserNotActiveException) { - $msg = __d('Users', 'Your user has not been validated yet. Please check your inbox for instructions'); - } elseif ($event->data['exception'] instanceof AccountNotActiveException) { - $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); + $msg = __d('Users', 'Issues trying to log in with your social account'); + if (isset($event->data['exception']) ) { + if ($event->data['exception'] instanceof MissingEmailException) { + $this->Flash->success(__d('Users', 'Please enter your email')); + $this->request->session()->write(Configure::read('Users.Key.Session.social'), $event->data['rawData']); + return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); + } + if ($event->data['exception'] instanceof UserNotActiveException) { + $msg = __d('Users', 'Your user has not been validated yet. Please check your inbox for instructions'); + } elseif ($event->data['exception'] instanceof AccountNotActiveException) { + $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); + } } $this->Flash->success($msg); return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); @@ -76,13 +79,14 @@ public function login() return $this->redirect($event->result); } - $socialLogin = $this->request->session()->check(Configure::read('Users.Key.Session.social')); + $socialLogin = $this->_isSocialLogin(); + if (!empty($socialLogin)) { - $this->redirect(['action' => 'social-email']); + return $this->redirect(['action' => 'social-email']); } if ($this->request->is('post')) { $user = $this->Auth->identify(); - return $this->_afterIdentifyUser($user, false); + return $this->_afterIdentifyUser($user, $socialLogin); } } @@ -109,7 +113,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false) $this->Flash->error($message, 'default', [], 'auth'); } - $this->redirect(Configure::read('Auth.loginAction')); + return $this->redirect(Configure::read('Auth.loginAction')); } } diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 42e454cd5..8bb4a3a14 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -53,15 +53,15 @@ public function beforeLayout(Event $event) * @param array $options * @return string */ - public function socialLogin($name, $options) + public function socialLogin($name, $options = []) { if (empty($options['label'])) { $options['label'] = 'Sign in with'; } return $this->Html->link($this->Html->tag('i', '', [ 'class' => __d('Users', 'fa fa-{0}', strtolower($name)), - ]) . __d('Users', '{0} {1}', $options['label'], Inflector::camelize($name)), "/auth/$name", [ - 'escape' => false, 'class' => __d('Users', 'btn btn-social btn-{0} ' . $options['class'] ? :'', strtolower($name)) + ]) . __d('Users', '{0} {1}', Hash::get($options, 'label') , Inflector::camelize($name)), "/auth/$name", [ + 'escape' => false, 'class' => __d('Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ? :'', strtolower($name)) ]); } diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 88bac68f5..a3255fb4c 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -15,14 +15,15 @@ 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\Network\Request; +use Cake\ORM\Entity; use Cake\TestSuite\TestCase; -use Opauth\Opauth\Response; -class LoginTraitTest extends TestCase +class LoginTraitTest extends BaseTraitTest { /** * setup @@ -31,6 +32,9 @@ class LoginTraitTest extends TestCase */ public function setUp() { + $this->traitClassName = 'CakeDC\Users\Controller\Traits\LoginTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; + parent::setUp(); $request = new Request(); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') @@ -49,18 +53,6 @@ public function tearDown() parent::tearDown(); } - /** - * mock utility - * - * @return void - */ - protected function _mockDispatchEvent(Event $event) - { - $this->Trait->expects($this->any()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); - } - /** * test * @@ -119,7 +111,6 @@ public function testAfterIdentifyEmptyUser() ->disableOriginalConstructor() ->getMock(); $user = []; - $redirectLoginOK = '/'; $this->Trait->Auth->expects($this->once()) ->method('identify') ->will($this->returnValue($user)); @@ -150,112 +141,25 @@ public function testAfterIdentifyEmptyUserSocialLogin() $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') ->setMethods(['is']) ->getMock(); - $this->Trait->request->expects($this->once()) + /*$this->Trait->request->expects($this->once()) ->method('is') ->with('post') - ->will($this->returnValue(true)); + ->will($this->returnValue(true));*/ $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) ->disableOriginalConstructor() ->getMock(); $user = []; - $redirectLoginOK = '/'; - $this->Trait->Auth->expects($this->once()) + /* $this->Trait->Auth->expects($this->once()) ->method('identify') - ->will($this->returnValue($user)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with([ - 'controller' => 'Users', - 'action' => 'socialEmail' - ]); - $this->Trait->login(); - } + ->will($this->returnValue($user));*/ - /** - * test - * - * @return void - */ - public function testLoginAfterIdentifyAccountNotActive() - { - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') - ->setMethods(['dispatchEvent', 'redirect', '_afterIdentifyUser']) - ->getMockForTrait(); - $this->_mockDispatchEvent(new Event('event')); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); - $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify']) - ->disableOriginalConstructor() - ->getMock(); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['success']) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => 1, - ]; - $this->Trait->Auth->expects($this->once()) - ->method('identify') - ->will($this->returnValue($user)); $this->Trait->expects($this->once()) - ->method('_afterIdentifyUser') - ->with($user, false) - ->will($this->throwException(new AccountNotActiveException(''))); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Your social account has not been validated yet. Please check your inbox for instructions'); - $this->Trait->login(); - } + ->method('redirect') + ->with([ + 'action' => 'social-email' + ]); - /** - * test - * - * @return void - */ - public function testLoginAfterIdentifyMissingEmailException() - { - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') - ->setMethods(['dispatchEvent', 'redirect', '_afterIdentifyUser']) - ->getMockForTrait(); - $this->_mockDispatchEvent(new Event('event')); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); - $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify']) - ->disableOriginalConstructor() - ->getMock(); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['success']) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => 1, - ]; - $this->Trait->Auth->expects($this->once()) - ->method('identify') - ->will($this->returnValue($user)); - $this->Trait->expects($this->once()) - ->method('_afterIdentifyUser') - ->with($user, false) - ->will($this->throwException(new MissingEmailException(''))); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please enter your email'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['controller' => 'Users', 'action' => 'socialEmail']); $this->Trait->login(); } @@ -366,4 +270,116 @@ public function testLogout() ->with('You\'ve successfully logged out'); $this->Trait->logout(); } + + /** + * test + * + * @return void + */ + public function testFailedSocialLoginMissingEmail() + { + $event = new Entity(); + $event->data = [ + 'exception' => new MissingEmailException('Email not present'), + 'rawData' => [ + 'id' => 11111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please enter your email'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); + + $this->Trait->failedSocialLogin($event); + } + + /** + * test + * + * @return void + */ + public function testFailedSocialUserNotActive() + { + $event = new Entity(); + $event->data = [ + 'exception' => new UserNotActiveException('Facebook user-1'), + 'rawData' => [ + 'id' => 111111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Your user has not been validated yet. Please check your inbox for instructions'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Trait->failedSocialLogin($event); + } + + /** + * test + * + * @return void + */ + public function testFailedSocialUserAccountNotActive() + { + $event = new Entity(); + $event->data = [ + 'exception' => new AccountNotActiveException('Facebook user-1'), + 'rawData' => [ + 'id' => 111111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Your social account has not been validated yet. Please check your inbox for instructions'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Trait->failedSocialLogin($event); + } + + + /** + * test + * + * @return void + */ + public function testFailedSocialUserAccount() + { + $event = new Entity(); + $event->data = [ + 'rawData' => [ + 'id' => 111111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Issues trying to log in with your social account'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Trait->failedSocialLogin($event); + } } diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index cb71ac66d..0d0d95d49 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -39,52 +39,6 @@ public function tearDown() parent::tearDown(); } - /** - * Test opauthInit with no callback - * - */ - public function testOpauthInitTest() - { - $Opauth = $this->getMock('Opauth\Opauth\Opauth', ['run'], [], '', false); - $Opauth->expects($this->once()) - ->method('run') - ->will($this->returnValue('response')); - $this->controller->Trait->expects($this->once()) - ->method('_getOpauthInstance') - ->will($this->returnValue($Opauth)); - $this->controller->Trait->opauthInit(); - } - - /** - * Test opauthInit with callback - * - */ - public function testOpauthInitTestCallback() - { - $Opauth = $this->getMock('Opauth\Opauth\Opauth', ['run'], [], '', false); - $Opauth->expects($this->once()) - ->method('run') - ->will($this->returnValue('response')); - $session = $this->getMock('Cake\Network\Session', ['write', 'check']); - $session->expects($this->once()) - ->method('write') - ->with(Configure::read('Users.Key.Session.social'), 'response'); - $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session']); - $this->controller->Trait->request->expects($this->once()) - ->method('session') - ->will($this->returnValue($session)); - $this->controller->Trait->expects($this->once()) - ->method('_getOpauthInstance') - ->will($this->returnValue($Opauth)); - $this->controller->Trait->expects($this->once()) - ->method('_generateOpauthCompleteUrl') - ->will($this->returnValue('url')); - $this->controller->Trait->expects($this->once()) - ->method('redirect') - ->with('url'); - $this->controller->Trait->opauthInit('callback'); - } - /** * Test socialEmail * diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index e84d208bb..1a9d18a9b 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -60,7 +60,7 @@ public function testValidateUserNotFound() $this->_mockFlash(); $this->Trait->Flash->expects($this->once()) ->method('error') - ->with('Invalid token and/or email'); + ->with('Invalid token or user account already validated'); $this->Trait->expects($this->once()) ->method('redirect') ->with(['action' => 'login']); diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index ecafc1817..c241e2a41 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -179,19 +179,21 @@ public function testActivateUser() public function testSocialLogin() { - $raw = [ + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_FACEBOOK, + 'email' => 'user-2@test.com', 'id' => 'reference-2-1', - 'first_name' => 'User 2', - 'gender' => 'female', - 'verified' => 1, - 'user_email' => 'user-2@test.com', - 'link' => 'link' + 'link' => 'link', + 'raw' => [ + 'id' => 'reference-2-1', + 'token' => 'token', + 'first_name' => 'User 2', + 'gender' => 'female', + 'verified' => 1, + 'user_email' => 'user-2@test.com', + 'link' => 'link' + ] ]; - $data = new \Cake\Network\Response(); - $data->provider = SocialAccountsTable::PROVIDER_FACEBOOK; - $data->email = 'user-2@test.com'; - $data->raw = $raw; - $data->uid = 'reference-2-1'; $options = [ 'use_email' => 1, 'validate_email' => 1, @@ -209,20 +211,18 @@ public function testSocialLogin() */ public function testSocialLoginInactiveAccount() { - $raw = [ + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_TWITTER, + 'email' => 'hello@test.com', 'id' => 'reference-2-2', - 'first_name' => 'User 2', - 'gender' => 'female', - 'verified' => 1, - 'user_email' => 'hello@test.com', - ]; - $data = new \Cake\Network\Response(); - $data->provider = SocialAccountsTable::PROVIDER_TWITTER; - $data->email = 'hello@test.com'; - $data->raw = $raw; - $data->uid = 'reference-2-2'; - $data->info = [ - 'first_name' => 'User 2', + 'link' => 'link', + 'raw' => [ + 'id' => 'reference-2-2', + 'first_name' => 'User 2', + 'gender' => 'female', + 'verified' => 1, + 'user_email' => 'hello@test.com', + ] ]; $options = [ 'use_email' => 1, @@ -241,23 +241,21 @@ public function testSocialLoginInactiveAccount() */ public function testSocialLoginCreateNewAccountWithNoCredentials() { - $raw = [ + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_TWITTER, + 'email' => 'user@test.com', 'id' => 'reference-not-existing', - 'first_name' => 'Not existing user', - 'gender' => 'male', - 'user_email' => 'user@test.com', - ]; - $data = new \Cake\Network\Response(); - $data->provider = SocialAccountsTable::PROVIDER_TWITTER; - $data->email = 'user@test.com'; - $data->raw = $raw; - $data->validated = true; - $data->uid = 'reference-not-existing'; - $data->info = [ - 'first_name' => 'Not existing user', + 'link' => 'link', + 'raw' => [ + 'id' => 'reference-not-existing', + 'first_name' => 'Not existing user', + 'gender' => 'male', + 'user_email' => 'user@test.com', + ], + 'credentials' => [], + 'name' => '', ]; - $data->credentials = []; - $data->name = ''; + $options = [ 'use_email' => 0, 'validate_email' => 1, @@ -273,33 +271,34 @@ public function testSocialLoginCreateNewAccountWithNoCredentials() */ public function testSocialLoginCreateNewAccount() { - $raw = [ + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_TWITTER, + 'email' => 'username@test.com', 'id' => 'no-existing-reference', + 'link' => 'link', 'first_name' => 'First Name', 'last_name' => 'Last Name', - 'gender' => 'male', - 'user_email' => 'user@test.com', - 'twitter' => 'link' - ]; - - $data = new \Cake\Network\Response(); - $data->provider = SocialAccountsTable::PROVIDER_TWITTER; - $data->email = 'user-2@test.com'; - $data->raw = $raw; - $data->uid = 'no-existing-reference'; - $data->info = [ - 'first_name' => 'First Name', - 'last_name' => 'Last Name', - 'urls' => ['twitter' => 'twitter'], + 'raw' => [ + 'id' => 'no-existing-reference', + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'gender' => 'male', + 'user_email' => 'user@test.com', + 'twitter' => 'link' + ], + 'info' => [ + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'urls' => ['twitter' => 'twitter'] + ], + 'validated' => true, + 'credentials' => [ + 'token' => 'token', + 'token_secret' => 'secret', + 'token_expires' => '' + ], ]; - $data->validated = true; - $data->email = 'username@test.com'; - $data->credentials = [ - 'token' => 'token', - 'token_secret' => 'secret', - 'token_expires' => '' - ]; $options = [ 'use_email' => 0, 'validate_email' => 0, diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 651d70ca0..249406620 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -53,30 +53,6 @@ public function tearDown() parent::tearDown(); } - /** - * Test facebookLogin - * - * @return void - */ - public function testFacebookLogin() - { - $result = $this->User->facebookLogin(); - $expected = 'Sign in with Facebook'; - $this->assertEquals($expected, $result); - } - - /** - * Test twitterLogin - * - * @return void - */ - public function testTwitterLoginEnabled() - { - $result = $this->User->twitterLogin(); - $expected = 'Sign in with Twitter'; - $this->assertEquals($expected, $result); - } - /** * Test twitterLogin * From 65547cdaed44d5658e4cbc41f4c3062468c41e00 Mon Sep 17 00:00:00 2001 From: David Albrecht Date: Mon, 9 Nov 2015 11:10:37 +0100 Subject: [PATCH 0309/1476] unified style of hash-function of the six calls of User->hash() some had `null`as second parameter and some had `sha1`. Both have the same effect, since the hash-method of Cake's Utility/Security-class defaults to `sha1` if the hashing-type is set to `null`. However, I think it is better to unify this, because if anything changes in the default-behaviour of Cake's hash-function this Plugin will break. --- Model/User.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Model/User.php b/Model/User.php index a73ab8c56..7a30fe868 100644 --- a/Model/User.php +++ b/Model/User.php @@ -574,7 +574,7 @@ public function register($postData = array(), $options = array()) { $this->set($postData); if ($this->validates()) { - $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); + $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], null, true); $this->create(); $this->data = $this->save($postData, false); $this->data[$this->alias]['id'] = $this->id; @@ -830,7 +830,7 @@ public function add($postData = null) { $postData[$this->alias]['role'] = 'admin'; } } - $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); + $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], null, true); $this->create(); $result = $this->save($postData, false); if ($result) { @@ -860,7 +860,7 @@ public function edit($userId = null, $postData = null) { $this->set($postData); if ($this->validates()) { if(isset($postData[$this->alias]['password'])) { - $this->data[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], 'sha1', true); + $this->data[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], null, true); } $result = $this->save(null, false); if ($result) { From 5a53ec12c6b5fb678fb5e2d52d3309278dff8f2b Mon Sep 17 00:00:00 2001 From: David Albrecht Date: Mon, 9 Nov 2015 11:12:23 +0100 Subject: [PATCH 0310/1476] fixed links --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 408e81198..95b7fc2a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing ============ -This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugins). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/plugins) for detailed instructions. \ No newline at end of file +This repository follows the [CakeDC Plugin Standard](http://www.cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://www.cakedc.com/plugin-standard#contributing) for detailed instructions. \ No newline at end of file From cfc78d0cb057d57bff80797599934b1c57c6c64e Mon Sep 17 00:00:00 2001 From: David Albrecht Date: Mon, 9 Nov 2015 12:15:02 +0100 Subject: [PATCH 0311/1476] hash-function parameters set in one place In order to reduce repetion, I removed the optional parameters from the six hash-calls. The parameters are now being set only once in the default-params definition. This increases the readability of the code, especially when somebody overrides the User->hash() method to use a different hashing method, but doesn't want to change all six calls of the hash-method to remove the type and salt definitions there. --- Model/User.php | 14 +++++++------- Test/Case/Model/UserTest.php | 8 ++++---- Test/Fixture/UserFixture.php | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Model/User.php b/Model/User.php index 7a30fe868..8e1e8ab8a 100644 --- a/Model/User.php +++ b/Model/User.php @@ -194,7 +194,7 @@ protected function _setupValidation() { * value to $string (Security.salt) * @return string Hash */ - public function hash($string, $type = null, $salt = false) { + public function hash($string, $type = null, $salt = true) { return Security::hash($string, $type, $salt); } @@ -381,7 +381,7 @@ public function resetPassword($postData = array()) { $this->set($postData); if ($this->validates()) { - $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['new_password'], null, true); + $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['new_password']); $this->data[$this->alias]['password_token'] = null; $result = $this->save($this->data, array( 'validate' => false, @@ -404,7 +404,7 @@ public function changePassword($postData = array()) { $this->set($postData); if ($this->validates()) { - $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['new_password'], null, true); + $this->data[$this->alias]['password'] = $this->hash($this->data[$this->alias]['new_password']); $this->save($postData, array( 'validate' => false, 'callbacks' => $this->enableCallbacks)); @@ -428,7 +428,7 @@ public function validateOldPassword($password) { } $currentPassword = $this->field('password', array($this->alias . '.id' => $this->data[$this->alias]['id'])); - return $currentPassword === $this->hash($password['old_password'], null, true); + return $currentPassword === $this->hash($password['old_password']); } /** @@ -574,7 +574,7 @@ public function register($postData = array(), $options = array()) { $this->set($postData); if ($this->validates()) { - $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], null, true); + $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password']); $this->create(); $this->data = $this->save($postData, false); $this->data[$this->alias]['id'] = $this->id; @@ -830,7 +830,7 @@ public function add($postData = null) { $postData[$this->alias]['role'] = 'admin'; } } - $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], null, true); + $postData[$this->alias]['password'] = $this->hash($postData[$this->alias]['password']); $this->create(); $result = $this->save($postData, false); if ($result) { @@ -860,7 +860,7 @@ public function edit($userId = null, $postData = null) { $this->set($postData); if ($this->validates()) { if(isset($postData[$this->alias]['password'])) { - $this->data[$this->alias]['password'] = $this->hash($postData[$this->alias]['password'], null, true); + $this->data[$this->alias]['password'] = $this->hash($postData[$this->alias]['password']); } $result = $this->save(null, false); if ($result) { diff --git a/Test/Case/Model/UserTest.php b/Test/Case/Model/UserTest.php index 1cb06c46c..f2ce835ea 100755 --- a/Test/Case/Model/UserTest.php +++ b/Test/Case/Model/UserTest.php @@ -196,7 +196,7 @@ public function testPasswordReset() { * @return void */ public function testValidateOldPassword() { - $password = $this->User->hash('password', null, true); + $password = $this->User->hash('password'); $this->User->id = '1'; $this->User->saveField('password', $password); $this->User->data = array( @@ -289,7 +289,7 @@ public function testRegister() { $result = $this->User->data; $this->assertEquals($result['User']['active'], 1); - $this->assertEquals($result['User']['password'], $this->User->hash('password', 'sha1', true)); + $this->assertEquals($result['User']['password'], $this->User->hash('password')); $this->assertTrue(is_string($result['User']['email_token'])); $result = $this->User->findById($this->User->id); @@ -329,7 +329,7 @@ public function testChangePassword() { 'recursive' => -1, 'conditions' => array( 'User.id' => 1))); - $this->assertEquals($ressult['User']['password'], $this->User->hash('testtest', null, true)); + $this->assertEquals($ressult['User']['password'], $this->User->hash('testtest')); } /** @@ -464,7 +464,7 @@ public function testEditPassword() { $result = $this->User->edit($userId, $data1); - $hashPassword = $this->User->hash($data1['User']['password'], 'sha1', true); + $hashPassword = $this->User->hash($data1['User']['password']); $this->assertTrue($result); $this->assertEquals($this->User->data['User']['password'], $hashPassword); diff --git a/Test/Fixture/UserFixture.php b/Test/Fixture/UserFixture.php index 838df1cd2..4bf4db904 100644 --- a/Test/Fixture/UserFixture.php +++ b/Test/Fixture/UserFixture.php @@ -188,7 +188,7 @@ public function __construct() { parent::__construct(); $this->User = ClassRegistry::init('Users.User'); foreach ($this->records as &$record) { - $record['password'] = $this->User->hash($record['password'], null, true); + $record['password'] = $this->User->hash($record['password']); } } From 2856b2cdcddb42034cd56edf266c1c77c90417ac Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Mon, 9 Nov 2015 17:49:04 -0430 Subject: [PATCH 0312/1476] Refactoring UserHelper::link to use UserHelper::isAuthorized method --- src/View/Helper/UserHelper.php | 4 +--- tests/TestCase/View/Helper/UserHelperTest.php | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 0cb5dc7af..1263837bc 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -97,9 +97,7 @@ public function logout($message = null, $options = []) */ public function link($title, $url = null, array $options = []) { - $event = new Event(UsersAuthComponent::EVENT_IS_AUTHORIZED, $this, ['url' => $url]); - $result = $this->_View->eventManager()->dispatch($event); - if ($result->result) { + if ($this->isAuthorized($url)) { $linkOptions = $options; unset($linkOptions['before'], $linkOptions['after']); return Hash::get($options, 'before') . $this->Html->link($title, $url, $linkOptions) . Hash::get($options, 'after'); diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index bbdad73a3..6c29af869 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -153,7 +153,7 @@ public function testLinkAuthorized() * * @return void */ - public function testIsAuthorizedHH() + public function testIsAuthorized() { $view = new View(); $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') @@ -167,8 +167,8 @@ public function testIsAuthorizedHH() ->method('dispatch') ->will($this->returnValue($result)); - $link = $this->User->isAuthorized(['controller' => 'MyController', 'action' => 'myAction']); - $this->assertTrue($link); + $result = $this->User->isAuthorized(['controller' => 'MyController', 'action' => 'myAction']); + $this->assertTrue($result); } From f11d3415719d166139c257b0c6ef107f99f72254 Mon Sep 17 00:00:00 2001 From: "Joan B. Gimenez" Date: Wed, 11 Nov 2015 09:21:00 -0700 Subject: [PATCH 0313/1476] It Users.Tos.required is set to false, do not display the Tos checkbox during registration --- src/Template/Users/register.ctp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index 80b2f1470..37556f5f3 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -20,7 +20,9 @@ echo $this->Form->input('password_confirm', ['type' => 'password']); echo $this->Form->input('first_name'); echo $this->Form->input('last_name'); - echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); + if (Configure::read('Users.Tos.required')) { + echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); + } echo $this->User->addReCaptcha(); ?>
From efc3c8c9e3da764c8f528ac8bc8822a82a7e2fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 12 Nov 2015 09:25:42 +0000 Subject: [PATCH 0314/1476] fix phpcs --- src/Template/Users/register.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index 37556f5f3..773ed5fc8 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -21,7 +21,7 @@ echo $this->Form->input('first_name'); echo $this->Form->input('last_name'); if (Configure::read('Users.Tos.required')) { - echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); + echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); } echo $this->User->addReCaptcha(); ?> From ce11dd0e352ade110a18e448d50b999023fe93d3 Mon Sep 17 00:00:00 2001 From: "Joan B. Gimenez" Date: Thu, 12 Nov 2015 08:08:39 -0700 Subject: [PATCH 0315/1476] Ignoring some IDEA project files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 61ead8666..220baa276 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /vendor +CakeUsersPlugin.iml +.idea From df3a1abf012e1dd8019ec717db857a2ab890d576 Mon Sep 17 00:00:00 2001 From: "Joan B. Gimenez" Date: Thu, 12 Nov 2015 08:28:35 -0700 Subject: [PATCH 0316/1476] Ignoring any .iml file, regardless the name --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 220baa276..4681e063b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /vendor -CakeUsersPlugin.iml +*.iml .idea From 20b9082851df4aa312b0bbcabd8b2383e9f212e7 Mon Sep 17 00:00:00 2001 From: "Joan B. Gimenez" Date: Thu, 12 Nov 2015 09:32:48 -0700 Subject: [PATCH 0317/1476] Do not need this .gitignore changes for the pull --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4681e063b..61ead8666 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ /vendor -*.iml -.idea From 95d036a1cb9f10846aec5aa909b65f61d09ffa03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 16 Nov 2015 10:21:01 +0000 Subject: [PATCH 0318/1476] add ApiAuthenticate to allow simple token based auth --- .gitignore | 3 + src/Auth/ApiKeyAuthenticate.php | 107 ++++++++++++ .../TestCase/Auth/ApiKeyAuthenticateTest.php | 156 ++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 src/Auth/ApiKeyAuthenticate.php create mode 100644 tests/TestCase/Auth/ApiKeyAuthenticateTest.php diff --git a/.gitignore b/.gitignore index 61ead8666..4e2c08050 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ +/tmp /vendor +/.idea +composer.lock diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php new file mode 100644 index 000000000..5fa2bf320 --- /dev/null +++ b/src/Auth/ApiKeyAuthenticate.php @@ -0,0 +1,107 @@ + self::TYPE_QUERYSTRING, + //name to retrieve the api key value from + 'name' => 'api_key', + //db field where the key is stored + 'field' => 'api_token', + //require SSL to pass the token. You should always require SSL to use tokens for Auth + 'require_ssl' => true, + ]; + + /** + * Authenticate callback + * Reads the API Key based on configuration and login the user + * + * @param Request $request Cake request object. + * @param Response $response Cake response object. + * @return mixed + */ + public function authenticate(Request $request, Response $response) + { + $type = $this->config('type'); + if (!in_array($type, $this->types)) { + throw new OutOfBoundsException(__d('Users', 'Type {0} is not valid', $type)); + } + + if (!is_callable([$this, $type])) { + throw new OutOfBoundsException(__d('Users', 'Type {0} has no associated callable', $type)); + } + + if ($this->config('require_ssl') && !$request->is('ssl')) { + throw new ForbiddenException(__d('Users', 'SSL is required for ApiKey Authentication', $type)); + } + + $apiKey = $this->$type($request); + if (empty($apiKey)) { + return false; + } + + $this->_config['fields']['username'] = $this->config('field'); + $this->_config['userModel'] = Configure::read('Users.table'); + $this->_config['finder'] = 'all'; + $result = $this->_query($apiKey)->first(); + + if (empty($result)) { + return false; + } + + return $result->toArray(); + //idea: add array with checks to be passed to $request->is(...) + } + + /** + * Get the api key from the querystring + * + * @param Request $request + * @return string api key + */ + public function querystring(Request $request) + { + $name = $this->config('name'); + return $request->query($name); + } + + /** + * Get the api key from the header + * + * @param Request $request + * @return string api key + */ + public function header(Request $request) + { + $name = $this->config('name'); + return $request->header($name); + } +} diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php new file mode 100644 index 000000000..dbe3c1418 --- /dev/null +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -0,0 +1,156 @@ +getMock( + 'Cake\Controller\Controller', + null, + [$request, $response] + ); + $registry = new ComponentRegistry($controller); + $this->apiKey = new ApiKeyAuthenticate($registry, ['require_ssl' => false]); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->apiKey, $this->controller); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHappy() + { + $request = new Request('/?api_key=yyy'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertEquals('user-1', $result['username']); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateFail() + { + $request = new Request('/'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + + $request = new Request('/?api_key=none'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + + $request = new Request('/?api_key='); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Type wrong is not valid + * + */ + public function testAuthenticateWrongType() + { + $this->apiKey->config('type', 'wrong'); + $request = new Request('/'); + $this->apiKey->authenticate($request, new Response()); + } + + /** + * test + * + * @expectedException \Cake\Network\Exception\ForbiddenException + * @expectedExceptionMessage SSL is required for ApiKey Authentication + * + */ + public function testAuthenticateRequireSSL() + { + $this->apiKey->config('require_ssl', true); + $request = new Request('/'); + $this->apiKey->authenticate($request, new Response()); + } + + /** + * test + * + * @return void + */ + public function testHeaderHappy() + { + $request = $this->getMockBuilder('\Cake\Network\Request') + ->setMethods(['header']) + ->getMock(); + $request->expects($this->once()) + ->method('header') + ->with('api_key') + ->will($this->returnValue('yyy')); + $this->apiKey->config('type', 'header'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertEquals('user-1', $result['username']); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHeaderFail() + { + $request = $this->getMockBuilder('\Cake\Network\Request') + ->setMethods(['header']) + ->getMock(); + $request->expects($this->once()) + ->method('header') + ->with('api_key') + ->will($this->returnValue('wrong')); + $this->apiKey->config('type', 'header'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + } +} From bd5255b44d1998116e9bbd211e797e817a932793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 16 Nov 2015 11:08:12 +0000 Subject: [PATCH 0319/1476] refs #api-authenticate fix phpcs --- src/Auth/ApiKeyAuthenticate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 5fa2bf320..36f51dc39 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -84,7 +84,7 @@ public function authenticate(Request $request, Response $response) /** * Get the api key from the querystring * - * @param Request $request + * @param Request $request request * @return string api key */ public function querystring(Request $request) @@ -96,7 +96,7 @@ public function querystring(Request $request) /** * Get the api key from the header * - * @param Request $request + * @param Request $request request * @return string api key */ public function header(Request $request) From edccfa41e5c7239122d7492004acfd574292eb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 16 Nov 2015 11:17:06 +0000 Subject: [PATCH 0320/1476] refs #api-authenticate add to defaults and add doc page --- Docs/Documentation/ApiKeyAuthenticate.md | 29 ++++++++++++++++++++++++ config/users.php | 1 + 2 files changed, 30 insertions(+) create mode 100644 Docs/Documentation/ApiKeyAuthenticate.md diff --git a/Docs/Documentation/ApiKeyAuthenticate.md b/Docs/Documentation/ApiKeyAuthenticate.md new file mode 100644 index 000000000..9befe32b2 --- /dev/null +++ b/Docs/Documentation/ApiKeyAuthenticate.md @@ -0,0 +1,29 @@ +ApiKeyAuthenticate +============= + +Setup +--------------- + +ApiKeyAuthenticate default configuration is +```php + protected $_defaultConfig = [ + //type, can be either querystring or header + 'type' => self::TYPE_QUERYSTRING, + //name to retrieve the api key value from + 'name' => 'api_key', + //db field where the key is stored + 'field' => 'api_token', + //require SSL to pass the token. You should always require SSL to use tokens for Auth + 'require_ssl' => true, + ]; +``` + +We are using query strings for passing the api_key token. And we require SSL by default. +Note you can override these options using + +```php +$config['Auth']['authenticate']['CakeDC/Users.ApiKey'] = [ + 'type' => 'header', + ]; +``` + diff --git a/config/users.php b/config/users.php index a9a602d45..ec9078120 100644 --- a/config/users.php +++ b/config/users.php @@ -91,6 +91,7 @@ 'all' => [ 'scope' => ['active' => 1] ], + 'CakeDC/Users.ApiKey', 'CakeDC/Users.RememberMe', 'Form', ], From 4a846c8fba6239354c96bab865a8ad4de9d0f971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 16 Nov 2015 15:37:31 +0000 Subject: [PATCH 0321/1476] Change order to check first if api key --- src/Auth/ApiKeyAuthenticate.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 36f51dc39..e667d29bb 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -59,15 +59,15 @@ public function authenticate(Request $request, Response $response) throw new OutOfBoundsException(__d('Users', 'Type {0} has no associated callable', $type)); } - if ($this->config('require_ssl') && !$request->is('ssl')) { - throw new ForbiddenException(__d('Users', 'SSL is required for ApiKey Authentication', $type)); - } - $apiKey = $this->$type($request); if (empty($apiKey)) { return false; } + if ($this->config('require_ssl') && !$request->is('ssl')) { + throw new ForbiddenException(__d('Users', 'SSL is required for ApiKey Authentication', $type)); + } + $this->_config['fields']['username'] = $this->config('field'); $this->_config['userModel'] = Configure::read('Users.table'); $this->_config['finder'] = 'all'; From 1e01aa41c8eac59f7d2c85324b2abe929827a975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 16 Nov 2015 15:52:35 +0000 Subject: [PATCH 0322/1476] refs #fix-texts-reorder-api-key fix test --- tests/TestCase/Auth/ApiKeyAuthenticateTest.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php index dbe3c1418..3008c98ce 100644 --- a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -112,10 +112,22 @@ public function testAuthenticateWrongType() public function testAuthenticateRequireSSL() { $this->apiKey->config('require_ssl', true); - $request = new Request('/'); + $request = new Request('/?api_key=test'); $this->apiKey->authenticate($request, new Response()); } + /** + * test + * + */ + public function testAuthenticateRequireSSLNoKey() + { + $this->apiKey->config('require_ssl', true); + $request = new Request('/'); + $this->assertFalse($this->apiKey->authenticate($request, new Response())); + } + + /** * test * From 4b45ba8dec01ce3e3f9c60eb9f7723025a9c1728 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 27 Nov 2015 09:06:55 -0430 Subject: [PATCH 0323/1476] Updated documentation based on social login changes --- Docs/Documentation/Configuration.md | 44 ++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 2d98fafa9..1d8e387d7 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -11,16 +11,31 @@ config/bootstrap.php Configure::write('Users.config', ['users']); Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); ``` - + Then in your config/users.php ``` -return [ - 'Opauth.Strategy.Facebook.app_id' => 'YOUR APP ID', - 'Opauth.Strategy.Facebook.app_secret' => 'YOUR APP SECRET', - 'Opauth.Strategy.Twitter.key' => 'YOUR APP KEY', - 'Opauth.Strategy.Twitter.secret' => 'YOUR APP SECRET', - //etc -]; +'Opauth.providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5' + ] + ], + 'linkedIn' => [ + 'className' => 'League\OAuth2\Client\Provider\LinkedIn', + ], + 'instagram' => [ + 'className' => 'League\OAuth2\Client\Provider\Instagram', + ], + 'google' => [ + 'className' => 'League\OAuth2\Client\Provider\Google', + 'options' => [ + 'userFields' => ['url', 'aboutMe'], + ] + ] + //etc + ], + ``` Configuration for social login @@ -30,11 +45,14 @@ Create the facebook/twitter applications you want to use and setup the configura config/bootstrap.php ``` -Configure::write('Opauth.Strategy.Facebook.app_id', 'YOUR APP ID'); -Configure::write('Opauth.Strategy.Facebook.app_secret', 'YOUR APP SECRET'); +Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); +Configure::write('OAuth.providers.facebook.options.redirectUri', 'REDIRECT URL'); + +Configure::write('OAuth.providers.instagram.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.instagram.options.clientSecret', 'YOUR APP SECRET'); +Configure::write('OAuth.providers.instagram.options.redirectUri','REDIRECT URL') -Configure::write('Opauth.Strategy.Twitter.key', 'YOUR APP KEY'); -Configure::write('Opauth.Strategy.Twitter.secret', 'YOUR APP SECRET'); ``` Or use the config override option when loading the plugin (see above) @@ -147,4 +165,4 @@ To modify the flash messages, use the standard PO file provided by the plugin an Check http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#setting-up-translations for more details about how the PO files should be managed in your application. -We've included an updated POT file with all the `Users` domain keys for your customization. \ No newline at end of file +We've included an updated POT file with all the `Users` domain keys for your customization. From c7a627e6dc97e2fbfb38a6069cbf2f36b4ffd287 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 27 Nov 2015 09:22:02 -0430 Subject: [PATCH 0324/1476] Updated documentation based on social login changes --- Docs/Documentation/Installation.md | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index db8527cff..f18ac7738 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -11,21 +11,12 @@ composer require cakedc/users:3.1.* if you want to use social login features... ``` -composer require opauth/opauth:1.0.x-dev -composer require opauth/facebook:1.0.x-dev -composer require opauth/twitter:1.0.x-dev -``` - -IMPORTANT: We have a fork adding some fixes to the facebook strategy, please add to your composer.json file: +composer require Muffin/OAuth2:* +composer require league/oauth2-facebook:* +composer require league/oauth2-instagram:* +composer require league/oauth2-google:* +composer require league/oauth2-linkedin:* -``` - "repositories": - [ - { - "type": "vcs", - "url": "https://github.com/CakeDC/facebook.git" - } - ], ``` Creating Required Tables @@ -61,12 +52,15 @@ Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); Then in your config/users.php ``` return [ - 'Opauth.Strategy.Facebook.app_id' => 'YOUR APP ID', - 'Opauth.Strategy.Facebook.app_secret' => 'YOUR APP SECRET', - 'Opauth.Strategy.Twitter.key' => 'YOUR APP KEY', - 'Opauth.Strategy.Twitter.secret' => 'YOUR APP SECRET', + 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', + 'OAuth.providers.facebook.options.clientSecret' => 'YOUR APP SECRET', + 'OAuth.providers.facebook.options.redirectUri' => 'REDIRECT URL', + 'OAuth.providers.instagram.options.clientId' => 'YOUR APP ID', + 'OAuth.providers.instagram.options.clientSecret' => 'YOUR APP SECRET', + 'OAuth.providers.instagram.options.redirectUri' => 'REDIRECT URL', //etc ]; + ``` For more details, check the Configuration doc page From 631e7f67a933102be10cd30636ab29ab58f2c5bf Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 3 Dec 2015 08:54:47 -0430 Subject: [PATCH 0325/1476] Updating documentation --- Docs/Documentation/Configuration.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 1d8e387d7..a37f68b0f 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -20,18 +20,22 @@ Then in your config/users.php 'options' => [ 'graphApiVersion' => 'v2.5' ] + 'redirectUri' => Router::url('/auth/facebook', true) ], 'linkedIn' => [ 'className' => 'League\OAuth2\Client\Provider\LinkedIn', + 'redirectUri' => Router::url('/auth/linkedIn', true) ], 'instagram' => [ 'className' => 'League\OAuth2\Client\Provider\Instagram', + 'redirectUri' => Router::url('/auth/instagram', true) ], 'google' => [ 'className' => 'League\OAuth2\Client\Provider\Google', 'options' => [ 'userFields' => ['url', 'aboutMe'], ] + 'redirectUri' => Router::url('/auth/google', true) ] //etc ], @@ -47,11 +51,9 @@ config/bootstrap.php ``` Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); -Configure::write('OAuth.providers.facebook.options.redirectUri', 'REDIRECT URL'); Configure::write('OAuth.providers.instagram.options.clientId', 'YOUR APP ID'); Configure::write('OAuth.providers.instagram.options.clientSecret', 'YOUR APP SECRET'); -Configure::write('OAuth.providers.instagram.options.redirectUri','REDIRECT URL') ``` From f04f51813c19479adffcaf46d0d052242a6ff1ff Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 3 Dec 2015 08:55:23 -0430 Subject: [PATCH 0326/1476] Updating documentation --- Docs/Documentation/Installation.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index f18ac7738..3822254fa 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -54,10 +54,8 @@ Then in your config/users.php return [ 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', 'OAuth.providers.facebook.options.clientSecret' => 'YOUR APP SECRET', - 'OAuth.providers.facebook.options.redirectUri' => 'REDIRECT URL', 'OAuth.providers.instagram.options.clientId' => 'YOUR APP ID', 'OAuth.providers.instagram.options.clientSecret' => 'YOUR APP SECRET', - 'OAuth.providers.instagram.options.redirectUri' => 'REDIRECT URL', //etc ]; From d4fa1fc9183a75518ff6028ececcfd881e9f4ed8 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 4 Dec 2015 11:30:09 -0500 Subject: [PATCH 0327/1476] wip Twitter login --- config/bootstrap.php | 2 +- config/routes.php | 7 ++ config/users.php | 2 +- src/Auth/Social/Mapper/AbstractMapper.php | 9 ++- src/Auth/Social/Mapper/Twitter.php | 16 ++++- src/Auth/SocialAuthenticate.php | 33 +++++++--- .../Component/UsersAuthComponent.php | 1 + src/Controller/Traits/LoginTrait.php | 65 +++++++++++++++++-- src/Model/Behavior/SocialBehavior.php | 4 ++ src/Template/Users/social_email.ctp | 1 + 10 files changed, 116 insertions(+), 24 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 9efc06c3e..38e79e6fa 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -25,5 +25,5 @@ if (Configure::read('Users.Social.login')) { Plugin::load('Muffin/OAuth2'); - EventManager::instance()->on(\CakeDC\Users\Controller\Component\UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, [new \CakeDC\Users\Controller\UsersController(), 'failedSocialLogin']); + EventManager::instance()->on(\CakeDC\Users\Controller\Component\UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, [new \CakeDC\Users\Controller\UsersController(), 'failedSocialLoginListener']); } diff --git a/config/routes.php b/config/routes.php index 103c8a55d..27b1e480c 100644 --- a/config/routes.php +++ b/config/routes.php @@ -27,6 +27,13 @@ }); } +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 1ce14c39d..d332eade8 100644 --- a/config/users.php +++ b/config/users.php @@ -119,7 +119,7 @@ 'options' => [ 'userFields' => ['url', 'aboutMe'], ] - ] + ], ], ] ]; diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index 62dbb2be1..f5febe6b4 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -90,12 +90,11 @@ protected function _map() } $result[$field] = $value; }); - /** @var \League\OAuth2\Client\Token\AccessToken $token **/ - $token = Hash::get($this->_rawData, 'token'); + $token = (array)Hash::get($this->_rawData, 'token'); $result['credentials'] = [ - 'token' => $token->getToken(), - 'secret' => null, //todo check when twitter is available - 'expires' => $token->getExpires(), + 'token' => Hash::get($token, 'accessToken'), + 'secret' => Hash::get($token, 'tokenSecret'), + 'expires' => Hash::get($token, 'expires'), ]; $result['raw'] = $this->_rawData; return $result; diff --git a/src/Auth/Social/Mapper/Twitter.php b/src/Auth/Social/Mapper/Twitter.php index 1ea14e196..639190ab8 100644 --- a/src/Auth/Social/Mapper/Twitter.php +++ b/src/Auth/Social/Mapper/Twitter.php @@ -11,5 +11,19 @@ class Twitter extends AbstractMapper { - + /** + * Map for provider fields + * @var null + */ + protected $_mapFields = [ + 'id' => 'uid', + 'username' => 'nickname', + 'full_name' => 'name', + 'first_name' => 'firstName', + 'last_name' => 'lastName', + 'email' => 'email', + 'avatar' => 'imageUrl', + 'bio' => 'description', + 'validated' => 'validated' + ]; } \ No newline at end of file diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 0bc472f5f..1d8023db1 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -22,6 +22,7 @@ use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Model\Table\SocialAccountsTable; use Muffin\OAuth2\Auth\OAuthAuthenticate; /** @@ -39,16 +40,16 @@ class SocialAuthenticate extends OAuthAuthenticate */ public function __construct(ComponentRegistry $registry, array $config = []) { - Configure::write('Muffin/OAuth2', Configure::read('OAuth')); - parent::__construct($registry, array_merge($config, Configure::read('OAuth'))); + $oauthConfig = Configure::read('OAuth'); + unset($oauthConfig['providers']['twitter']); + Configure::write('Muffin/OAuth2', $oauthConfig); + parent::__construct($registry, array_merge($config, $oauthConfig)); } /** - * Finds or creates a local user. - * - * @param array $data Mapped user data. - * @return array - * @throws \Muffin\OAuth2\Auth\Exception\MissingEventListenerException + * Find or create local user + * @param array $data + * @return array|bool|mixed */ protected function _touch(array $data) { @@ -63,7 +64,7 @@ protected function _touch(array $data) if (empty($data['provider']) && !empty($this->_provider)) { $data['provider'] = SocialUtils::getProvider($this->_provider); } - $user = $User->socialLogin($data, $options); + $user = $User->socialLogin($data, $options); } catch (UserNotActiveException $ex) { $exception = $ex; } catch (AccountNotActiveException $ex) { @@ -71,10 +72,14 @@ protected function _touch(array $data) } catch (MissingEmailException $ex) { $exception = $ex; } + if (!empty($exception)) { $event = UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN; $args = ['exception' => $exception, 'rawData' => $data]; $event = $this->dispatchEvent($event, $args); + if ($data['provider'] == SocialAccountsTable::PROVIDER_TWITTER) { + throw $exception; + } return $event->result; } @@ -101,16 +106,24 @@ public function getUser(Request $request) $user = $data; $request->session()->delete(Configure::read('Users.Key.Session.social')); } else { - if (!$rawData = $this->_authenticate($request)) { + if (empty($data) && !$rawData = $this->_authenticate($request)) { return false; } - $provider = SocialUtils::getProvider($this->_provider); + if (empty($rawData)) { + $rawData = $data; + } + if (!is_null($this->_provider)) { + $provider = SocialUtils::getProvider($this->_provider); + } else { + $provider = ucfirst($request->param('provider')); + } $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; $providerMapper = new $providerMapperClass($rawData); $user = $providerMapper(); $user['provider'] = $provider; } + if (!$user || !$this->config('userModel')) { return false; } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index f46092a67..471a828e3 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -103,6 +103,7 @@ protected function _initAuth() 'validateEmail', 'resendTokenValidation', 'login', + 'twitterLogin', 'socialEmail', 'resetPassword', 'requestResetPassword', diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 7c31ffb26..48b27fc88 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -19,6 +19,7 @@ use Cake\Core\Configure; use Cake\Utility\Hash; use CakeDC\Users\Exception\UserNotActiveException; +use League\OAuth1\Client\Server\Twitter; /** * Covers the login, logout and social login @@ -28,20 +29,72 @@ trait LoginTrait { use CustomUsersTableTrait; + public function twitterLogin() { + $this->autoRender = false; + $server = new Twitter(array( + 'identifier' => 'ZqU9nNUsyuRkDJRLvPYPQ9YXI', + 'secret' => 'vZrxSe5c7DKEUROMpTUDjPu2Mepvvzucsk1ZSSYluRiNB4H5qN', + 'callbackUri' => 'http://local.woozk.xyz/auth/twitter', + )); +// $oauthToken = $this->request->query('oauth_token'); +// $oauthVerifier = $this->request->query('oauth_verifier'); +// if (!empty($oauthToken) && !empty($oauthVerifier)) { + $temporaryCredentials = $this->request->session()->read('temporary_credentials'); + //$tokenCredentials = $server->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); + $tokenCredentials = new \League\OAuth1\Client\Credentials\TokenCredentials(); + $tokenCredentials->setIdentifier('2165382168-o3THZG14a5t21k4CdkCmGhecu2MrZpPNx6rpflm'); + $tokenCredentials->setSecret('sX0CMhCzoaUPxlachfdAItdrkZAgltk5xy0Djbl1hfXaP'); + $user = (array)$server->getUserDetails($tokenCredentials); + $user['token'] = [ + 'accessToken' => $tokenCredentials->getIdentifier(), + 'tokenSecret' => $tokenCredentials->getSecret(), + ]; + $this->request->session()->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->session()->read(Configure::read('Users.Key.Session.social'))); + } +// } else { +// $temporaryCredentials = $server->getTemporaryCredentials(); +// $this->request->session()->write('temporary_credentials', $temporaryCredentials); +// $server->authorize($temporaryCredentials); +// } + return; + } /** * @param $event */ - public function failedSocialLogin($event) { + public function failedSocialLoginListener(Event $event) { + $this->failedSocialLogin($event->data['exception'], $event->data['rawData']); + } + + /** + * @param $exception + * @param $data + * @return mixed + */ + public function failedSocialLogin($exception, $data) + { $msg = __d('Users', 'Issues trying to log in with your social account'); - if (isset($event->data['exception']) ) { - if ($event->data['exception'] instanceof MissingEmailException) { + if (isset($exception) ) { + if ($exception instanceof MissingEmailException) { $this->Flash->success(__d('Users', 'Please enter your email')); - $this->request->session()->write(Configure::read('Users.Key.Session.social'), $event->data['rawData']); + $this->request->session()->write(Configure::read('Users.Key.Session.social'), $data); return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); + } - if ($event->data['exception'] instanceof UserNotActiveException) { + if ($exception instanceof UserNotActiveException) { $msg = __d('Users', 'Your user has not been validated yet. Please check your inbox for instructions'); - } elseif ($event->data['exception'] instanceof AccountNotActiveException) { + } elseif ($exception instanceof AccountNotActiveException) { $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); } } diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 528069415..02c1c69e3 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -45,7 +45,11 @@ public function socialLogin(array $data, array $options) ->contain(['Users']) ->first(); if (empty($existingAccount->user)) { + debug($data); + debug($options); $user = $this->_createSocialUser($data, $options); + debug($user); + die(); if (!empty($user->social_accounts[0])) { $existingAccount = $user->social_accounts[0]; } else { diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp index 52cc6086e..4ac0f9071 100644 --- a/src/Template/Users/social_email.ctp +++ b/src/Template/Users/social_email.ctp @@ -16,6 +16,7 @@ Form->input('email') ?> + User->addReCaptcha(); ?> Form->button(__d('Users', 'Submit')); ?> Form->end() ?>
From b7abe9b58e398f89908c1afb85cb9f2e8335bbcc Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 4 Dec 2015 12:45:40 -0500 Subject: [PATCH 0328/1476] Finish twitter implementation. Fix Instagram login --- composer.json | 3 +- src/Auth/Social/Mapper/AbstractMapper.php | 8 +-- src/Auth/Social/Mapper/Instagram.php | 6 +- src/Auth/Social/Mapper/Twitter.php | 16 +++++ src/Auth/SocialAuthenticate.php | 5 +- src/Controller/Traits/LoginTrait.php | 85 ++++++++++++----------- src/Model/Behavior/SocialBehavior.php | 5 +- src/Model/Entity/User.php | 1 + 8 files changed, 73 insertions(+), 56 deletions(-) diff --git a/composer.json b/composer.json index a3bd60a99..a4700bcee 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ }, "autoload-dev": { "psr-4": { - "CakeDC\\Users\\Test\\": "tests" + "CakeDC\\Users\\Test\\": "tests", + "CakeDC\\Users\\Test\\Fixture": "tests" } } } diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index f5febe6b4..b0706507f 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -90,11 +90,11 @@ protected function _map() } $result[$field] = $value; }); - $token = (array)Hash::get($this->_rawData, 'token'); + $token = Hash::get($this->_rawData, 'token'); $result['credentials'] = [ - 'token' => Hash::get($token, 'accessToken'), - 'secret' => Hash::get($token, 'tokenSecret'), - 'expires' => Hash::get($token, 'expires'), + 'token' => is_array($token) ? Hash::get($token, 'accessToken') : $token->getToken(), + 'secret' => is_array($token) ? Hash::get($token, 'tokenSecret') : null, + 'expires' => is_array($token) ? Hash::get($token, 'expires') : $token->getExpires(), ]; $result['raw'] = $this->_rawData; return $result; diff --git a/src/Auth/Social/Mapper/Instagram.php b/src/Auth/Social/Mapper/Instagram.php index c483c551e..0c89d26a3 100644 --- a/src/Auth/Social/Mapper/Instagram.php +++ b/src/Auth/Social/Mapper/Instagram.php @@ -22,10 +22,8 @@ class Instagram extends AbstractMapper * @var */ protected $_mapFields = [ - 'avatar' => 'data.profile_picture', - 'id' => 'data.id', - 'full_name' => 'data.full_name', - 'username' => 'data.username' + 'full_name' => 'full_name', + 'avatar' => 'profile_picture', ]; /** diff --git a/src/Auth/Social/Mapper/Twitter.php b/src/Auth/Social/Mapper/Twitter.php index 639190ab8..1fa6ad471 100644 --- a/src/Auth/Social/Mapper/Twitter.php +++ b/src/Auth/Social/Mapper/Twitter.php @@ -9,8 +9,16 @@ namespace CakeDC\Users\Auth\Social\Mapper; +use Cake\Utility\Hash; + class Twitter extends AbstractMapper { + + /** + * Url constants + */ + const TWITTER_BASE_URL = 'https://twitter.com/'; + /** * Map for provider fields * @var null @@ -26,4 +34,12 @@ class Twitter extends AbstractMapper 'bio' => 'description', 'validated' => 'validated' ]; + + /** + * @return string + */ + protected function _link() + { + return self::TWITTER_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); + } } \ No newline at end of file diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 1d8023db1..7c42c56b2 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -64,7 +64,8 @@ protected function _touch(array $data) if (empty($data['provider']) && !empty($this->_provider)) { $data['provider'] = SocialUtils::getProvider($this->_provider); } - $user = $User->socialLogin($data, $options); + + $user = $User->socialLogin($data, $options); } catch (UserNotActiveException $ex) { $exception = $ex; } catch (AccountNotActiveException $ex) { @@ -77,7 +78,7 @@ protected function _touch(array $data) $event = UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN; $args = ['exception' => $exception, 'rawData' => $data]; $event = $this->dispatchEvent($event, $args); - if ($data['provider'] == SocialAccountsTable::PROVIDER_TWITTER) { + if ($exception instanceof MissingEmailException && $data['provider'] == SocialAccountsTable::PROVIDER_TWITTER) { throw $exception; } return $event->result; diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 48b27fc88..caf05066d 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -31,66 +31,66 @@ trait LoginTrait public function twitterLogin() { $this->autoRender = false; - $server = new Twitter(array( - 'identifier' => 'ZqU9nNUsyuRkDJRLvPYPQ9YXI', - 'secret' => 'vZrxSe5c7DKEUROMpTUDjPu2Mepvvzucsk1ZSSYluRiNB4H5qN', - 'callbackUri' => 'http://local.woozk.xyz/auth/twitter', - )); -// $oauthToken = $this->request->query('oauth_token'); -// $oauthVerifier = $this->request->query('oauth_verifier'); -// if (!empty($oauthToken) && !empty($oauthVerifier)) { + + $server = new Twitter([ + 'identifier' => Configure::read('OAuth.providers.twitter.options.identifier'), + 'secret' => Configure::read('OAuth.providers.twitter.options.secret'), + 'callbackUri' => Configure::read('OAuth.providers.twitter.options.redirectUri'), + ]); + $oauthToken = $this->request->query('oauth_token'); + $oauthVerifier = $this->request->query('oauth_verifier'); + if (!empty($oauthToken) && !empty($oauthVerifier)) { $temporaryCredentials = $this->request->session()->read('temporary_credentials'); - //$tokenCredentials = $server->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); - $tokenCredentials = new \League\OAuth1\Client\Credentials\TokenCredentials(); - $tokenCredentials->setIdentifier('2165382168-o3THZG14a5t21k4CdkCmGhecu2MrZpPNx6rpflm'); - $tokenCredentials->setSecret('sX0CMhCzoaUPxlachfdAItdrkZAgltk5xy0Djbl1hfXaP'); - $user = (array)$server->getUserDetails($tokenCredentials); - $user['token'] = [ - 'accessToken' => $tokenCredentials->getIdentifier(), - 'tokenSecret' => $tokenCredentials->getSecret(), - ]; - $this->request->session()->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->session()->read(Configure::read('Users.Key.Session.social'))); - } -// } else { -// $temporaryCredentials = $server->getTemporaryCredentials(); -// $this->request->session()->write('temporary_credentials', $temporaryCredentials); -// $server->authorize($temporaryCredentials); -// } + $tokenCredentials = $server->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); + $user = (array)$server->getUserDetails($tokenCredentials); + $user['token'] = [ + 'accessToken' => $tokenCredentials->getIdentifier(), + 'tokenSecret' => $tokenCredentials->getSecret(), + ]; + $this->request->session()->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->session()->read(Configure::read('Users.Key.Session.social'))); + } + } else { + $temporaryCredentials = $server->getTemporaryCredentials(); + $this->request->session()->write('temporary_credentials', $temporaryCredentials); + $server->authorize($temporaryCredentials); + } return; } /** * @param $event */ public function failedSocialLoginListener(Event $event) { - $this->failedSocialLogin($event->data['exception'], $event->data['rawData']); + $this->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } /** * @param $exception * @param $data + * @param bool|false $flash * @return mixed */ - public function failedSocialLogin($exception, $data) + public function failedSocialLogin($exception, $data, $flash = false) { $msg = __d('Users', 'Issues trying to log in with your social account'); if (isset($exception) ) { if ($exception instanceof MissingEmailException) { - $this->Flash->success(__d('Users', 'Please enter your email')); + if ($flash) { + $this->Flash->success(__d('Users', 'Please enter your email')); + } $this->request->session()->write(Configure::read('Users.Key.Session.social'), $data); return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); - } if ($exception instanceof UserNotActiveException) { $msg = __d('Users', 'Your user has not been validated yet. Please check your inbox for instructions'); @@ -98,7 +98,10 @@ public function failedSocialLogin($exception, $data) $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); } } - $this->Flash->success($msg); + if ($flash) { + $this->request->session()->delete(Configure::read('Users.Key.Session.social')); + $this->Flash->success($msg); + } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 02c1c69e3..e939c2f94 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -45,11 +45,7 @@ public function socialLogin(array $data, array $options) ->contain(['Users']) ->first(); if (empty($existingAccount->user)) { - debug($data); - debug($options); $user = $this->_createSocialUser($data, $options); - debug($user); - die(); if (!empty($user->social_accounts[0])) { $existingAccount = $user->social_accounts[0]; } else { @@ -101,6 +97,7 @@ protected function _createSocialUser($data, $options = []) ->where([$this->_table->alias() . '.email' => $email]) ->first(); } + $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); $this->_table->isValidateEmail = $validateEmail; $result = $this->_table->save($user); diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index f33b5e51d..4e588032f 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -35,6 +35,7 @@ class User extends Entity 'confirm_password' => true, 'first_name' => true, 'last_name' => true, + 'avatar' => true, 'token' => true, 'token_expires' => true, 'api_token' => true, From f7ab5c42cac2cdd3f61d0b475b707bd509036a76 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Mon, 14 Dec 2015 11:19:16 -0430 Subject: [PATCH 0329/1476] Fixing unit tests after twitter integration changes --- config/bootstrap.php | 12 ++- src/Model/Behavior/RegisterBehavior.php | 1 + .../Controller/Traits/LoginTraitTest.php | 98 +++++++++---------- .../Model/Behavior/RegisterBehaviorTest.php | 5 - 4 files changed, 59 insertions(+), 57 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 38e79e6fa..28400af47 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -10,6 +10,8 @@ */ use Cake\Core\Configure; +use Cake\Log\Log; +use Cake\Core\Exception\MissingPluginException; use Cake\Core\Plugin; use Cake\Event\EventManager; use Cake\ORM\TableRegistry; @@ -23,7 +25,11 @@ Configure::write('Auth.authenticate.all.userModel', Configure::read('Users.table')); } -if (Configure::read('Users.Social.login')) { - Plugin::load('Muffin/OAuth2'); - EventManager::instance()->on(\CakeDC\Users\Controller\Component\UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, [new \CakeDC\Users\Controller\UsersController(), 'failedSocialLoginListener']); +if (Configure::read('Users.Social.login') && php_sapi_name() != 'cli') { + try { + Plugin::load('Muffin/OAuth2'); + 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()); + } } diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 87b4a77f1..3d065f7fe 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -109,6 +109,7 @@ public function activateUser(EntityInterface $user) throw new UserAlreadyActiveException(__d('Users', "User account already validated")); } $user->activation_date = new DateTime(); + $user->token_expires = null; $user->active = true; $result = $this->_table->save($user); diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index a3255fb4c..a8c1e12e3 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -62,12 +62,12 @@ public function testLoginHappy() { $this->_mockDispatchEvent(new Event('event')); $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); + ->setMethods(['is']) + ->getMock(); $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); + ->method('is') + ->with('post') + ->will($this->returnValue(true)); $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) ->disableOriginalConstructor() @@ -80,14 +80,14 @@ public function testLoginHappy() ->method('identify') ->will($this->returnValue($user)); $this->Trait->Auth->expects($this->at(1)) - ->method('setUser') - ->with($user); + ->method('setUser') + ->with($user); $this->Trait->Auth->expects($this->at(2)) ->method('redirectUrl') ->will($this->returnValue($redirectLoginOK)); $this->Trait->expects($this->once()) - ->method('redirect') - ->with($redirectLoginOK); + ->method('redirect') + ->with($redirectLoginOK); $this->Trait->login(); } @@ -100,12 +100,12 @@ public function testAfterIdentifyEmptyUser() { $this->_mockDispatchEvent(new Event('event')); $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); + ->setMethods(['is']) + ->getMock(); $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); + ->method('is') + ->with('post') + ->will($this->returnValue(true)); $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) ->disableOriginalConstructor() @@ -119,8 +119,8 @@ public function testAfterIdentifyEmptyUser() ->disableOriginalConstructor() ->getMock(); $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Username or password is incorrect', 'default', [], 'auth'); + ->method('error') + ->with('Username or password is incorrect', 'default', [], 'auth'); $this->Trait->login(); } @@ -135,12 +135,12 @@ public function testAfterIdentifyEmptyUserSocialLogin() ->setMethods(['dispatchEvent', 'redirect', '_isSocialLogin']) ->getMockForTrait(); $this->Trait->expects($this->any()) - ->method('_isSocialLogin') - ->will($this->returnValue(true)); + ->method('_isSocialLogin') + ->will($this->returnValue(true)); $this->_mockDispatchEvent(new Event('event')); $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); + ->setMethods(['is']) + ->getMock(); /*$this->Trait->request->expects($this->once()) ->method('is') ->with('post') @@ -150,9 +150,9 @@ public function testAfterIdentifyEmptyUserSocialLogin() ->disableOriginalConstructor() ->getMock(); $user = []; - /* $this->Trait->Auth->expects($this->once()) - ->method('identify') - ->will($this->returnValue($user));*/ + /* $this->Trait->Auth->expects($this->once()) + ->method('identify') + ->will($this->returnValue($user));*/ $this->Trait->expects($this->once()) ->method('redirect') @@ -176,27 +176,27 @@ public function testLoginBeforeLoginReturningArray() $event = new Event('event'); $event->result = $user; $this->Trait->expects($this->at(0)) - ->method('dispatchEvent') - ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) - ->will($this->returnValue($event)); + ->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'))); + ->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); + ->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); + ->method('redirect') + ->with($redirectLoginOK); $this->Trait->login(); } @@ -211,12 +211,12 @@ public function testLoginBeforeLoginReturningStoppedEvent() $event->result = '/'; $event->stopPropagation(); $this->Trait->expects($this->at(0)) - ->method('dispatchEvent') - ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) - ->will($this->returnValue($event)); + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) + ->will($this->returnValue($event)); $this->Trait->expects($this->once()) - ->method('redirect') - ->with('/'); + ->method('redirect') + ->with('/'); $this->Trait->login(); } @@ -235,9 +235,9 @@ public function testLoginGet() ->disableOriginalConstructor() ->getMock(); $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); + ->method('is') + ->with('post') + ->will($this->returnValue(false)); $this->Trait->login(); Configure::write('Users.Social.login', $socialLogin); } @@ -259,15 +259,15 @@ public function testLogout() ->method('logout') ->will($this->returnValue($redirectLogoutOK)); $this->Trait->expects($this->once()) - ->method('redirect') - ->with($redirectLogoutOK); + ->method('redirect') + ->with($redirectLogoutOK); $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') ->setMethods(['success']) ->disableOriginalConstructor() ->getMock(); $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('You\'ve successfully logged out'); + ->method('success') + ->with('You\'ve successfully logged out'); $this->Trait->logout(); } @@ -296,7 +296,7 @@ public function testFailedSocialLoginMissingEmail() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); - $this->Trait->failedSocialLogin($event); + $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } /** @@ -324,7 +324,7 @@ public function testFailedSocialUserNotActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Trait->failedSocialLogin($event); + $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } /** @@ -352,7 +352,7 @@ public function testFailedSocialUserAccountNotActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Trait->failedSocialLogin($event); + $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } @@ -380,6 +380,6 @@ public function testFailedSocialUserAccount() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Trait->failedSocialLogin($event); + $this->Trait->failedSocialLogin(null, $event->data['rawData'], true); } } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 5148525ce..e6d3657b3 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -255,7 +255,6 @@ public function testActiveUserRemoveValidationToken() { $user = $this->Table->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') - ->setMethods(['_removeValidationToken']) ->setConstructorArgs([$this->Table]) ->getMock(); @@ -263,10 +262,6 @@ public function testActiveUserRemoveValidationToken() $resultValidationToken->token_expires = null; $resultValidationToken->token = null; - $this->Behavior->expects($this->once()) - ->method('_removeValidationToken') - ->will($this->returnValue($resultValidationToken)); - $this->Behavior->activateUser($user); } } From f4377331d76d66a40e6348c4a93c880f9acfbb2a Mon Sep 17 00:00:00 2001 From: designway Date: Mon, 4 Jan 2016 14:25:53 +0100 Subject: [PATCH 0330/1476] Update AbstractMapper.php Social login by google, validate/active fields are always false. AbstractMapper.php the function _validated return false because email field is returned in a array. 'emails' => [ (int) 0 => [ 'value' => '...@...' ] And mapFields['email'] for google is emails.0.value, cant use !empty() for that. --- src/Auth/Social/Mapper/AbstractMapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index b0706507f..590a9fc84 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -71,7 +71,7 @@ public function __invoke() */ protected function _validated() { - return !empty($this->_rawData[$this->_mapFields['email']]); + return !empty(Hash::get($this->_rawData, $this->_mapFields['email'])); } /** From 1937249a10c82f79228c5db36de0d7ffd432e51e Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Wed, 6 Jan 2016 18:50:03 -0200 Subject: [PATCH 0331/1476] fixing composer.json Fixture namespace --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a4700bcee..4fe069456 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "autoload-dev": { "psr-4": { "CakeDC\\Users\\Test\\": "tests", - "CakeDC\\Users\\Test\\Fixture": "tests" + "CakeDC\\Users\\Test\\Fixture\\": "tests" } } } From 3748afd11639fdda0c56db1b139f931426e5713f Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Wed, 6 Jan 2016 19:21:02 -0200 Subject: [PATCH 0332/1476] fixing User::tokenExpired method --- src/Model/Entity/User.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 4e588032f..6dcbbd3e9 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -125,7 +125,12 @@ public function checkPassword($password, $hashedPassword) */ public function tokenExpired() { - return empty($this->token_expires) || strtotime($this->token_expires) < strtotime("now"); + if (empty($this->token_expires)) { + return true; + } + + $tokenExpiresTime = strtotime($this->token_expires->format("Y-m-d H:i")); + return $tokenExpiresTime < strtotime("now"); } /** From 9435f7bd29a40542651b00bf523cef61cf5eaa8e Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Wed, 6 Jan 2016 19:29:17 -0200 Subject: [PATCH 0333/1476] fixing User::tokenExpired method when token_expires is string --- src/Model/Entity/User.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 6dcbbd3e9..14a9b6426 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -129,8 +129,12 @@ public function tokenExpired() return true; } - $tokenExpiresTime = strtotime($this->token_expires->format("Y-m-d H:i")); - return $tokenExpiresTime < strtotime("now"); + $tokenExpiresTime = $this->token_expires; + if (is_object($this->token_expires)) { + $tokenExpiresTime = $this->token_expires->format("Y-m-d H:i"); + } + + return strtotime($tokenExpiresTime) < strtotime("now"); } /** From 64bcb3ad56d10a62f5d598bd51e0f2bb9d9696ac Mon Sep 17 00:00:00 2001 From: chav170 Date: Sun, 10 Jan 2016 16:41:29 +0000 Subject: [PATCH 0334/1476] refs #validation-messages-fix now the validation errors from patchEntity are displayed on the change password form --- src/Controller/Traits/PasswordManagementTrait.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index ed6008da7..b7045ce57 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -48,12 +48,16 @@ public function changePassword() if ($this->request->is('post')) { try { $user = $this->getUsersTable()->patchEntity($user, $this->request->data(), ['validate' => 'passwordConfirm']); - $user = $this->getUsersTable()->changePassword($user); - if ($user) { - $this->Flash->success(__d('Users', 'Password has been changed successfully')); - return $this->redirect($redirect); - } else { + if ($user->errors()) { $this->Flash->error(__d('Users', 'Password could not be changed')); + } else { + $user = $this->getUsersTable()->changePassword($user); + if ($user) { + $this->Flash->success(__d('Users', 'Password has been changed successfully')); + return $this->redirect($redirect); + } else { + $this->Flash->error(__d('Users', 'Password could not be changed')); + } } } catch (UserNotFoundException $exception) { $this->Flash->error(__d('Users', 'User was not found')); From dfa62299dfc2465c6612c97f6e4a41355c133ac6 Mon Sep 17 00:00:00 2001 From: chav170 Date: Sun, 10 Jan 2016 16:50:12 +0000 Subject: [PATCH 0335/1476] refs #validation-messages-fix fixed double validation error message per field email and username --- src/Model/Table/UsersTable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index ca088f1e2..f36a9b3e1 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -151,13 +151,13 @@ public function validationRegister(Validator $validator) */ public function buildRules(RulesChecker $rules) { - $rules->add($rules->isUnique(['username']), [ + $rules->add($rules->isUnique(['username']), '_isUnique', [ 'errorField' => 'username', 'message' => __d('Users', 'Username already exists') ]); if ($this->isValidateEmail) { - $rules->add($rules->isUnique(['email']), [ + $rules->add($rules->isUnique(['email']), '_isUnique', [ 'errorField' => 'email', 'message' => __d('Users', 'Email already exists') ]); From 6693068ecedd3b664e971191916a4b14abe36e5b Mon Sep 17 00:00:00 2001 From: Ayman Alkom Date: Wed, 13 Jan 2016 12:10:10 +0200 Subject: [PATCH 0336/1476] Update LoginTrait.php --- src/Controller/Traits/LoginTrait.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index afde464af..984dd09db 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -42,6 +42,11 @@ public function login() $socialLogin = $this->_isSocialLogin(); if (!$this->request->is('post') && !$socialLogin) { + if ($this->Auth->user()) { + $msg = __d('Users', 'Your are already logged in'); + $this->Flash->error($msg); + return $this->redirect($this->referer()); + } return; } From 0aebf2ec17b8877eaffec7df3442a28cb78378f8 Mon Sep 17 00:00:00 2001 From: Ayman Alkom Date: Thu, 14 Jan 2016 14:03:20 +0200 Subject: [PATCH 0337/1476] Update LoginTraitTest.php --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 88bac68f5..5af8f865f 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -326,6 +326,10 @@ 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() From 97cf2e0eb66329f3d2ab5e30a268777def4c37f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 14 Jan 2016 13:05:41 +0000 Subject: [PATCH 0338/1476] update php version for coveralls --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b9669e624..cc347134b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,10 +20,10 @@ matrix: fast_finish: true include: - - php: 5.4 + - php: 5.5 env: PHPCS=1 DEFAULT=0 - - php: 5.4 + - php: 5.5 env: COVERALLS=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' before_script: From 5ed0a325edf0069f56d61c204a3b1f4a6e948f76 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 20 Jan 2016 19:29:39 -0430 Subject: [PATCH 0339/1476] Adding unit tests to SocialAuthenticate, SocialBehavior and UsersHelper. Refactoring where needed --- src/Auth/SocialAuthenticate.php | 75 ++- src/Exception/MissingProviderException.php | 18 + src/Model/Behavior/SocialBehavior.php | 6 +- src/View/Helper/UserHelper.php | 5 +- .../TestCase/Auth/SocialAuthenticateTest.php | 484 ++++++++++++++++++ .../Model/Behavior/SocialBehaviorTest.php | 363 +++++++++++++ tests/TestCase/Shell/UsersShellTest.php | 24 +- tests/TestCase/View/Helper/UserHelperTest.php | 25 + 8 files changed, 973 insertions(+), 27 deletions(-) create mode 100644 src/Exception/MissingProviderException.php create mode 100644 tests/TestCase/Auth/SocialAuthenticateTest.php create mode 100644 tests/TestCase/Model/Behavior/SocialBehaviorTest.php diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 7c42c56b2..29c43ba85 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -21,6 +21,7 @@ use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Exception\MissingProviderException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Model\Table\SocialAccountsTable; use Muffin\OAuth2\Auth\OAuthAuthenticate; @@ -50,22 +51,15 @@ public function __construct(ComponentRegistry $registry, array $config = []) * Find or create local user * @param array $data * @return array|bool|mixed + * @throws MissingEmailException */ protected function _touch(array $data) { - $userModel = Configure::read('Users.table'); - $User = TableRegistry::get($userModel); - $options = [ - 'use_email' => Configure::read('Users.Email.required'), - 'validate_email' => Configure::read('Users.Email.validate'), - 'token_expiration' => Configure::read('Users.Token.expiration') - ]; try { if (empty($data['provider']) && !empty($this->_provider)) { $data['provider'] = SocialUtils::getProvider($this->_provider); } - - $user = $User->socialLogin($data, $options); + $user = $this->_socialLogin($data); } catch (UserNotActiveException $ex) { $exception = $ex; } catch (AccountNotActiveException $ex) { @@ -113,16 +107,9 @@ public function getUser(Request $request) if (empty($rawData)) { $rawData = $data; } - if (!is_null($this->_provider)) { - $provider = SocialUtils::getProvider($this->_provider); - } else { - $provider = ucfirst($request->param('provider')); - } - $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; - $providerMapper = new $providerMapperClass($rawData); - $user = $providerMapper(); - $user['provider'] = $provider; + $provider = $this->_getProviderName($request); + $user = $this->_mapUser($provider, $rawData); } if (!$user || !$this->config('userModel')) { @@ -132,7 +119,57 @@ public function getUser(Request $request) if (!$result = $this->_touch($user)) { return false; } - return $result; } + + /** + * Get the provider name based on the request or on the provider set. + * + * @param \Cake\Network\Request $request Request object. + * @return mixed Either false or an array of user information + */ + protected function _getProviderName($request = null) + { + $provider = false; + if (!is_null($this->_provider)) { + $provider = SocialUtils::getProvider($this->_provider); + } else if (!empty($request)){ + $provider = ucfirst($request->param('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('Users', "Provider cannot be empty")); + } + $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; + $providerMapper = new $providerMapperClass($data); + $user = $providerMapper(); + $user['provider'] = $provider; + return $user; + } + + 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; + } } diff --git a/src/Exception/MissingProviderException.php b/src/Exception/MissingProviderException.php new file mode 100644 index 000000000..dc25ed0e8 --- /dev/null +++ b/src/Exception/MissingProviderException.php @@ -0,0 +1,18 @@ +generateUniqueUsername(Hash::get($userData, 'username')); - if ($useEmail) { $userData['email'] = Hash::get($data, 'email'); if (empty(Hash::get($data, 'validated'))) { $accountData['active'] = false; } } + $userData['password'] = $this->randomString(); $userData['avatar'] = Hash::get($data, 'avatar'); $userData['validated'] = !empty(Hash::get($data, 'validated')); - $userData['tos_date'] = date("Y-m-d H:i:s"); + $userData['tos_date'] = date("Y-m-d H:i:s"); $userData['gender'] = Hash::get($data, 'gender'); //$userData['timezone'] = Hash::get($data, 'timezone'); $userData['social_accounts'][] = $accountData; diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 8bb4a3a14..1dd5a4e7e 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -11,11 +11,11 @@ namespace CakeDC\Users\View\Helper; -use Cake\Utility\Inflector; 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; /** @@ -133,9 +133,10 @@ public function addReCaptchaScript() */ public function addReCaptcha() { - if (!Configure::check('Users.Registration.reCaptcha')) { + if (!Configure::read('Users.Registration.reCaptcha')) { return false; } + $this->Form->unlockField('g-recaptcha-response'); return $this->Html->tag('div', '', [ 'class' => 'g-recaptcha', diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php new file mode 100644 index 000000000..cbdb3c9c2 --- /dev/null +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -0,0 +1,484 @@ +Table = TableRegistry::get('CakeDC/Users.Users'); + + $this->Token = $this->getMockBuilder('AccessToken') + ->setMethods(['getToken', 'getExpires']) + ->disableOriginalConstructor() + ->getMock(); + + $this->controller = $this->getMock( + 'Cake\Controller\Controller', + null, + [$request, $response] + ); + $this->Request = $request; + $this->Registry = new ComponentRegistry($this->controller); + + $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') + ->setMethods(['_authenticate', '_getProviderName', '_mapUser', '_socialLogin', 'dispatchEvent']) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * 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); + } + + /** + * Test getUser + * + * @dataProvider providerGetUser + */ + public function testGetUserAuth($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)); + + $user = $this->Table->get('00000000-0000-0000-0000-000000000002'); + $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->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') + ->setMethods(['_authenticate', '_getProviderName', '_mapUser', '_touch']) + ->disableOriginalConstructor() + ->getMock(); + + $session = $this->getMock('Cake\Network\Session', ['read', 'delete']); + $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->getMock('Cake\Network\Request', ['session']); + $this->Request->expects($this->any()) + ->method('session') + ->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'))); + + $event = new Event('ExceptionEvent'); + $event->result = 'result'; + + $this->SocialAuthenticate->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + + $result = $this->SocialAuthenticate->getUser($this->Request); + $this->assertEquals($result, 'result'); + } + + /** + * 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'))); + + $event = new Event('ExceptionEvent'); + $event->result = 'result'; + + $this->SocialAuthenticate->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + + $result = $this->SocialAuthenticate->getUser($this->Request); + $this->assertEquals($result, 'result'); + } + + /** + * 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'))); + + $event = new Event('ExceptionEvent'); + $event->result = 'result'; + + $this->SocialAuthenticate->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + + $result = $this->SocialAuthenticate->getUser($this->Request); + $this->assertEquals($result, 'result'); + } + + /** + * Test getUser + * + * @dataProvider providerTwitter + * @expectedException CakeDC\Users\Exception\MissingEmailException + */ + 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->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') + ->disableOriginalConstructor() + ->getMock(); + $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->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') + ->disableOriginalConstructor() + ->getMock(); + + $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($result, $mappedData); + } + + /** + * 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=normal', + '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->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') + ->disableOriginalConstructor() + ->getMock(); + + $reflectedClass = new ReflectionClass($this->SocialAuthenticate); + $mapUser = $reflectedClass->getMethod('_mapUser'); + $mapUser->setAccessible(true); + $mapUser->invoke($this->SocialAuthenticate, null, $data); + } + +} diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php new file mode 100644 index 000000000..83cbb908a --- /dev/null +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -0,0 +1,363 @@ +Table = $this->getMockForModel('CakeDC/Users.Users', ['save']); + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialBehavior') + ->setMethods(['randomString', '_updateActive', 'generateUniqueUsername']) + ->setConstructorArgs([$this->Table]) + ->getMock(); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->Table, $this->Behavior, $this->Email); + parent::tearDown(); + } + + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerFacebookSocialLogin + */ + public function testSocialLoginFacebookProvider($data, $options, $dataUser) + { + $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); + $user->password = '$2y$10$0QzszaIEpW1pYpoKJVf4DeqEAHtg9whiLTX/l3TcHAoOLF1bC9U.6'; + + $this->Behavior->expects($this->once()) + ->method('generateUniqueUsername') + ->with('email') + ->will($this->returnValue('username')); + + $this->Behavior->expects($this->once()) + ->method('randomString') + ->will($this->returnValue('password')); + + $this->Behavior->expects($this->once()) + ->method('_updateActive') + ->will($this->returnValue($user)); + + $this->Table->expects($this->once()) + ->method('save') + ->with($user) + ->will($this->returnValue($user)); + + $result = $this->Behavior->socialLogin($data, $options); + $this->assertEquals($result, $user); + } + + /** + * Provider for socialLogin with facebook and not existing user + * + */ + public function providerFacebookSocialLogin() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'facebook-id', + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'raw' => [ + 'id' => '10153521527396318', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + 'result' => [ + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'username' => 'username', + 'email' => 'email@example.com', + 'password' => '$2y$10$oLPxCkKJ1TUCR6xJ1t0Wj.7Fznx49Wn4NZB2aJCmVvRMucaHuNyyO', + 'avatar' => null, + 'tos_date' => '2016-01-20 15:45:09', + 'gender' => null, + 'social_accounts' => [ + [ + 'provider' => 'Facebook', + 'username' => null, + 'reference' => '10153521527396318', + 'avatar' => '', + 'link' => 'facebook-link', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => '2016-03-19 21:41:22', + 'data' => '-', + 'active' => true + ] + ], + 'activation_date' => '2016-01-20 15:45:09', + 'active' => true, + ] + ] + + ]; + + } + + /** + * Test socialLogin with facebook with existing and active user + * + * @dataProvider providerFacebookSocialLoginExistingReference + */ + public function testSocialLoginExistingReference($data, $options) + { + $this->Behavior->expects($this->never()) + ->method('generateUniqueUsername'); + + $this->Behavior->expects($this->never()) + ->method('randomString'); + + $this->Behavior->expects($this->never()) + ->method('_updateActive'); + + $result = $this->Behavior->socialLogin($data, $options); + $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); + $this->assertTrue($result->active); + + } + + /** + * Provider for socialLogin with facebook with existing and active user + * + */ + public function providerFacebookSocialLoginExistingReference() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-2-1', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with existing and active user and not active social account + * + * @expectedException CakeDC\Users\Exception\AccountNotActiveException + * @dataProvider providerSocialLoginExistingAndNotActiveAccount + */ + public function testSocialLoginExistingNotActiveReference($data, $options) + { + + $this->Behavior->expects($this->never()) + ->method('generateUniqueUsername'); + + $this->Behavior->expects($this->never()) + ->method('randomString'); + + $this->Behavior->expects($this->never()) + ->method('_updateActive'); + $this->Behavior->socialLogin($data, $options); + + } + + /** + * Provider for socialLogin with existing and active user and not active social account + * + */ + public function providerSocialLoginExistingAndNotActiveAccount() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-1-1234', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with existing and active account but not active user + * + * @expectedException CakeDC\Users\Exception\UserNotActiveException + * @dataProvider providerSocialLoginExistingAccountNotActiveUser + */ + public function testSocialLoginExistingReferenceNotActiveUser($data, $options) + { + + $this->Behavior->expects($this->never()) + ->method('generateUniqueUsername'); + + $this->Behavior->expects($this->never()) + ->method('randomString'); + + $this->Behavior->expects($this->never()) + ->method('_updateActive'); + $this->Behavior->socialLogin($data, $options); + + } + + /** + * Provider for socialLogin with existing and active account but not active user + * + */ + public function providerSocialLoginExistingAccountNotActiveUser() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-1-1234', + 'provider' => 'Twitter' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerFacebookSocialLoginNoEmail + * @expectedException CakeDC\Users\Exception\MissingEmailException + */ + public function testSocialLoginNoEmail($data, $options) + { + $result = $this->Behavior->socialLogin($data, $options); + } + + + /** + * Provider for socialLogin with facebook and not existing user + * + */ + public function providerFacebookSocialLoginNoEmail() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'facebook-id', + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'validated' => true, + 'link' => 'facebook-link', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerGenerateUsername + */ + public function testGenerateUniqueUsername($param, $expected) + { + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialBehavior') + ->setMethods(['randomString', '_updateActive']) + ->setConstructorArgs([$this->Table]) + ->getMock(); + + $result = $this->Behavior->generateUniqueUsername($param); + $this->assertEquals($expected, $result); + } + + /** + * Provider for socialLogin with facebook and not existing user + * + */ + public function providerGenerateUsername() + { + return [ + ['username', 'username'], + ['user-1', 'user-10'], + ['user-5', 'user-50'] + + ]; + } + +} diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 2980a2dce..f773beb99 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -36,12 +36,12 @@ public function setUp() { parent::setUp(); $this->out = new ConsoleOutput(); - $this->io = new ConsoleIo($this->out); + $this->io = $this->getMock('Cake\Console\ConsoleIo'); $this->Users = TableRegistry::get('CakeDC/Users.Users'); $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', - '_generateRandomUsername', '_generatedHashedPassword', 'error']) + '_generateRandomUsername', '_generatedHashedPassword', 'error', '_updateUser']) ->setConstructorArgs([$this->io]) ->getMock(); @@ -108,8 +108,6 @@ public function testAddUser() ->with($entityUser) ->will($this->returnValue($userSaved)); - //TODO: Add assertions with 'out' - $this->Shell->runCommand(['addUser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email']]); } @@ -234,4 +232,22 @@ public function testResetAllPasswordsNoPassingParams() $this->Shell->runCommand(['resetAllPasswords']); } + + /** + * Reset password + * + * @return void + */ + public function testResetPassword() + { + $user = $this->Users->newEntity(); + $user->username = 'user-1'; + $user->password = 'password'; + + $this->Shell->expects($this->once()) + ->method('_updateUser') + ->will($this->returnValue($user)); + + $this->Shell->runCommand(['resetPassword', 'user-1', 'password']); + } } diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 249406620..7c8a36e36 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -187,6 +187,17 @@ public function testAddReCaptcha() Configure::write('reCaptcha.key', $siteKey); } + /** + * Test add ReCaptcha field + * + * @return void + */ + public function testAddReCaptchaEmpty() + { + Configure::write('Users.Registration.reCaptcha', false); + $result = $this->User->addReCaptcha(); + $this->assertFalse($result); + } /** * Test add ReCaptcha field @@ -200,4 +211,18 @@ public function testAddReCaptchaScript() ->with('script', $this->stringContains('https://www.google.com/recaptcha/api.js')); $this->User->addReCaptchaScript(); } + + /** + * Test social login link + * + * @return void + */ + public function testSocialLoginLink() + { + $result = $this->User->socialLogin('facebook'); + $this->assertEquals('Sign in with Facebook', $result); + + $result = $this->User->socialLogin('twitter', ['label' => 'Register with']); + $this->assertEquals('Register with Twitter', $result); + } } From 93d4082822d6f64f120d05d2b7af9c957d7688ee Mon Sep 17 00:00:00 2001 From: Andy Carter Date: Thu, 28 Jan 2016 19:19:22 +0000 Subject: [PATCH 0340/1476] Route prefix should be set to false by default Fixes #28. --- config/users.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index d332eade8..2921d5c1c 100644 --- a/config/users.php +++ b/config/users.php @@ -86,6 +86,7 @@ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', + 'prefix' => false ], 'authenticate' => [ 'all' => [ @@ -100,7 +101,7 @@ ], ], 'OAuth' => [ - 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin'], + 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => false], 'providers' => [ 'facebook' => [ 'className' => 'League\OAuth2\Client\Provider\Facebook', From 4d26db4ce4c4b340a444119637dd1715f3d94b78 Mon Sep 17 00:00:00 2001 From: Chris Mielke Date: Fri, 29 Jan 2016 10:14:46 -0800 Subject: [PATCH 0341/1476] Add setup instructions for UserHelper --- Docs/Documentation/UserHelper.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md index 9abfce96d..062b8111e 100644 --- a/Docs/Documentation/UserHelper.md +++ b/Docs/Documentation/UserHelper.md @@ -6,7 +6,17 @@ The User Helper has some methods that may be needed if you want to improve your Setup --------------- -The User Helper just need some Configure variables to function properly. +Enable the Helper in `src/view/AppView.php`: +```php +class AppView extends View +{ + public function initialize() + { + parent::initialize(); + $this->loadHelper('CakeDC/Users.User'); + } +} +``` Social Login ----------------- @@ -62,4 +72,4 @@ $this->User->addReCaptchaScript(); $this->User->addReCaptcha(); ``` -Note that the script is added automatically if the feature is enabled in config. \ No newline at end of file +Note that the script is added automatically if the feature is enabled in config. From c9c39f7e4b9c00db23e35790da0089aca8766d4e Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sun, 31 Jan 2016 15:38:19 +0000 Subject: [PATCH 0342/1476] add required lib for testing --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 4fe069456..70781da3f 100644 --- a/composer.json +++ b/composer.json @@ -7,10 +7,10 @@ "cakephp/cakephp": "3.1.*" }, "require-dev": { - "phpunit/phpunit": "*" + "phpunit/phpunit": "*", + "muffin/oauth2": "dev-master" }, "suggest": { - "muffin/oauth2": "Provide Social Authentication", "league/oauth2-facebook": "Provide Social Authentication with Facebook", "league/oauth2-instagram": "Provide Social Authentication with Instagram", "google/recaptcha": "Provide reCAPTCHA validation for registration form" From 1d4a28164cb8408e130f8b310f510ef8368e345e Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Sun, 31 Jan 2016 15:38:19 +0000 Subject: [PATCH 0343/1476] add required lib for testing --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4fe069456..c36114d7c 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,8 @@ "cakephp/cakephp": "3.1.*" }, "require-dev": { - "phpunit/phpunit": "*" + "phpunit/phpunit": "*", + "muffin/oauth2": "dev-master" }, "suggest": { "muffin/oauth2": "Provide Social Authentication", From 4cc3ed4afc37bbf96b391a2f20bc25691aeb8bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 1 Feb 2016 10:51:53 +0000 Subject: [PATCH 0344/1476] fix return value in write context --- src/Model/Behavior/SocialBehavior.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index a6d187e87..63533f1ec 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -137,6 +137,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail } $accountData['data'] = serialize(Hash::get($data, 'raw')); $accountData['active'] = true; + $dataValidated = Hash::get($data, 'validated'); if (empty($existingUser)) { @@ -154,8 +155,9 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['username'] = Hash::get($data, 'username'); $username = Hash::get($userData, 'username'); if (empty($username)) { - if (!empty(Hash::get($data, 'email'))) { - $email = explode('@', Hash::get($data, 'email')); + $dataEmail = Hash::get($data, 'email'); + if (!empty($dataEmail)) { + $email = explode('@', $dataEmail); $userData['username'] = Hash::get($email, 0); } else { $firstName = Hash::get($userData, 'first_name'); @@ -167,14 +169,14 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); if ($useEmail) { $userData['email'] = Hash::get($data, 'email'); - if (empty(Hash::get($data, 'validated'))) { + if (empty($dataValidated)) { $accountData['active'] = false; } } $userData['password'] = $this->randomString(); $userData['avatar'] = Hash::get($data, 'avatar'); - $userData['validated'] = !empty(Hash::get($data, 'validated')); + $userData['validated'] = !empty($dataValidated); $userData['tos_date'] = date("Y-m-d H:i:s"); $userData['gender'] = Hash::get($data, 'gender'); //$userData['timezone'] = Hash::get($data, 'timezone'); @@ -182,7 +184,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $user = $this->_table->newEntity($userData, ['associated' => ['SocialAccounts']]); $user = $this->_updateActive($user, false, $tokenExpiration); } else { - if ($useEmail && empty(Hash::get($data, 'validated'))) { + if ($useEmail && empty($dataValidated)) { $accountData['active'] = false; } $user = $this->_table->patchEntity($existingUser, [ From aea0c1b9483afab0571e9372369f61f7a088f197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 1 Feb 2016 17:28:52 +0000 Subject: [PATCH 0345/1476] fix empty return values in 5.4 --- src/Auth/SocialAuthenticate.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 29c43ba85..eb526764f 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -94,9 +94,10 @@ protected function _touch(array $data) public function getUser(Request $request) { $data = $request->session()->read(Configure::read('Users.Key.Session.social')); - if (!empty($data) && (!empty($data['email'] || !empty($request->data('email'))))) { - if (!empty($request->data('email'))) { - $data['email'] = $request->data('email'); + $requestDataEmail = $request->data('email'); + if (!empty($data) && (!empty($data['email']) || !empty($requestDataEmail))) { + if (!empty($requestDataEmail)) { + $data['email'] = $requestDataEmail; } $user = $data; $request->session()->delete(Configure::read('Users.Key.Session.social')); From 185b7524b0027b2161038873a960c00502b44da8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 1 Feb 2016 17:45:04 +0000 Subject: [PATCH 0346/1476] fix empty return values in 5.4 --- src/Auth/Social/Mapper/AbstractMapper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index 590a9fc84..136179b53 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -71,7 +71,8 @@ public function __invoke() */ protected function _validated() { - return !empty(Hash::get($this->_rawData, $this->_mapFields['email'])); + $email = Hash::get($this->_rawData, $this->_mapFields['email']); + return !empty($email); } /** From 7adf8a035cf9569deda6bbe177805e248f821953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 1 Feb 2016 17:52:46 +0000 Subject: [PATCH 0347/1476] fix travis php version for coveralls --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b9669e624..cc347134b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,10 +20,10 @@ matrix: fast_finish: true include: - - php: 5.4 + - php: 5.5 env: PHPCS=1 DEFAULT=0 - - php: 5.4 + - php: 5.5 env: COVERALLS=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' before_script: From 336556cced58784c53a995fef1f4fd89f5ae50d2 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 2 Feb 2016 09:34:46 -0500 Subject: [PATCH 0348/1476] Fixing typos --- src/Auth/SimpleRbacAuthorize.php | 2 +- src/Locale/Users.pot | 2 +- src/Model/Behavior/Behavior.php | 2 +- src/Template/Email/html/validation.ctp | 2 +- src/View/Helper/UserHelper.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 5847e5e15..03bcaf3fc 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -168,7 +168,7 @@ public function authorize($user, Request $request) * @param array $user current user array * @param string $role effective role for the current user * @param Request $request request - * @return bool true if there is a match in permissisons + * @return bool true if there is a match in permissions */ protected function _checkRules(array $user, $role, Request $request) { diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 79f386803..551c6cda2 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -270,7 +270,7 @@ 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 correcly displayed, please copy the following address in your web browser {0}" +msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" msgstr "" #: Template/Email/html/reset_password.ctp:30 diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index d0307d980..32e6d2aba 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -23,7 +23,7 @@ class Behavior extends BaseBehavior { /** - * Send the templated email to the user + * Send the template email to the user * * @param EntityInterface $user User entity * @param string $subject Subject, note the first_name of the user will be prepended if exists diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index dbdc2fe4f..df1dc3fe2 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -24,7 +24,7 @@ $activationUrl = [ Html->link(__d('Users', 'Activate your account here'), $activationUrl) ?>

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

, diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 1dd5a4e7e..843cf2531 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -34,7 +34,7 @@ class UserHelper extends Helper protected $_defaultConfig = []; /** - * beforeLayou callback loads reCaptcha if enabled + * beforeLayout callback loads reCaptcha if enabled * * @param Event $event event * @return void From 8e7a7bcf33bcaeb47ea43c0d91596c0b5825f5b9 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 2 Feb 2016 09:39:05 -0500 Subject: [PATCH 0349/1476] Adding necessary @throws tags to comment blocks --- src/Controller/Traits/LoginTrait.php | 3 +++ src/Controller/Traits/RegisterTrait.php | 1 + src/Model/Behavior/PasswordBehavior.php | 1 + src/Model/Behavior/SocialBehavior.php | 3 +++ 4 files changed, 8 insertions(+) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index caf05066d..9fc519a90 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -106,6 +106,9 @@ public function failedSocialLogin($exception, $data, $flash = false) } /** + * Social login + * + * @throws NotFoundException * @return array */ public function socialLogin() diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index b572b6811..5c3b0293b 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -30,6 +30,7 @@ trait RegisterTrait /** * Register a new user * + * @throws NotFoundException * @return type */ public function register() diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index fc87c150d..03c0bc6ec 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -105,6 +105,7 @@ public function sendResetPasswordEmail(EntityInterface $user, Email $email = nul * Change password method * * @param EntityInterface $user user data. + * @throws WrongPasswordException * @return mixed */ public function changePassword(EntityInterface $user) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 63533f1ec..9b8d5d33c 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -35,6 +35,9 @@ class SocialBehavior extends Behavior * * @param array $data Array social login. * @param array $options Array option data. + * @throws InvalidArgumentException + * @throws UserNotActiveException + * @throws AccountNotActiveException * @return bool|EntityInterface|mixed */ public function socialLogin(array $data, array $options) From 94f808f2f5489b7d29891f5fb99636d9779d3340 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 2 Feb 2016 09:44:24 -0500 Subject: [PATCH 0350/1476] Fixing comment to make it match with the method signature --- src/Model/Behavior/Behavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index 32e6d2aba..95764a8d9 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -87,7 +87,7 @@ protected function _updateActive(EntityInterface $user, $validateEmail, $tokenEx /** * Remove user token for validation * - * @param User $user user object. + * @param EntityInterface $user user object. * @return EntityInterface */ protected function _removeValidationToken(EntityInterface $user) From 1f79fc633d5038ac25360d758e1e5571732b4e90 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 2 Feb 2016 10:03:19 -0500 Subject: [PATCH 0351/1476] Fixed param type in comment block --- src/Model/Behavior/Behavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index 95764a8d9..26226c29c 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -66,7 +66,7 @@ protected function _getEmailInstance(Email $email = null) * DRY for update active and token based on validateEmail flag * * @param EntityInterface $user User to be updated. - * @param type $validateEmail email user to validate. + * @param bool $validateEmail email user to validate. * @param type $tokenExpiration token to be updated. * @return EntityInterface */ From 10c9fa84421c01cec9ac87144bebe8672db95cb2 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 2 Feb 2016 10:30:41 -0500 Subject: [PATCH 0352/1476] Removed unused references --- src/Auth/SocialAuthenticate.php | 2 -- src/Controller/Component/RememberMeComponent.php | 1 - src/Controller/Traits/LoginTrait.php | 1 - src/Controller/Traits/RegisterTrait.php | 1 - src/Controller/Traits/SimpleCrudTrait.php | 1 - src/Controller/Traits/UserValidationTrait.php | 1 - src/Model/Behavior/RegisterBehavior.php | 1 - src/Model/Behavior/SocialAccountBehavior.php | 4 ---- src/Model/Entity/User.php | 1 - src/Model/Table/SocialAccountsTable.php | 8 -------- src/Model/Table/UsersTable.php | 4 ---- 11 files changed, 25 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index eb526764f..b618b5e07 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -13,8 +13,6 @@ use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; -use Cake\Error\Debugger; -use Cake\Log\Log; use Cake\Network\Request; use Cake\ORM\TableRegistry; use CakeDC\Users\Auth\Social\Util\SocialUtils; diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 1293b1ede..488fa272f 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -14,7 +14,6 @@ use Cake\Controller\Component; use Cake\Core\Configure; use Cake\Event\Event; -use Cake\ORM\TableRegistry; use Cake\Utility\Security; use InvalidArgumentException; diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 9fc519a90..db5d32e37 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -17,7 +17,6 @@ use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use Cake\Core\Configure; -use Cake\Utility\Hash; use CakeDC\Users\Exception\UserNotActiveException; use League\OAuth1\Client\Server\Twitter; diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 5c3b0293b..a6a832870 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -16,7 +16,6 @@ use Cake\Datasource\EntityInterface; use Cake\Network\Exception\NotFoundException; use Cake\Network\Response; -use InvalidArgumentException; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index 34b0b7634..63fd75b72 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -13,7 +13,6 @@ use Cake\Network\Exception\NotFoundException; use Cake\Network\Response; -use Cake\ORM\TableRegistry; use Cake\Utility\Inflector; /** diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 5a24003e8..74836e61a 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -17,7 +17,6 @@ use Cake\Core\Configure; use Cake\Network\Response; use Exception; -use InvalidArgumentException; /** * Covers the user validation diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 3d065f7fe..4f8f33d56 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -14,7 +14,6 @@ use CakeDC\Users\Exception\TokenExpiredException; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; -use CakeDC\Users\Model\Behavior\Behavior; use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 8b37502b2..0f7a7d18a 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -13,9 +13,6 @@ use ArrayObject; use CakeDC\Users\Exception\AccountAlreadyActiveException; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Model\Behavior\Behavior; use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; @@ -23,7 +20,6 @@ use Cake\Event\Event; use Cake\Mailer\Email; use Cake\ORM\Entity; -use InvalidArgumentException; /** * Covers social account features diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 14a9b6426..5e3a4c15d 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Model\Entity; -use Cake\Auth\DefaultPasswordHasher; use Cake\Core\Configure; use Cake\ORM\Entity; use Cake\Utility\Text; diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index dc06716d2..f753d0e81 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -11,15 +11,7 @@ namespace CakeDC\Users\Model\Table; -use ArrayObject; -use CakeDC\Users\Exception\AccountAlreadyActiveException; -use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; -use Cake\Datasource\EntityInterface; -use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\Event\Event; -use Cake\Mailer\Email; -use Cake\ORM\Entity; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 984628e5d..1314f173a 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -11,10 +11,6 @@ namespace CakeDC\Users\Model\Table; -use CakeDC\Users\Exception\WrongPasswordException; -use CakeDC\Users\Model\Entity\User; -use Cake\Datasource\EntityInterface; -use Cake\Mailer\Email; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Utility\Hash; From 021a2e83053d2d4ad0afb2da9922b06bdd80b3e7 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 2 Feb 2016 10:33:45 -0500 Subject: [PATCH 0353/1476] Removed commented code --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 8 -------- tests/TestCase/Model/Behavior/SocialBehaviorTest.php | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index a8c1e12e3..e2ca3f370 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -141,18 +141,10 @@ public function testAfterIdentifyEmptyUserSocialLogin() $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') ->setMethods(['is']) ->getMock(); - /*$this->Trait->request->expects($this->once()) - ->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->expects($this->once()) ->method('redirect') diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php index 83cbb908a..600b49465 100644 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -298,7 +298,7 @@ public function providerSocialLoginExistingAccountNotActiveUser() */ public function testSocialLoginNoEmail($data, $options) { - $result = $this->Behavior->socialLogin($data, $options); + $this->Behavior->socialLogin($data, $options); } From 8a56fab75a363374f6b6af5f78184be0916ed551 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 2 Feb 2016 10:54:27 -0500 Subject: [PATCH 0354/1476] phpcs fixes --- src/Auth/Social/Mapper/AbstractMapper.php | 18 ++++++++++++++---- src/Auth/Social/Mapper/Facebook.php | 13 +++++++++++++ src/Auth/Social/Mapper/Google.php | 15 +++++++++++---- src/Auth/Social/Mapper/Instagram.php | 15 +++++++++++---- src/Auth/Social/Mapper/LinkedIn.php | 11 +++++++---- src/Auth/Social/Mapper/Twitter.php | 16 +++++++++++----- src/Auth/Social/Util/SocialUtils.php | 16 ++++++++++++---- src/Template/Users/change_password.ctp | 6 +++++- 8 files changed, 84 insertions(+), 26 deletions(-) diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index 136179b53..7c307e354 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -1,15 +1,22 @@ - Form->input('current_password', ['type' => 'password', 'required' => true, 'label' => __d('Users', 'Current password')]); ?> + Form->input('current_password', [ + 'type' => 'password', + 'required' => true, + 'label' => __d('Users', 'Current password')]); + ?> Form->input('password'); ?> Form->input('password_confirm', ['type' => 'password', 'required' => true]); ?> From 18166ffbfc5bcd60ac47975fcc374a320a6e0577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 5 Feb 2016 14:24:11 +0000 Subject: [PATCH 0355/1476] update composer requirements --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4fe069456..349fb7a37 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "cakephp-plugin", "require": { "php": ">=5.4.16", - "cakephp/cakephp": "3.1.*" + "cakephp/cakephp": "~3.1" }, "require-dev": { "phpunit/phpunit": "*" From cc139a24463d129191b9f4b6a366f07db2cd3985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 6 Feb 2016 16:36:59 +0000 Subject: [PATCH 0356/1476] refs #fix-tests fix required oauth2 lib --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index e1e77e741..5cbd591c5 100644 --- a/composer.json +++ b/composer.json @@ -4,11 +4,11 @@ "type": "cakephp-plugin", "require": { "php": ">=5.4.16", - "cakephp/cakephp": "~3.1" + "cakephp/cakephp": "~3.1", + "muffin/oauth2": "dev-master" }, "require-dev": { - "phpunit/phpunit": "*", - "muffin/oauth2": "dev-master" + "phpunit/phpunit": "*" }, "suggest": { "league/oauth2-facebook": "Provide Social Authentication with Facebook", From c274f561eeda03389fee559005cab69ae924fe68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 6 Feb 2016 16:53:05 +0000 Subject: [PATCH 0357/1476] disable social authentication by default to get rid of exceptions if providers not found when loading SocialAuthenticate --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 2921d5c1c..a225a0293 100644 --- a/config/users.php +++ b/config/users.php @@ -39,7 +39,7 @@ ], 'Social' => [ //enable social login - 'login' => true, + 'login' => false, ], 'Profile' => [ //Allow view other users profiles From 78b556a824bd136db4eb1b04708a2f1453e6f9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 6 Feb 2016 17:02:58 +0000 Subject: [PATCH 0358/1476] refs #fix-tests fix test default social login disabled now --- tests/TestCase/Controller/Component/UsersAuthComponentTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 2c45e2f9c..3138bb384 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -106,8 +106,6 @@ public function testInitializeNoRequiredRememberMe() ->getMock(); $this->Controller->UsersAuth->expects($this->once()) ->method('_initAuth'); - $this->Controller->UsersAuth->expects($this->once()) - ->method('_loadSocialLogin'); $this->Controller->UsersAuth->expects($this->never()) ->method('_loadRememberMe'); $this->Controller->UsersAuth->initialize([]); From 035a73763d8464e3fe01e4cb33423e19c29e9ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 6 Feb 2016 17:34:24 +0000 Subject: [PATCH 0359/1476] add missing dependencies, fix phpcs --- composer.json | 6 ++-- src/Auth/Social/Mapper/AbstractMapper.php | 4 +-- src/Auth/Social/Mapper/LinkedIn.php | 2 +- src/Auth/Social/Mapper/Twitter.php | 2 +- src/Auth/Social/Util/SocialUtils.php | 5 +-- src/Auth/SocialAuthenticate.php | 17 ++++++---- src/Controller/Traits/LoginTrait.php | 33 +++++++++++-------- src/Controller/Traits/ProfileTrait.php | 3 +- src/Model/Behavior/SocialBehavior.php | 7 ++-- src/Shell/UsersShell.php | 3 +- src/View/Helper/UserHelper.php | 10 +++--- .../TestCase/Auth/SocialAuthenticateTest.php | 25 +++++++------- .../Model/Behavior/SocialBehaviorTest.php | 21 ++++-------- tests/TestCase/Model/Table/UsersTableTest.php | 9 +++-- 14 files changed, 76 insertions(+), 71 deletions(-) diff --git a/composer.json b/composer.json index 5cbd591c5..dfc76803d 100644 --- a/composer.json +++ b/composer.json @@ -5,10 +5,12 @@ "require": { "php": ">=5.4.16", "cakephp/cakephp": "~3.1", - "muffin/oauth2": "dev-master" + "muffin/oauth2": "dev-master", + "league/oauth1-client": "@stable" }, "require-dev": { - "phpunit/phpunit": "*" + "phpunit/phpunit": "*", + "cakephp/cakephp-codesniffer": "^2.0" }, "suggest": { "league/oauth2-facebook": "Provide Social Authentication with Facebook", diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index 7c307e354..0a738b0d6 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -53,8 +53,8 @@ abstract class AbstractMapper /** * Constructor * - * @param $rawData - * @param null $mapFields + * @param mixed $rawData raw data + * @param mixed $mapFields map fields */ public function __construct($rawData, $mapFields = null) { diff --git a/src/Auth/Social/Mapper/LinkedIn.php b/src/Auth/Social/Mapper/LinkedIn.php index fa01829a4..6edd447eb 100644 --- a/src/Auth/Social/Mapper/LinkedIn.php +++ b/src/Auth/Social/Mapper/LinkedIn.php @@ -25,4 +25,4 @@ class LinkedIn extends AbstractMapper 'bio' => 'headline', 'link' => 'publicProfileUrl' ]; -} \ No newline at end of file +} diff --git a/src/Auth/Social/Mapper/Twitter.php b/src/Auth/Social/Mapper/Twitter.php index a078f8a95..cf2bfe37b 100644 --- a/src/Auth/Social/Mapper/Twitter.php +++ b/src/Auth/Social/Mapper/Twitter.php @@ -48,4 +48,4 @@ protected function _link() { return self::TWITTER_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); } -} \ No newline at end of file +} diff --git a/src/Auth/Social/Util/SocialUtils.php b/src/Auth/Social/Util/SocialUtils.php index d67b1ee47..9fedd1779 100644 --- a/src/Auth/Social/Util/SocialUtils.php +++ b/src/Auth/Social/Util/SocialUtils.php @@ -22,7 +22,8 @@ class SocialUtils { /** * Get provider from classname - * @param AbstractProvider $provider + * + * @param AbstractProvider $provider provider * @return string */ public static function getProvider(AbstractProvider $provider) @@ -30,4 +31,4 @@ public static function getProvider(AbstractProvider $provider) $reflect = new ReflectionClass($provider); return $reflect->getShortName(); } -} \ No newline at end of file +} diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index b618b5e07..4ee9e07c2 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -11,10 +11,6 @@ namespace CakeDC\Users\Auth; -use Cake\Controller\ComponentRegistry; -use Cake\Core\Configure; -use Cake\Network\Request; -use Cake\ORM\TableRegistry; use CakeDC\Users\Auth\Social\Util\SocialUtils; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; @@ -22,6 +18,10 @@ use CakeDC\Users\Exception\MissingProviderException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Model\Table\SocialAccountsTable; +use Cake\Controller\ComponentRegistry; +use Cake\Core\Configure; +use Cake\Network\Request; +use Cake\ORM\TableRegistry; use Muffin\OAuth2\Auth\OAuthAuthenticate; /** @@ -47,7 +47,8 @@ public function __construct(ComponentRegistry $registry, array $config = []) /** * Find or create local user - * @param array $data + * + * @param array $data data * @return array|bool|mixed * @throws MissingEmailException */ @@ -132,7 +133,7 @@ protected function _getProviderName($request = null) $provider = false; if (!is_null($this->_provider)) { $provider = SocialUtils::getProvider($this->_provider); - } else if (!empty($request)){ + } elseif (!empty($request)) { $provider = ucfirst($request->param('provider')); } return $provider; @@ -158,6 +159,10 @@ protected function _mapUser($provider, $data) return $user; } + /** + * @param mixed $data data + * @return mixed + */ protected function _socialLogin($data) { $options = [ diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index db5d32e37..152b78b7a 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Event\Event; -use Cake\Network\Exception\NotFoundException; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; -use Cake\Core\Configure; use CakeDC\Users\Exception\UserNotActiveException; +use Cake\Core\Configure; +use Cake\Event\Event; +use Cake\Network\Exception\NotFoundException; use League\OAuth1\Client\Server\Twitter; /** @@ -28,7 +28,13 @@ trait LoginTrait { use CustomUsersTableTrait; - public function twitterLogin() { + /** + * Do twitter login + * + * @return mixed|void + */ + public function twitterLogin() + { $this->autoRender = false; $server = new Twitter([ @@ -65,25 +71,26 @@ public function twitterLogin() { $this->request->session()->write('temporary_credentials', $temporaryCredentials); $server->authorize($temporaryCredentials); } - return; } /** - * @param $event + * @param Event $event event + * @return void */ - public function failedSocialLoginListener(Event $event) { + public function failedSocialLoginListener(Event $event) + { $this->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } /** - * @param $exception - * @param $data - * @param bool|false $flash + * @param mixed $exception exception + * @param mixed $data data + * @param bool|false $flash flash * @return mixed */ public function failedSocialLogin($exception, $data, $flash = false) { $msg = __d('Users', 'Issues trying to log in with your social account'); - if (isset($exception) ) { + if (isset($exception)) { if ($exception instanceof MissingEmailException) { if ($flash) { $this->Flash->success(__d('Users', 'Please enter your email')); @@ -120,8 +127,8 @@ public function socialLogin() } $user = $this->Auth->user(); return $this->_afterIdentifyUser($user, true); - } + /** * Login user * @@ -137,7 +144,7 @@ public function login() return $this->redirect($event->result); } - $socialLogin = $this->_isSocialLogin(); + $socialLogin = $this->_isSocialLogin(); if (!empty($socialLogin)) { return $this->redirect(['action' => 'social-email']); diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index a9edbdd47..0d68ac6bc 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use Cake\Controller\Component\AuthComponent; use Cake\Core\Configure; use Cake\Datasource\Exception\InvalidPrimaryKeyException; use Cake\Datasource\Exception\RecordNotFoundException; @@ -35,7 +36,7 @@ public function profile($id = null) $id = $loggedUserId; } try { - $appContain = (array)Configure::read('Auth.authenticate.' . \Cake\Controller\Component\AuthComponent::ALL . '.contain'); + $appContain = (array)Configure::read('Auth.authenticate.' . AuthComponent::ALL . '.contain'); $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; $user = $this->getUsersTable()->get($id, [ 'contain' => array_merge((array)$appContain, (array)$socialContain) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 9b8d5d33c..f2f50ca05 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Model\Behavior; -use Cake\Event\EventDispatcherTrait; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Traits\RandomStringTrait; use Cake\Datasource\EntityInterface; +use Cake\Event\EventDispatcherTrait; use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; @@ -27,8 +27,8 @@ */ class SocialBehavior extends Behavior { - use RandomStringTrait; use EventDispatcherTrait; + use RandomStringTrait; /** * Performs social login @@ -143,7 +143,6 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $dataValidated = Hash::get($data, 'validated'); if (empty($existingUser)) { - $firstName = Hash::get($data, 'first_name'); $lastName = Hash::get($data, 'last_name'); if (!empty($firstName) && !empty($lastName)) { @@ -180,7 +179,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['password'] = $this->randomString(); $userData['avatar'] = Hash::get($data, 'avatar'); $userData['validated'] = !empty($dataValidated); - $userData['tos_date'] = date("Y-m-d H:i:s"); + $userData['tos_date'] = date("Y-m-d H:i:s"); $userData['gender'] = Hash::get($data, 'gender'); //$userData['timezone'] = Hash::get($data, 'timezone'); $userData['social_accounts'][] = $accountData; diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 634b21462..dc544b6f3 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -16,6 +16,7 @@ use Cake\Console\Shell; use Cake\Core\Configure; use Cake\Utility\Hash; +use Cake\Utility\Text; /** * Shell with utilities for the Users Plugin @@ -336,7 +337,7 @@ public function deleteUser() */ protected function _generateRandomPassword() { - return str_replace('-', '', \Cake\Utility\Text::uuid()); + return str_replace('-', '', Text::uuid()); } /** diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 843cf2531..50990edca 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -49,8 +49,8 @@ public function beforeLayout(Event $event) /** * Social login link * - * @param string $name - * @param array $options + * @param string $name name + * @param array $options options * @return string */ public function socialLogin($name, $options = []) @@ -60,9 +60,9 @@ public function socialLogin($name, $options = []) } return $this->Html->link($this->Html->tag('i', '', [ 'class' => __d('Users', 'fa fa-{0}', strtolower($name)), - ]) . __d('Users', '{0} {1}', Hash::get($options, 'label') , Inflector::camelize($name)), "/auth/$name", [ - 'escape' => false, 'class' => __d('Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ? :'', strtolower($name)) - ]); + ]) . __d('Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)), "/auth/$name", [ + 'escape' => false, 'class' => __d('Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ? :'', strtolower($name)) + ]); } /** diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index cbdb3c9c2..c42ec7165 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -11,17 +11,15 @@ namespace CakeDC\Users\Test\TestCase\Auth; -use Cake\ORM\TableRegistry; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Exception\UserNotActiveException; use Cake\Controller\ComponentRegistry; -use Cake\Controller\Controller; -use Cake\Event\EventManager; use Cake\Event\Event; use Cake\Network\Request; use Cake\Network\Response; +use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Exception\UserNotActiveException; use ReflectionClass; class SocialAuthenticateTest extends TestCase @@ -95,7 +93,7 @@ public function testGetUserAuth($rawData, $mapper) ->method('_mapUser') ->will($this->returnValue($mapper)); - $user = $this->Table->get('00000000-0000-0000-0000-000000000002'); + $user = $this->Table->get('00000000-0000-0000-0000-000000000002'); $this->SocialAuthenticate->expects($this->once()) ->method('_socialLogin') ->will($this->returnValue($user)); @@ -128,7 +126,7 @@ public function providerGetUser() 'locale' => 'en_US', 'link' => 'link', ], - 'mappedData' => [ + 'mappedData' => [ 'id' => 'reference-2-1', 'username' => null, 'full_name' => 'User S', @@ -343,7 +341,7 @@ public function providerTwitter() 'locale' => 'en_US', 'link' => 'link', ], - 'mappedData' => [ + 'mappedData' => [ 'id' => 'reference-2-1', 'username' => null, 'full_name' => 'User S', @@ -428,7 +426,7 @@ public function providerMapper() { return [ [ - 'rawData' => [ + 'rawData' => [ 'id' => 'my-facebook-id', 'name' => 'My name.', 'first_name' => 'My first name', @@ -438,7 +436,7 @@ public function providerMapper() 'locale' => 'en_US', 'link' => 'https://www.facebook.com/app_scoped_user_id/my-facebook-id/', ], - 'mappedData' => [ + 'mappedData' => [ 'id' => 'my-facebook-id', 'username' => null, 'full_name' => 'My name.', @@ -454,11 +452,11 @@ public function providerMapper() 'credentials' => [ 'token' => 'token', 'secret' => null, - 'expires' => (int) 1458510952 + 'expires' => (int)1458510952 ], 'provider' => 'Facebook' ], - ] + ] ]; } @@ -480,5 +478,4 @@ public function testMapUserException() $mapUser->setAccessible(true); $mapUser->invoke($this->SocialAuthenticate, null, $data); } - } diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php index 600b49465..33f700836 100644 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -61,7 +61,7 @@ public function tearDown() */ public function testSocialLoginFacebookProvider($data, $options, $dataUser) { - $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); + $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); $user->password = '$2y$10$0QzszaIEpW1pYpoKJVf4DeqEAHtg9whiLTX/l3TcHAoOLF1bC9U.6'; $this->Behavior->expects($this->once()) @@ -122,7 +122,7 @@ public function providerFacebookSocialLogin() 'link' => 'facebook-link', 'provider' => 'Facebook' ], - 'options' => [ + 'options' => [ 'use_email' => true, 'validate_email' => true, 'token_expiration' => 3600 @@ -154,10 +154,9 @@ public function providerFacebookSocialLogin() 'activation_date' => '2016-01-20 15:45:09', 'active' => true, ] - ] + ] ]; - } /** @@ -179,7 +178,6 @@ public function testSocialLoginExistingReference($data, $options) $result = $this->Behavior->socialLogin($data, $options); $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); $this->assertTrue($result->active); - } /** @@ -194,7 +192,7 @@ public function providerFacebookSocialLoginExistingReference() 'id' => 'reference-2-1', 'provider' => 'Facebook' ], - 'options' => [ + 'options' => [ 'use_email' => true, 'validate_email' => true, 'token_expiration' => 3600 @@ -212,7 +210,6 @@ public function providerFacebookSocialLoginExistingReference() */ public function testSocialLoginExistingNotActiveReference($data, $options) { - $this->Behavior->expects($this->never()) ->method('generateUniqueUsername'); @@ -222,7 +219,6 @@ public function testSocialLoginExistingNotActiveReference($data, $options) $this->Behavior->expects($this->never()) ->method('_updateActive'); $this->Behavior->socialLogin($data, $options); - } /** @@ -237,7 +233,7 @@ public function providerSocialLoginExistingAndNotActiveAccount() 'id' => 'reference-1-1234', 'provider' => 'Facebook' ], - 'options' => [ + 'options' => [ 'use_email' => true, 'validate_email' => true, 'token_expiration' => 3600 @@ -255,7 +251,6 @@ public function providerSocialLoginExistingAndNotActiveAccount() */ public function testSocialLoginExistingReferenceNotActiveUser($data, $options) { - $this->Behavior->expects($this->never()) ->method('generateUniqueUsername'); @@ -265,7 +260,6 @@ public function testSocialLoginExistingReferenceNotActiveUser($data, $options) $this->Behavior->expects($this->never()) ->method('_updateActive'); $this->Behavior->socialLogin($data, $options); - } /** @@ -280,7 +274,7 @@ public function providerSocialLoginExistingAccountNotActiveUser() 'id' => 'reference-1-1234', 'provider' => 'Twitter' ], - 'options' => [ + 'options' => [ 'use_email' => true, 'validate_email' => true, 'token_expiration' => 3600 @@ -320,7 +314,7 @@ public function providerFacebookSocialLoginNoEmail() 'link' => 'facebook-link', 'provider' => 'Facebook' ], - 'options' => [ + 'options' => [ 'use_email' => true, 'validate_email' => true, 'token_expiration' => 3600 @@ -359,5 +353,4 @@ public function providerGenerateUsername() ]; } - } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index c241e2a41..f9522fd60 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -27,7 +27,6 @@ */ class UsersTableTest extends TestCase { - /** * Fixtures * @@ -184,7 +183,7 @@ public function testSocialLogin() 'email' => 'user-2@test.com', 'id' => 'reference-2-1', 'link' => 'link', - 'raw' => [ + 'raw' => [ 'id' => 'reference-2-1', 'token' => 'token', 'first_name' => 'User 2', @@ -216,7 +215,7 @@ public function testSocialLoginInactiveAccount() 'email' => 'hello@test.com', 'id' => 'reference-2-2', 'link' => 'link', - 'raw' => [ + 'raw' => [ 'id' => 'reference-2-2', 'first_name' => 'User 2', 'gender' => 'female', @@ -246,7 +245,7 @@ public function testSocialLoginCreateNewAccountWithNoCredentials() 'email' => 'user@test.com', 'id' => 'reference-not-existing', 'link' => 'link', - 'raw' => [ + 'raw' => [ 'id' => 'reference-not-existing', 'first_name' => 'Not existing user', 'gender' => 'male', @@ -278,7 +277,7 @@ public function testSocialLoginCreateNewAccount() 'link' => 'link', 'first_name' => 'First Name', 'last_name' => 'Last Name', - 'raw' => [ + 'raw' => [ 'id' => 'no-existing-reference', 'first_name' => 'First Name', 'last_name' => 'Last Name', From 03281aac7336b4644e0ff7040214640788a3a29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 6 Feb 2016 17:43:18 +0000 Subject: [PATCH 0360/1476] fix docs about default social login disabled --- Docs/Documentation/Configuration.md | 4 +++- Docs/Documentation/Installation.md | 9 ++++++++- Docs/Documentation/SocialAuthenticate.md | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index a37f68b0f..70ebecc19 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -10,9 +10,11 @@ config/bootstrap.php ``` Configure::write('Users.config', ['users']); Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); +Configure::write('Users.Social.login', true); //to enable social login ``` Then in your config/users.php + ``` 'Opauth.providers' => [ 'facebook' => [ @@ -102,7 +104,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use ], 'Social' => [ //enable social login - 'login' => true, + 'login' => false, ], //Avatar placeholder 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 3822254fa..6a5cafde6 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -5,7 +5,7 @@ Composer ------ ``` -composer require cakedc/users:3.1.* +composer require cakedc/users ``` if you want to use social login features... @@ -16,7 +16,13 @@ composer require league/oauth2-facebook:* composer require league/oauth2-instagram:* composer require league/oauth2-google:* composer require league/oauth2-linkedin:* +``` + +NOTE: you'll need to enable social login in your bootstrap.php file if you want to use it, social +login is disabled by default. Check the [Configuration](Configuration.md) page for more details. +``` +Configure::write('Users.Social.login', true); //to enable social login ``` Creating Required Tables @@ -47,6 +53,7 @@ config/bootstrap.php ``` Configure::write('Users.config', ['users']); Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); +Configure::write('Users.Social.login', true); //to enable social login ``` Then in your config/users.php diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index 6bcfefe20..bb3fd2929 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -27,7 +27,7 @@ Configure::write('Users', [ ], 'Social' => [ //enable social login - 'login' => true, + 'login' => false, ], 'Key' => [ 'Session' => [ From 7e593c9c0ac599368434354b8e90948cccad6bb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 6 Feb 2016 17:48:45 +0000 Subject: [PATCH 0361/1476] fix readme --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c797056ef..4ceafd332 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.1.* -* PHP 5.4.16+ +* CakePHP 3.1+ +* PHP 5.4.16+ Note CakePHP 3.2 requires PHP 5.5 so 5.4 compatibility would be dropped sooner than later... Documentation ------------- @@ -55,11 +55,14 @@ For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory Roadmap ------ + +* 3.1.4 << you are here + * SocialAuthenticate refactored to drop Opauth in favor of Muffin/OAuth2 and league/oauth2 +* 3.1.3 + * UserHelper improvements * 3.1.2 - * Add Google authentication - * Add Instagram authentication - * Improve unit test coverage -* YOU ARE HERE > 3.1.0 Migration to CakePHP 3.0 + * Fixes in RBAC permission matchers +* 3.1.0 Migration to CakePHP 3.0 * Unit test coverage improvements * Refactor UsersTable to Behavior * Add google authentication From e877f201e5b10bf2cb73fa25d82a1069300d2842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sat, 6 Feb 2016 17:50:55 +0000 Subject: [PATCH 0362/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index daa667f3f..abcaef42f 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 3 :minor: 1 -:patch: 0 +:patch: 4 :special: '' From 755ee1a96d00422f8ac974b9b13c5e1d4e86aaef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 31 Jan 2016 13:40:30 +0000 Subject: [PATCH 0363/1476] add Owner rule class, to define ownership permissions quickly --- src/Auth/Rules/AbstractRule.php | 92 +++++++++ src/Auth/Rules/Owner.php | 72 +++++++ src/Auth/Rules/Rule.php | 27 +++ src/Auth/SimpleRbacAuthorize.php | 3 + tests/Fixture/PostsFixture.php | 60 ++++++ tests/Fixture/PostsUsersFixture.php | 60 ++++++ tests/TestCase/Auth/Rules/OwnerTest.php | 261 ++++++++++++++++++++++++ tests/bootstrap.php | 4 +- 8 files changed, 578 insertions(+), 1 deletion(-) create mode 100644 src/Auth/Rules/AbstractRule.php create mode 100644 src/Auth/Rules/Owner.php create mode 100644 src/Auth/Rules/Rule.php create mode 100644 tests/Fixture/PostsFixture.php create mode 100644 tests/Fixture/PostsUsersFixture.php create mode 100644 tests/TestCase/Auth/Rules/OwnerTest.php diff --git a/src/Auth/Rules/AbstractRule.php b/src/Auth/Rules/AbstractRule.php new file mode 100644 index 000000000..f8955fbbc --- /dev/null +++ b/src/Auth/Rules/AbstractRule.php @@ -0,0 +1,92 @@ +config($config); + } + + /** + * Get a table from the alias, table object or inspecting the request for a default table + * + * @param Request $request request + * @param mixed $table table + * @return \Cake\ORM\Table + * @throw OutOfBoundsException if table alias is empty + */ + protected function _getTable(Request $request, $table = null) + { + if (empty($table)) { + return $this->_getTableFromRequest($request); + } + if ($table instanceof Table) { + return $table; + } + return TableRegistry::get($table); + } + + /** + * Inspect the request and try to retrieve a table based on the current controller + * + * @param Request $request request + * @return Table + * @throws OutOfBoundsException if table alias can't be extracted from request + */ + protected function _getTableFromRequest(Request $request) + { + $plugin = Hash::get($request->params, 'plugin'); + $controller = Hash::get($request->params, 'controller'); + $modelClass = ($plugin ? $plugin . '.' : '') . $controller; + + $this->modelFactory('Table', [$this->tableLocator(), 'get']); + if (empty($modelClass)) { + throw new OutOfBoundsException(__d('Users', 'Table alias is empty, please define a table alias, we could not extract a default table from the request')); + } + return $this->loadModel($modelClass); + } + + /** + * Check the current entity is owned by the logged in user + * + * @param array $user Auth array with the logged in data + * @param string $role role of the user + * @param Request $request current request, used to get a default table if not provided + * @return bool + * @throws OutOfBoundsException if table is not found or it doesn't have the expected fields + */ + abstract public function allowed(array $user, $role, Request $request); +} diff --git a/src/Auth/Rules/Owner.php b/src/Auth/Rules/Owner.php new file mode 100644 index 000000000..68799892c --- /dev/null +++ b/src/Auth/Rules/Owner.php @@ -0,0 +1,72 @@ + 'user_id', + /* + * request key type to retrieve the table id, could be "params", "query", "data" to locate the table id + * example: + * yoursite.com/controller/action/XXX would be + * tableKeyType => 'params', 'tableIdParamsKey' => 'pass.0' + * yoursite.com/controlerr/action?post_id=XXX would be + * tableKeyType => 'query', 'tableIdParamsKey' => 'post_id' + * yoursite.com/controller/action [posted form with a field named post_id] would be + * tableKeyType => 'data', 'tableIdParamsKey' => 'post_id' + */ + 'tableKeyType' => 'params', + // request->params key path to retrieve the owned table id + 'tableIdParamsKey' => 'pass.0', + /* define table to use or pick it from controller name defaults if null + * if null, table used will be based on current controller's default table + * if string, TableRegistry::get will be used + * if Table, the table object will be used + */ + 'table' => null, + 'conditions' => [], + ]; + + /** + * {@inheritdoc} + */ + public function allowed(array $user, $role, Request $request) + { + $table = $this->_getTable($request, $this->config('table')); + //retrieve table id from request + $id = Hash::get($request->{$this->config('tableKeyType')}, $this->config('tableIdParamsKey')); + $userId = Hash::get($user, 'id'); + + try { + if (!$table->hasField($this->config('ownerForeignKey'))) { + throw new OutOfBoundsException(__d('Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); + } + } catch (Exception $ex) { + throw new OutOfBoundsException(__d('Users', 'Table {0} has no columns, please check the table exists. {1}', $table->alias(), $ex->getMessage())); + } + $conditions = array_merge([ + $table->primaryKey() => $id, + $this->config('ownerForeignKey') => $userId + ], $this->config('conditions')); + + return $table->exists($conditions); + } +} diff --git a/src/Auth/Rules/Rule.php b/src/Auth/Rules/Rule.php new file mode 100644 index 000000000..7ba6c438d --- /dev/null +++ b/src/Auth/Rules/Rule.php @@ -0,0 +1,27 @@ +_matchOrAsterisk($permission, 'controller', $controller) && $this->_matchOrAsterisk($permission, 'action', $action)) { $allowed = Hash::get($permission, 'allowed'); + if ($allowed === null) { //allowed will be true by default return true; } elseif (is_callable($allowed)) { return (bool)call_user_func($allowed, $user, $role, $request); + } elseif ($allowed instanceof \CakeDC\Users\Auth\Rules\AbstractRule) { + return $allowed->allowed($user, $role, $request); } else { return (bool)$allowed; } diff --git a/tests/Fixture/PostsFixture.php b/tests/Fixture/PostsFixture.php new file mode 100644 index 000000000..fadeb7179 --- /dev/null +++ b/tests/Fixture/PostsFixture.php @@ -0,0 +1,60 @@ + ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'title' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'title' => 'post-1', + 'user_id' => '00000000-0000-0000-0000-000000000001', + ], + [ + 'id' => '00000000-0000-0000-0000-000000000002', + 'title' => 'post-2', + 'user_id' => '00000000-0000-0000-0000-000000000002', + ], + ]; +} diff --git a/tests/Fixture/PostsUsersFixture.php b/tests/Fixture/PostsUsersFixture.php new file mode 100644 index 000000000..9227398ab --- /dev/null +++ b/tests/Fixture/PostsUsersFixture.php @@ -0,0 +1,60 @@ + ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'post_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'post_id' => '00000000-0000-0000-0000-000000000001', + ], + [ + 'id' => '00000000-0000-0000-0000-000000000002', + 'user_id' => '00000000-0000-0000-0000-000000000002', + 'post_id' => '00000000-0000-0000-0000-000000000002', + ], + ]; +} diff --git a/tests/TestCase/Auth/Rules/OwnerTest.php b/tests/TestCase/Auth/Rules/OwnerTest.php new file mode 100644 index 000000000..e98b8f0c8 --- /dev/null +++ b/tests/TestCase/Auth/Rules/OwnerTest.php @@ -0,0 +1,261 @@ +Owner = new Owner(); + $this->request = $this->getMockBuilder('\Cake\Network\Request') + ->getMock(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->Owner); + } + + /** + * test + * + * @return void + */ + public function testAllowed() + { + $this->request->params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Posts', + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testAllowedUsingTableAlias() + { + $this->Owner = new Owner([ + 'table' => 'Posts' + ]); + $this->request->params = [ + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testAllowedUsingTableInstance() + { + $this->Owner = new Owner([ + 'table' => TableRegistry::get('CakeDC/Users.Posts'), + ]); + $this->request->params = [ + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Table alias is empty, please define a table alias, we could not extract a default table from the request + */ + public function testAllowedShouldThrowExceptionBecauseEmptyAliasFromRequest() + { + $this->request->params = [ + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->Owner->allowed($user, 'user', $this->request); + } + + /** + * test + * + * @return void + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Missing column column_not_found in table Posts while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 + */ + public function testAllowedShouldThrowExceptionBecauseForeignKeyNotPresentInTable() + { + $this->Owner = new Owner([ + 'table' => TableRegistry::get('CakeDC/Users.Posts'), + 'ownerForeignKey' => 'column_not_found', + ]); + $this->request->params = [ + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->Owner->allowed($user, 'user', $this->request); + } + + /** + * test + * + * @return void + */ + public function testNotAllowedBecauseNotOwner() + { + $this->request->params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Posts', + 'pass' => ['00000000-0000-0000-0000-000000000002'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testNotAllowedBecauseUserNotFound() + { + $this->request->params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Posts', + 'pass' => ['00000000-0000-0000-0000-000000000002'] + ]; + $user = [ + 'id' => 'not-found', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testNotAllowedBecausePostNotFound() + { + $this->request->params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Posts', + 'pass' => ['not-found'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Table NoDefaultTable has no columns, please check the table exists. Cannot describe no_default_table. It has 0 columns. + */ + public function testNotAllowedBecauseNoDefaultTable() + { + $this->request->params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'NoDefaultTable', + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * Test using the Owner rule in a belongsToMany association + * Posts belongsToMany Users + * @return void + */ + public function testAllowedBelongsToMany() + { + $this->Owner = new Owner([ + 'table' => 'PostsUsers' + ]); + $this->request->params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'IsNotUsed', + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * Test using the Owner rule in a belongsToMany association + * Posts belongsToMany Users + * @return void + */ + public function testNotAllowedBelongsToMany() + { + $this->Owner = new Owner([ + 'table' => 'PostsUsers' + ]); + $this->request->params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'IsNotUsed', + 'pass' => ['00000000-0000-0000-0000-000000000002'] + ]; + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b0bbdb56c..d676a0a80 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -20,7 +20,9 @@ unset($findRoot); chdir($root); -define('DS', DIRECTORY_SEPARATOR); +if (!defined('DS')) { + define('DS', DIRECTORY_SEPARATOR); +} define('ROOT', $root); define('APP_DIR', 'App'); define('WEBROOT_DIR', 'webroot'); From ff96108cde2e3bf59ef2a15203de354811879dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 8 Feb 2016 17:31:34 +0000 Subject: [PATCH 0364/1476] minor fixes in tests --- src/Auth/Rules/Owner.php | 2 +- tests/TestCase/Auth/Rules/OwnerTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Auth/Rules/Owner.php b/src/Auth/Rules/Owner.php index 68799892c..0f52a1338 100644 --- a/src/Auth/Rules/Owner.php +++ b/src/Auth/Rules/Owner.php @@ -60,7 +60,7 @@ public function allowed(array $user, $role, Request $request) throw new OutOfBoundsException(__d('Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); } } catch (Exception $ex) { - throw new OutOfBoundsException(__d('Users', 'Table {0} has no columns, please check the table exists. {1}', $table->alias(), $ex->getMessage())); + throw new OutOfBoundsException(__d('Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); } $conditions = array_merge([ $table->primaryKey() => $id, diff --git a/tests/TestCase/Auth/Rules/OwnerTest.php b/tests/TestCase/Auth/Rules/OwnerTest.php index e98b8f0c8..aa320cf36 100644 --- a/tests/TestCase/Auth/Rules/OwnerTest.php +++ b/tests/TestCase/Auth/Rules/OwnerTest.php @@ -174,7 +174,7 @@ public function testNotAllowedBecauseUserNotFound() 'pass' => ['00000000-0000-0000-0000-000000000002'] ]; $user = [ - 'id' => 'not-found', + 'id' => '99999999-0000-0000-0000-000000000000', ]; $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); } @@ -189,7 +189,7 @@ public function testNotAllowedBecausePostNotFound() $this->request->params = [ 'plugin' => 'CakeDC/Users', 'controller' => 'Posts', - 'pass' => ['not-found'] + 'pass' => ['99999999-0000-0000-0000-000000000000'] //not found ]; $user = [ 'id' => '00000000-0000-0000-0000-000000000001', @@ -202,7 +202,7 @@ public function testNotAllowedBecausePostNotFound() * * @return void * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Table NoDefaultTable has no columns, please check the table exists. Cannot describe no_default_table. It has 0 columns. + * @expectedExceptionMessage Missing column user_id in table NoDefaultTable while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 */ public function testNotAllowedBecauseNoDefaultTable() { From a39f507cc88e4a1fd9b0d5662caeb0f2f021cf02 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 8 Feb 2016 14:18:54 -0500 Subject: [PATCH 0365/1476] Fixing new social login changes --- Docs/Documentation/Installation.md | 1 - composer.json | 35 ++- config/bootstrap.php | 13 +- config/routes.php | 15 +- config/users.php | 11 +- .../Exception/InvalidProviderException.php | 10 + .../Exception/InvalidSettingsException.php | 10 + .../MissingEventListenerException.php | 9 + .../MissingProviderConfigurationException.php | 10 + src/Auth/SocialAuthenticate.php | 263 +++++++++++++++++- src/Controller/Traits/LoginTrait.php | 11 +- src/Controller/Traits/SocialTrait.php | 1 + src/Model/Table/SocialAccountsTable.php | 1 - 13 files changed, 358 insertions(+), 32 deletions(-) create mode 100644 src/Auth/Exception/InvalidProviderException.php create mode 100644 src/Auth/Exception/InvalidSettingsException.php create mode 100644 src/Auth/Exception/MissingEventListenerException.php create mode 100644 src/Auth/Exception/MissingProviderConfigurationException.php diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 6a5cafde6..0e6e89caa 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -11,7 +11,6 @@ composer require cakedc/users if you want to use social login features... ``` -composer require Muffin/OAuth2:* composer require league/oauth2-facebook:* composer require league/oauth2-instagram:* composer require league/oauth2-google:* diff --git a/composer.json b/composer.json index dfc76803d..436ed31ed 100644 --- a/composer.json +++ b/composer.json @@ -2,20 +2,45 @@ "name": "cakedc/users", "description": "Users plugin for CakePHP 3.1", "type": "cakephp-plugin", + "keywords": [ + "cakephp", + "oauth2", + "auth", + "authentication", + "cakedc" + ], + "homepage": "https://github.com/CakeDC/users", + "license": "MIT", + "authors": [ + { + "name": "CakeDC", + "homepage": "http://www.cakedc.com", + "role": "Author" + }, + { + "name": "Others", + "homepage": "https://github.com/CakeDC/users/graphs/contributors" + } + ], + "support": { + "issues": "https://github.com/CakeDC/users/issues", + "source": "https://github.com/CakeDC/users" + }, "require": { "php": ">=5.4.16", "cakephp/cakephp": "~3.1", - "muffin/oauth2": "dev-master", - "league/oauth1-client": "@stable" }, "require-dev": { "phpunit/phpunit": "*", "cakephp/cakephp-codesniffer": "^2.0" }, "suggest": { - "league/oauth2-facebook": "Provide Social Authentication with Facebook", - "league/oauth2-instagram": "Provide Social Authentication with Instagram", - "google/recaptcha": "Provide reCAPTCHA validation for registration form" + "league/oauth1-client": "Provides Social Authentication with Twitter", + "league/oauth2-facebook": "Provides Social Authentication with Facebook", + "league/oauth2-instagram": "Provides Social Authentication with Instagram", + "league/oauth2-google": "Provides Social Authentication with Google+", + "league/oauth2-linkedin": "Provides Social Authentication with LinkedIn", + "google/recaptcha": "Provides reCAPTCHA validation for registration form" }, "autoload": { "psr-4": { diff --git a/config/bootstrap.php b/config/bootstrap.php index 28400af47..f931659c4 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -15,6 +15,7 @@ use Cake\Core\Plugin; use Cake\Event\EventManager; use Cake\ORM\TableRegistry; +use Cake\Routing\Router; Configure::load('CakeDC/Users.users'); collection((array)Configure::read('Users.config'))->each(function ($file) { @@ -27,9 +28,19 @@ if (Configure::read('Users.Social.login') && php_sapi_name() != 'cli') { try { - Plugin::load('Muffin/OAuth2'); EventManager::instance()->on(\CakeDC\Users\Controller\Component\UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, [new \CakeDC\Users\Controller\UsersController(), 'failedSocialLoginListener']); } catch (MissingPluginException $e) { Log::error($e->getMessage()); } } + +$oauthPath = Configure::read('OAuth.path'); +if (is_array($oauthPath)) { + Router::scope('/auth', function ($routes) use ($oauthPath) { + $routes->connect( + '/:provider', + $oauthPath, + ['provider' => implode('|', array_keys(Configure::read('OAuth.providers')))] + ); + }); +} \ No newline at end of file diff --git a/config/routes.php b/config/routes.php index 41dccc94b..191175c95 100644 --- a/config/routes.php +++ b/config/routes.php @@ -10,19 +10,14 @@ */ use Cake\Core\Configure; use Cake\Routing\Router; + Router::plugin('CakeDC/Users', ['path' => '/users'], function ($routes) { $routes->fallbacks('DashedRoute'); }); -$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')))] - ); - }); -} + +//if (!Configure::check('OAuth.path')) { +// Configure::load('CakeDC/Users.users'); +//} Router::connect('/auth/twitter', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', diff --git a/config/users.php b/config/users.php index 616c33606..edc5e2433 100644 --- a/config/users.php +++ b/config/users.php @@ -10,6 +10,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ use Cake\Core\Configure; +use Cake\Routing\Router; $config = [ 'Users' => [ @@ -107,19 +108,27 @@ 'facebook' => [ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5' + 'graphApiVersion' => 'v2.5', + 'redirectUri' => Router::url('/auth/facebook', true) ] ], 'linkedIn' => [ 'className' => 'League\OAuth2\Client\Provider\LinkedIn', + 'options' => [ + 'redirectUri' => Router::url('/auth/linkedIn', true) + ] ], 'instagram' => [ 'className' => 'League\OAuth2\Client\Provider\Instagram', + 'options' => [ + 'redirectUri' => Router::url('/auth/instagram', true) + ] ], 'google' => [ 'className' => 'League\OAuth2\Client\Provider\Google', 'options' => [ 'userFields' => ['url', 'aboutMe'], + 'redirectUri' => Router::url('/auth/google', true) ] ], ], diff --git a/src/Auth/Exception/InvalidProviderException.php b/src/Auth/Exception/InvalidProviderException.php new file mode 100644 index 000000000..1825d475c --- /dev/null +++ b/src/Auth/Exception/InvalidProviderException.php @@ -0,0 +1,10 @@ +normalizeConfig(array_merge($config, $oauthConfig)); + parent::__construct($registry, $config); + } + + /** + * Normalizes providers' configuration. + * + * @param array $config Array of config to normalize. + * @return array + * @throws \Exception + */ + public function normalizeConfig(array $config) + { + $config = Hash::merge((array)Configure::read('OAuth2'), $config); + + if (empty($config['providers'])) { + throw new MissingProviderConfigurationException(); + } + + 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 \Muffin\OAuth2\Auth\Exception\InvalidProviderException + * @throws \Muffin\OAuth2\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 a user based on information in the request. + * + * @param \Cake\Network\Request $request Request object. + * @param \Cake\Network\Response $response Response object. + * @return bool + * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. + */ + public function authenticate(Request $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\Network\Request $request Request object. + * @return array|bool + */ + protected function _authenticate(Request $request) + { + if (!$this->_validate($request)) { + return false; + } + + $provider = $this->provider($request); + $code = $request->query('code'); + + try { + $token = $provider->getAccessToken('authorization_code', compact('code')); + return compact('token') + $provider->getResourceOwner($token)->toArray(); + } catch (\Exception $e) { + return false; + } + } + + /** + * Validates OAuth2 request. + * + * @param \Cake\Network\Request $request Request object. + * @return bool + */ + protected function _validate(Request $request) + { + if (!array_key_exists('code', $request->query) || !$this->provider($request)) { + return false; + } + + $session = $request->session(); + $sessionKey = 'oauth2state'; + $state = $request->query('state'); + + if ($this->config('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->config('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\Network\Request $request Request object. + * @param \Cake\Network\Response $response Response object. + * @return \Cake\Network\Response|null + */ + public function unauthenticated(Request $request, Response $response) + { + $provider = $this->provider($request); + if (empty($provider) || !empty($request->query['code'])) { + return null; + } + + if ($this->config('options.state')) { + $request->session()->write('oauth2state', $provider->getState()); + } + + $response->location($provider->getAuthorizationUrl()); + return $response; + } + + /** + * Returns the `$request`-ed provider. + * + * @param \Cake\Network\Request $request Current HTTP request. + * @return \League\Oauth2\Client\Provider\GenericProvider|false + */ + public function provider(Request $request) + { + if (!$alias = $request->param('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->config('providers.' . $alias)) { + return false; + } + + $this->config($config); + + if (is_object($config) && $config instanceof AbstractProvider) { + return $config; + } + + $class = $config['className']; + return new $class($config['options'], $config['collaborators']); } /** @@ -66,14 +302,17 @@ protected function _touch(array $data) } catch (MissingEmailException $ex) { $exception = $ex; } - if (!empty($exception)) { - $event = UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN; $args = ['exception' => $exception, 'rawData' => $data]; - $event = $this->dispatchEvent($event, $args); - if ($exception instanceof MissingEmailException && $data['provider'] == SocialAccountsTable::PROVIDER_TWITTER) { - throw $exception; + $event = new Event(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, $args); + $event = EventManager::instance()->dispatch($event); +// if ($data['provider'] === SocialAccountsTable::PROVIDER_TWITTER) { +// throw $exception; +// } + if (method_exists($this->_registry->getController(), 'failedSocialLogin')) { + $this->_registry->getController()->failedSocialLogin($exception, $data, true); } + return $event->result; } @@ -88,7 +327,7 @@ protected function _touch(array $data) * * @param \Cake\Network\Request $request Request object. * @return mixed Either false or an array of user information - * @throws \RuntimeException If the `Muffin/OAuth2.newUser` event is missing or returns empty. + * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. */ public function getUser(Request $request) { @@ -110,6 +349,9 @@ public function getUser(Request $request) $provider = $this->_getProviderName($request); $user = $this->_mapUser($provider, $rawData); + if ($user['provider'] === SocialAccountsTable::PROVIDER_TWITTER) { + $request->session()->write(Configure::read('Users.Key.Session.social'), $user); + } } if (!$user || !$this->config('userModel')) { @@ -119,6 +361,7 @@ public function getUser(Request $request) if (!$result = $this->_touch($user)) { return false; } + $request->session()->delete(Configure::read('Users.Key.Session.social')); return $result; } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index f70476b18..493257e22 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -18,6 +18,7 @@ use Cake\Core\Configure; use Cake\Event\Event; use Cake\Network\Exception\NotFoundException; +use CakeDC\Users\Model\Table\SocialAccountsTable; use League\OAuth1\Client\Server\Twitter; /** @@ -63,8 +64,9 @@ public function twitterLogin() } catch (MissingEmailException $ex) { $exception = $ex; } + if (!empty($exception)) { - return $this->failedSocialLogin($exception, $this->request->session()->read(Configure::read('Users.Key.Session.social'))); + return $this->failedSocialLogin($exception, $this->request->session()->read(Configure::read('Users.Key.Session.social')), true); } } else { $temporaryCredentials = $server->getTemporaryCredentials(); @@ -78,7 +80,7 @@ public function twitterLogin() */ public function failedSocialLoginListener(Event $event) { - $this->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); + return $this->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } /** @@ -90,6 +92,7 @@ public function failedSocialLoginListener(Event $event) public function failedSocialLogin($exception, $data, $flash = false) { $msg = __d('Users', 'Issues trying to log in with your social account'); + if (isset($exception)) { if ($exception instanceof MissingEmailException) { if ($flash) { @@ -105,8 +108,10 @@ public function failedSocialLogin($exception, $data, $flash = false) } } if ($flash) { + $this->Auth->config('authError', $msg); + $this->Auth->config('flash.params', ['class' => 'success']); $this->request->session()->delete(Configure::read('Users.Key.Session.social')); - $this->Flash->success($msg); + $this->Flash->success(__d('Users', $msg)); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index bb03f187b..05a90f957 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -31,6 +31,7 @@ public function socialEmail() if (!$this->request->session()->check(Configure::read('Users.Key.Session.social'))) { throw new NotFoundException(); } + $this->request->session()->delete('Flash.auth'); if ($this->request->is('post')) { $validPost = $this->_validateRegisterPost(); diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index f753d0e81..5e86bb046 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -112,7 +112,6 @@ public function validationDefault(Validator $validator) */ public function buildRules(RulesChecker $rules) { - $rules->add($rules->isUnique(['username'])); $rules->add($rules->existsIn(['user_id'], 'Users')); return $rules; } From 2a80d7c4ff81d3607752bdd77291527d4b2f51be Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 8 Feb 2016 15:06:44 -0500 Subject: [PATCH 0366/1476] Remove out commented code --- src/Auth/SocialAuthenticate.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index d567ef4fa..2ac88c9b5 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -306,9 +306,6 @@ protected function _touch(array $data) $args = ['exception' => $exception, 'rawData' => $data]; $event = new Event(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, $args); $event = EventManager::instance()->dispatch($event); -// if ($data['provider'] === SocialAccountsTable::PROVIDER_TWITTER) { -// throw $exception; -// } if (method_exists($this->_registry->getController(), 'failedSocialLogin')) { $this->_registry->getController()->failedSocialLogin($exception, $data, true); } From eed74d010c72f2650e82d954c4da278f9b138694 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 8 Feb 2016 16:35:36 -0500 Subject: [PATCH 0367/1476] Fix google for non google+ users --- src/Auth/Social/Mapper/AbstractMapper.php | 1 + src/Auth/Social/Mapper/Google.php | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index 0a738b0d6..ac045815d 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -108,6 +108,7 @@ protected function _map() 'expires' => is_array($token) ? Hash::get($token, 'expires') : $token->getExpires(), ]; $result['raw'] = $this->_rawData; + return $result; } } diff --git a/src/Auth/Social/Mapper/Google.php b/src/Auth/Social/Mapper/Google.php index f5ba5a1ec..843cf75bb 100644 --- a/src/Auth/Social/Mapper/Google.php +++ b/src/Auth/Social/Mapper/Google.php @@ -10,6 +10,7 @@ */ namespace CakeDC\Users\Auth\Social\Mapper; +use Cake\Utility\Hash; /** * Google Mapper @@ -30,4 +31,12 @@ class Google extends AbstractMapper 'bio' => 'aboutMe', 'link' => 'url' ]; + + /** + * @return string + */ + protected function _link() + { + return Hash::get($this->_rawData, $this->_mapFields['link']) ?: '#'; + } } From d2b220bbd8e922a75b3084709f5bcf3be5cc623a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 9 Feb 2016 10:32:00 +0000 Subject: [PATCH 0368/1476] replace and use interface, as it should be --- src/Auth/SimpleRbacAuthorize.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index ab38d814b..85c5913c2 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -19,6 +19,7 @@ use Cake\Network\Request; use Cake\Utility\Hash; use Cake\Utility\Inflector; +use CakeDC\Users\Auth\Rules\Rule; use Psr\Log\LogLevel; /** @@ -213,8 +214,8 @@ protected function _matchRule($permission, $user, $role, $request) return true; } elseif (is_callable($allowed)) { return (bool)call_user_func($allowed, $user, $role, $request); - } elseif ($allowed instanceof \CakeDC\Users\Auth\Rules\AbstractRule) { - return $allowed->allowed($user, $role, $request); + } elseif ($allowed instanceof Rule) { + return (bool)$allowed->allowed($user, $role, $request); } else { return (bool)$allowed; } From fa2eb52d5b5da6d122e214fd36379fa2c65d887b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 9 Feb 2016 08:26:05 -0500 Subject: [PATCH 0369/1476] Adding inspired --- Docs/Documentation/SocialAuthenticate.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index bb3fd2929..3da9c7e89 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -80,3 +80,5 @@ $this->User->twitterLogin(); We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. +Social Authentication was inspired by [UseMuffin/OAuth2](https://github.com/UseMuffin/OAuth2) library. + From f145e81936cd01eda64c7fccc4a84c1dadd2b65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 9 Feb 2016 13:30:56 +0000 Subject: [PATCH 0370/1476] fix broken tests --- composer.json | 8 ++++++-- tests/TestCase/Auth/SocialAuthenticateTest.php | 11 ++++++----- tests/bootstrap.php | 2 ++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 436ed31ed..ec3d24a3f 100644 --- a/composer.json +++ b/composer.json @@ -28,11 +28,15 @@ }, "require": { "php": ">=5.4.16", - "cakephp/cakephp": "~3.1", + "cakephp/cakephp": "~3.1" }, "require-dev": { "phpunit/phpunit": "*", - "cakephp/cakephp-codesniffer": "^2.0" + "cakephp/cakephp-codesniffer": "^2.0", + "league/oauth2-facebook": "@stable", + "league/oauth2-instagram": "@stable", + "league/oauth2-google": "@stable", + "league/oauth2-linkedin": "@stable" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index c42ec7165..d7a9bfcff 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -60,7 +60,7 @@ public function setUp() $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') ->setMethods(['_authenticate', '_getProviderName', '_mapUser', '_socialLogin', 'dispatchEvent']) - ->disableOriginalConstructor() + ->setConstructorArgs([$this->Registry]) ->getMock(); } @@ -161,7 +161,7 @@ public function testGetUserSessionData() $user = ['username' => 'username', 'email' => 'myemail@test.com']; $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') ->setMethods(['_authenticate', '_getProviderName', '_mapUser', '_touch']) - ->disableOriginalConstructor() + ->setConstructorArgs([$this->Registry]) ->getMock(); $session = $this->getMock('Cake\Network\Session', ['read', 'delete']); @@ -375,8 +375,9 @@ public function providerTwitter() public function testSocialLogin() { $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->disableOriginalConstructor() + ->setConstructorArgs([$this->Registry]) ->getMock(); + $reflectedClass = new ReflectionClass($this->SocialAuthenticate); $socialLogin = $reflectedClass->getMethod('_socialLogin'); $socialLogin->setAccessible(true); @@ -398,7 +399,7 @@ public function testMapUser($data, $mappedData) { $data['token'] = $this->Token; $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->disableOriginalConstructor() + ->setConstructorArgs([$this->Registry]) ->getMock(); $reflectedClass = new ReflectionClass($this->SocialAuthenticate); @@ -470,7 +471,7 @@ public function testMapUserException() { $data = []; $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->disableOriginalConstructor() + ->setConstructorArgs([$this->Registry]) ->getMock(); $reflectedClass = new ReflectionClass($this->SocialAuthenticate); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b0bbdb56c..8295913b2 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -73,6 +73,8 @@ 'defaults' => 'php' ]); +//init router +\Cake\Routing\Router::reload(); \Cake\Core\Plugin::load('CakeDC/Users', [ 'path' => dirname(dirname(__FILE__)) . DS, From c7032c3bff8eb9470fbb275d440091776511c29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 10 Feb 2016 10:58:50 +0000 Subject: [PATCH 0371/1476] fix docs for owner rule, fix condition in belongsToMany --- Docs/Documentation/OwnerRule.md | 86 +++++++++++++++++++++++ Docs/Documentation/SimpleRbacAuthorize.md | 12 +++- src/Auth/Rules/Owner.php | 15 +++- src/Auth/SimpleRbacAuthorize.php | 29 +++++--- tests/Fixture/PostsUsersFixture.php | 4 +- tests/TestCase/Auth/Rules/OwnerTest.php | 6 +- 6 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 Docs/Documentation/OwnerRule.md diff --git a/Docs/Documentation/OwnerRule.md b/Docs/Documentation/OwnerRule.md new file mode 100644 index 000000000..db98eb455 --- /dev/null +++ b/Docs/Documentation/OwnerRule.md @@ -0,0 +1,86 @@ +Owner Rule +============= + +Setup +--------------- + +SimpleRbacAuthorize will pick and use specific Rule classes (implementing the \CakeDC\Users\Auth\Rules\Rule interface). +You only need to create your own permission rules, implement the required interface and pass the instance in the +'allowed' param. + +We provide an AbstractRule you could extend too, in case you want to use rules accessing the database and using the +default table associated to the current controller. + +Owner rule configuration +----------------- + +The Owner rule can be configured to use the following options +```php + //field in the owned table matching the user_id + 'ownerForeignKey' => 'user_id', + /* + * request key type to retrieve the table id, could be "params", "query", "data" to locate the table id + * example: + * yoursite.com/controller/action/XXX would be + * tableKeyType => 'params', 'tableIdParamsKey' => 'pass.0' + * yoursite.com/controlerr/action?post_id=XXX would be + * tableKeyType => 'query', 'tableIdParamsKey' => 'post_id' + * yoursite.com/controller/action [posted form with a field named post_id] would be + * tableKeyType => 'data', 'tableIdParamsKey' => 'post_id' + */ + 'tableKeyType' => 'params', + // request->params key path to retrieve the owned table id + 'tableIdParamsKey' => 'pass.0', + /* define table to use or pick it from controller name defaults if null + * if null, table used will be based on current controller's default table + * if string, TableRegistry::get will be used + * if Table, the table object will be used + */ + 'table' => null, + 'conditions' => [], +``` + +Example: + +(in your permissions.php file) +```php +[ + 'role' => ['user'], + 'controller' => ['Posts'], + 'action' => ['edit'], + 'allowed' => new Owner([ + 'ownerForeignKey' => 'owner_id', + ]), +], +``` + +In this example, action `/posts/edit/55` will be allowed if: + * The user is logged in + * The user role is 'user' + * There is a post in posts table with id 55 + * The 'owner_id' field in the post matches the user id + +Checking ownership in belongsToMany associations +----------------- + +Let's say you have users, posts, posts_users tables, and Posts belongsToMany Users, +you could check the ownership configuring the Owner rule: +```php +[ + 'role' => ['user'], + 'controller' => ['Posts'], + 'action' => ['edit'], + 'allowed' => new Owner([ + 'table' => 'PostsUsers', + 'id' => 'post_id', + 'ownerForeignKey' => 'owner_id' + ]), +], +``` + +In this example, action `/posts/edit/55` will be allowed if: + * The user is logged in + * The user role is 'user' + * There is a row in posts_users table matching + * 'owner_id' = user id + * 'post_id' = 55 diff --git a/Docs/Documentation/SimpleRbacAuthorize.md b/Docs/Documentation/SimpleRbacAuthorize.md index 3eb2a109f..17e173465 100644 --- a/Docs/Documentation/SimpleRbacAuthorize.md +++ b/Docs/Documentation/SimpleRbacAuthorize.md @@ -59,7 +59,7 @@ Permission rules syntax 'plugin' => 'OPTIONAL_NAME_OF_THE_PLUGIN_OR_[]_OR_*_DEFAULT_NULL', 'controller' => 'REQUIRED_NAME_OF_THE_CONTROLLER_OR_[]_OR_*' 'action' => 'REQUIRED_NAME_OF_ACTION_OR_[]_OR_*', - 'allowed' => 'OPTIONAL_BOOLEAN_OR_CALLABLE_DEFAULT_TRUE' + 'allowed' => 'OPTIONAL_BOOLEAN_OR_CALLABLE_OR_INSTANCE_OF_RULE_DEFAULT_TRUE' ] ``` * If no rule allowed = true is matched for a given user role and url, default return value will be false @@ -85,3 +85,13 @@ Example *ownership* callback, to allow users to edit their own Posts: return false; } ``` + +Permission Rules +---------------- +You could use an instance of the \CakeDC\Users\Auth\Rules\Rule interface to reuse your custom rules +Examples: +```php +'allowed' => new Owner() //will pick by default the post id from the first pass param +``` +Check the [Owner Rule](OwnerRule.md) documentation for more details + diff --git a/src/Auth/Rules/Owner.php b/src/Auth/Rules/Owner.php index 0f52a1338..5be38835c 100644 --- a/src/Auth/Rules/Owner.php +++ b/src/Auth/Rules/Owner.php @@ -36,12 +36,19 @@ class Owner extends AbstractRule 'tableKeyType' => 'params', // request->params key path to retrieve the owned table id 'tableIdParamsKey' => 'pass.0', - /* define table to use or pick it from controller name defaults if null + /* + * define table to use or pick it from controller name defaults if null * if null, table used will be based on current controller's default table * if string, TableRegistry::get will be used * if Table, the table object will be used */ 'table' => null, + /* + * define the table id to be used to match the row id, this is useful when checking belongsToMany associations + * Example: If checking ownership in a PostsUsers table, we should use 'id' => 'post_id' + * If value is null, we'll use the $table->primaryKey() + */ + 'id' => null, 'conditions' => [], ]; @@ -62,8 +69,12 @@ public function allowed(array $user, $role, Request $request) } catch (Exception $ex) { throw new OutOfBoundsException(__d('Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); } + $idColumn = $this->config('id'); + if (empty($idColumn)) { + $idColumn = $table->primaryKey(); + } $conditions = array_merge([ - $table->primaryKey() => $id, + $idColumn => $id, $this->config('ownerForeignKey') => $userId ], $this->config('conditions')); diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 85c5913c2..612ccc3a7 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Auth; +use CakeDC\Users\Auth\Rules\Rule; use Cake\Auth\BaseAuthorize; use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; @@ -19,7 +20,6 @@ use Cake\Network\Request; use Cake\Utility\Hash; use Cake\Utility\Inflector; -use CakeDC\Users\Auth\Rules\Rule; use Psr\Log\LogLevel; /** @@ -56,19 +56,26 @@ class SimpleRbacAuthorize extends BaseAuthorize * - ownership * - permissions stored in your database * - permission based on an external service API call - * Example ownership callback, to allow users to edit their own Posts: + * You could use an instance of the \CakeDC\Users\Auth\Rules\Rule interface to reuse your custom rules + * + * Examples: + * 1. Callback to allow users editing their own Posts: * * 'allowed' => function (array $user, $role, Request $request) { - $postId = Hash::get($request->params, 'pass.0'); - $post = TableRegistry::get('Posts')->get($postId); - $userId = Hash::get($user, 'id'); - if (!empty($post->user_id) && !empty($userId)) { - return $post->user_id === $userId; - } - return false; - } + * $postId = Hash::get($request->params, 'pass.0'); + * $post = TableRegistry::get('Posts')->get($postId); + * $userId = Hash::get($user, 'id'); + * if (!empty($post->user_id) && !empty($userId)) { + * return $post->user_id === $userId; + * } + * return false; + * } + * 2. Using the Owner Rule + * 'allowed' => new Owner() //will pick by default the post id from the first pass param + * + * Check the Owner Rule docs for more details + * * - * Suggestion: put your rules into a specific config file */ 'permissions' => [], ]; diff --git a/tests/Fixture/PostsUsersFixture.php b/tests/Fixture/PostsUsersFixture.php index 9227398ab..f4cea2af2 100644 --- a/tests/Fixture/PostsUsersFixture.php +++ b/tests/Fixture/PostsUsersFixture.php @@ -47,12 +47,12 @@ class PostsUsersFixture extends TestFixture */ public $records = [ [ - 'id' => '00000000-0000-0000-0000-000000000001', + 'id' => '00000000-0000-0000-0000-000000000011', 'user_id' => '00000000-0000-0000-0000-000000000001', 'post_id' => '00000000-0000-0000-0000-000000000001', ], [ - 'id' => '00000000-0000-0000-0000-000000000002', + 'id' => '00000000-0000-0000-0000-000000000012', 'user_id' => '00000000-0000-0000-0000-000000000002', 'post_id' => '00000000-0000-0000-0000-000000000002', ], diff --git a/tests/TestCase/Auth/Rules/OwnerTest.php b/tests/TestCase/Auth/Rules/OwnerTest.php index aa320cf36..eac550ec8 100644 --- a/tests/TestCase/Auth/Rules/OwnerTest.php +++ b/tests/TestCase/Auth/Rules/OwnerTest.php @@ -225,7 +225,8 @@ public function testNotAllowedBecauseNoDefaultTable() public function testAllowedBelongsToMany() { $this->Owner = new Owner([ - 'table' => 'PostsUsers' + 'table' => 'PostsUsers', + 'id' => 'post_id', ]); $this->request->params = [ 'plugin' => 'CakeDC/Users', @@ -246,7 +247,8 @@ public function testAllowedBelongsToMany() public function testNotAllowedBelongsToMany() { $this->Owner = new Owner([ - 'table' => 'PostsUsers' + 'table' => 'PostsUsers', + 'id' => 'post_id', ]); $this->request->params = [ 'plugin' => 'CakeDC/Users', From f2dd1fa3f472f9c04a54c5c51e10098a3c56baa2 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 11 Feb 2016 18:14:16 -0500 Subject: [PATCH 0372/1476] Fixing broken tests --- src/Auth/SocialAuthenticate.php | 24 +++-- .../TestCase/Auth/SocialAuthenticateTest.php | 78 +++++++--------- .../Controller/Traits/LoginTraitTest.php | 24 +++-- .../Controller/Traits/SocialTraitTest.php | 90 ++++++++++++++++++- tests/bootstrap.php | 1 - 5 files changed, 152 insertions(+), 65 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 2ac88c9b5..b964f43c7 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -122,8 +122,8 @@ protected function _normalizeConfig(&$config, $alias, $parent) * @param mixed $value Value. * @param string $key Key. * @return void - * @throws \Muffin\OAuth2\Auth\Exception\InvalidProviderException - * @throws \Muffin\OAuth2\Auth\Exception\InvalidSettingsException + * @throws CakeDC\Users\Auth\Exception\InvalidProviderException + * @throws CakeDC\Users\Auth\Exception\InvalidSettingsException */ protected function _validateConfig(&$value, $key) { @@ -134,6 +134,16 @@ protected function _validateConfig(&$value, $key) } } + /** + * Get the controller associated with the collection. + * + * @return Controller instance + */ + protected function _getController() + { + $this->_registry->getController(); + } + /** * Get a user based on information in the request. * @@ -306,10 +316,9 @@ protected function _touch(array $data) $args = ['exception' => $exception, 'rawData' => $data]; $event = new Event(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, $args); $event = EventManager::instance()->dispatch($event); - if (method_exists($this->_registry->getController(), 'failedSocialLogin')) { - $this->_registry->getController()->failedSocialLogin($exception, $data, true); + if (method_exists($this->_getController(), 'failedSocialLogin')) { + $this->_getController()->failedSocialLogin($exception, $data, true); } - return $event->result; } @@ -358,7 +367,10 @@ public function getUser(Request $request) if (!$result = $this->_touch($user)) { return false; } - $request->session()->delete(Configure::read('Users.Key.Session.social')); + + if ($request->session()->check(Configure::read('Users.Key.Session.social'))) { + $request->session()->delete(Configure::read('Users.Key.Session.social')); + } return $result; } diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index d7a9bfcff..babfae221 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -52,16 +52,17 @@ public function setUp() $this->controller = $this->getMock( 'Cake\Controller\Controller', - null, + ['failedSocialLogin'], [$request, $response] ); + $this->Request = $request; - $this->Registry = new ComponentRegistry($this->controller); + $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', '_getProviderName', + '_mapUser', '_socialLogin', 'dispatchEvent', '_validateConfig', '_getController']); - $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->setMethods(['_authenticate', '_getProviderName', '_mapUser', '_socialLogin', 'dispatchEvent']) - ->setConstructorArgs([$this->Registry]) - ->getMock(); + $this->SocialAuthenticate->expects($this->any()) + ->method('_getController') + ->will($this->returnValue($this->controller)); } /** @@ -73,6 +74,21 @@ 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 getUser * @@ -159,10 +175,8 @@ public function providerGetUser() public function testGetUserSessionData() { $user = ['username' => 'username', 'email' => 'myemail@test.com']; - $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->setMethods(['_authenticate', '_getProviderName', '_mapUser', '_touch']) - ->setConstructorArgs([$this->Registry]) - ->getMock(); + $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', + '_getProviderName', '_mapUser', '_touch', '_validateConfig' ]); $session = $this->getMock('Cake\Network\Session', ['read', 'delete']); $session->expects($this->once()) @@ -210,15 +224,10 @@ public function testGetUserNotEmailProvided($rawData, $mapper) ->method('_socialLogin') ->will($this->throwException(new MissingEmailException('missing email'))); - $event = new Event('ExceptionEvent'); - $event->result = 'result'; - - $this->SocialAuthenticate->expects($this->once()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); + $this->controller->expects($this->once()) + ->method('failedSocialLogin'); - $result = $this->SocialAuthenticate->getUser($this->Request); - $this->assertEquals($result, 'result'); + $this->SocialAuthenticate->getUser($this->Request); } /** @@ -245,15 +254,7 @@ public function testGetUserNotActive($rawData, $mapper) ->method('_socialLogin') ->will($this->throwException(new UserNotActiveException('user not active'))); - $event = new Event('ExceptionEvent'); - $event->result = 'result'; - - $this->SocialAuthenticate->expects($this->once()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); - - $result = $this->SocialAuthenticate->getUser($this->Request); - $this->assertEquals($result, 'result'); + $this->SocialAuthenticate->getUser($this->Request); } /** @@ -280,22 +281,13 @@ public function testGetUserNotActiveAccount($rawData, $mapper) ->method('_socialLogin') ->will($this->throwException(new AccountNotActiveException('user not active'))); - $event = new Event('ExceptionEvent'); - $event->result = 'result'; - - $this->SocialAuthenticate->expects($this->once()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); - - $result = $this->SocialAuthenticate->getUser($this->Request); - $this->assertEquals($result, 'result'); + $this->SocialAuthenticate->getUser($this->Request); } /** * Test getUser * * @dataProvider providerTwitter - * @expectedException CakeDC\Users\Exception\MissingEmailException */ public function testGetUserNotEmailProvidedTwitter($rawData, $mapper) { @@ -374,9 +366,7 @@ public function providerTwitter() */ public function testSocialLogin() { - $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->setConstructorArgs([$this->Registry]) - ->getMock(); + $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); $reflectedClass = new ReflectionClass($this->SocialAuthenticate); $socialLogin = $reflectedClass->getMethod('_socialLogin'); @@ -398,9 +388,7 @@ public function testSocialLogin() public function testMapUser($data, $mappedData) { $data['token'] = $this->Token; - $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->setConstructorArgs([$this->Registry]) - ->getMock(); + $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); $reflectedClass = new ReflectionClass($this->SocialAuthenticate); $mapUser = $reflectedClass->getMethod('_mapUser'); @@ -470,9 +458,7 @@ public function providerMapper() public function testMapUserException() { $data = []; - $this->SocialAuthenticate = $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->setConstructorArgs([$this->Registry]) - ->getMock(); + $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); $reflectedClass = new ReflectionClass($this->SocialAuthenticate); $mapUser = $reflectedClass->getMethod('_mapUser'); diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index a380837d1..e60b6db8d 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -40,6 +40,12 @@ public function setUp() $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') ->setMethods(['dispatchEvent', 'redirect']) ->getMockForTrait(); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['config']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->request = $request; } @@ -64,7 +70,7 @@ public function testLoginHappy() $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') ->setMethods(['is']) ->getMock(); - $this->Trait->request->expects($this->once()) + $this->Trait->request->expects($this->any()) ->method('is') ->with('post') ->will($this->returnValue(true)); @@ -102,7 +108,7 @@ public function testAfterIdentifyEmptyUser() $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') ->setMethods(['is']) ->getMock(); - $this->Trait->request->expects($this->once()) + $this->Trait->request->expects($this->any()) ->method('is') ->with('post') ->will($this->returnValue(true)); @@ -146,12 +152,6 @@ public function testAfterIdentifyEmptyUserSocialLogin() ->disableOriginalConstructor() ->getMock(); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with([ - 'action' => 'social-email' - ]); - $this->Trait->login(); } @@ -320,6 +320,14 @@ public function testFailedSocialUserNotActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Trait->Auth->expects($this->at(0)) + ->method('config') + ->with('authError', 'Your user has not been validated yet. Please check your inbox for instructions'); + + $this->Trait->Auth->expects($this->at(1)) + ->method('config') + ->with('flash.params', ['class' => 'success']); + $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 0d0d95d49..e5e02bbf5 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -30,7 +30,7 @@ public function setUp() true, true, true, - ['_getOpauthInstance', 'redirect', '_generateOpauthCompleteUrl'] + ['_getOpauthInstance', 'redirect', '_generateOpauthCompleteUrl', '_afterIdentifyUser', '_validateRegisterPost'] ); } @@ -45,14 +45,18 @@ public function tearDown() */ public function testSocialEmail() { - $session = $this->getMock('Cake\Network\Session', ['check']); - $session->expects($this->once()) + $session = $this->getMock('Cake\Network\Session', ['check', 'delete']); + $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->getMock('Cake\Network\Request', ['session']); - $this->controller->Trait->request->expects($this->once()) + $this->controller->Trait->request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); @@ -79,4 +83,82 @@ public function testSocialEmailInvalid() $this->controller->Trait->socialEmail(); } + + public function testSocialEmailPostValidateFalse() + { + $session = $this->getMock('Cake\Network\Session', ['check', 'delete']); + $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->getMock('Cake\Network\Request', ['session', 'is']); + $this->controller->Trait->request->expects($this->any()) + ->method('session') + ->will($this->returnValue($session)); + + $this->controller->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + + $this->controller->Trait->expects($this->once()) + ->method('_validateRegisterPost') + ->will($this->returnValue(false)); + + $this->controller->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) + ->disableOriginalConstructor() + ->getMock(); + + $this->controller->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The reCaptcha could not be validated'); + + $this->controller->Trait->socialEmail(); + } + + public function testSocialEmailPostValidateTrue() + { + $session = $this->getMock('Cake\Network\Session', ['check', 'delete']); + $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->getMock('Cake\Network\Request', ['session', 'is']); + $this->controller->Trait->request->expects($this->any()) + ->method('session') + ->will($this->returnValue($session)); + + $this->controller->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + + $this->controller->Trait->expects($this->once()) + ->method('_validateRegisterPost') + ->will($this->returnValue(true)); + + $this->controller->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['identify']) + ->disableOriginalConstructor() + ->getMock(); + + $this->controller->Trait->Auth->expects($this->once()) + ->method('identify'); + + $this->controller->Trait->expects($this->once()) + ->method('_afterIdentifyUser'); + + $this->controller->Trait->socialEmail(); + } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 8295913b2..5a21395a9 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -20,7 +20,6 @@ unset($findRoot); chdir($root); -define('DS', DIRECTORY_SEPARATOR); define('ROOT', $root); define('APP_DIR', 'App'); define('WEBROOT_DIR', 'webroot'); From 971203ad4a85ce657a0191c9944d8ae1f90f9a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 12 Feb 2016 10:19:59 +0000 Subject: [PATCH 0373/1476] fix missing DS --- tests/bootstrap.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 5a21395a9..e94f7f148 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -20,6 +20,9 @@ unset($findRoot); chdir($root); +if (!defined('DS')) { + define('DS', DIRECTORY_SEPARATOR); +} define('ROOT', $root); define('APP_DIR', 'App'); define('WEBROOT_DIR', 'webroot'); From 0efa39663c6ad78ed7e74cb967a4fcb57e99de43 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 12 Feb 2016 10:02:05 -0500 Subject: [PATCH 0374/1476] Improving documentation --- Docs/Documentation/Installation.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 6a5cafde6..6ebe9d27a 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -56,7 +56,7 @@ Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); Configure::write('Users.Social.login', true); //to enable social login ``` -Then in your config/users.php +Then in your config/users.php if you are using social login features ``` return [ 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', @@ -67,7 +67,6 @@ return [ ]; ``` - For more details, check the Configuration doc page Load the UsersAuth Component From 070bb60f5dc8c31fe7b7f117cb342bb6f569e6db Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 12 Feb 2016 12:33:52 -0500 Subject: [PATCH 0375/1476] Adding missing use --- src/Template/Users/register.ctp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index 773ed5fc8..f217de2f4 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -8,6 +8,7 @@ * @copyright Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +use Cake\Core\Configure; ?>

Form->create($user); ?> From 4584789bc4561878973c989083c17e0780403689 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 12 Feb 2016 12:34:27 -0500 Subject: [PATCH 0376/1476] Validation empty cookie --- src/Auth/RememberMeAuthenticate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Auth/RememberMeAuthenticate.php b/src/Auth/RememberMeAuthenticate.php index 3ae70dff7..c83bfc220 100644 --- a/src/Auth/RememberMeAuthenticate.php +++ b/src/Auth/RememberMeAuthenticate.php @@ -33,10 +33,10 @@ class RememberMeAuthenticate extends BaseAuthenticate public function authenticate(Request $request, Response $response) { $cookieName = Configure::read('Users.RememberMe.Cookie.name'); - if (!$this->_registry->Cookie->check($cookieName)) { + $cookie = $this->_registry->Cookie->read($cookieName); + if (empty($cookie)) { return false; } - $cookie = $this->_registry->Cookie->read($cookieName); $this->config('fields.username', 'id'); $user = $this->_findUser($cookie['id']); if ($user && From d574311d68613c90585c30696f0dc7c811dcd0e0 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 12 Feb 2016 12:36:24 -0500 Subject: [PATCH 0377/1476] Fixing return in method --- src/Auth/SocialAuthenticate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index b964f43c7..c4dc681bf 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -141,7 +141,7 @@ protected function _validateConfig(&$value, $key) */ protected function _getController() { - $this->_registry->getController(); + return $this->_registry->getController(); } /** From fb981986fcb8969ed8729fdf58501225113c2679 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 12 Feb 2016 12:40:33 -0500 Subject: [PATCH 0378/1476] Making twitter credentials name consistent with other providers credentials name --- src/Controller/Traits/LoginTrait.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 493257e22..6fcd9231e 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -39,8 +39,8 @@ public function twitterLogin() $this->autoRender = false; $server = new Twitter([ - 'identifier' => Configure::read('OAuth.providers.twitter.options.identifier'), - 'secret' => Configure::read('OAuth.providers.twitter.options.secret'), + 'identifier' => Configure::read('OAuth.providers.twitter.options.clientId'), + 'secret' => Configure::read('OAuth.providers.twitter.options.clientSecret'), 'callbackUri' => Configure::read('OAuth.providers.twitter.options.redirectUri'), ]); $oauthToken = $this->request->query('oauth_token'); @@ -99,6 +99,7 @@ public function failedSocialLogin($exception, $data, $flash = false) $this->Flash->success(__d('Users', 'Please enter your email')); } $this->request->session()->write(Configure::read('Users.Key.Session.social'), $data); + //$flash = false; return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); } if ($exception instanceof UserNotActiveException) { @@ -107,12 +108,13 @@ public function failedSocialLogin($exception, $data, $flash = false) $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); } } - if ($flash) { + /*if ($flash) { $this->Auth->config('authError', $msg); $this->Auth->config('flash.params', ['class' => 'success']); $this->request->session()->delete(Configure::read('Users.Key.Session.social')); + debug('delete 1'); die; $this->Flash->success(__d('Users', $msg)); - } + }*/ return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } From 4a65186ae5691023ad3761ba3ae6fa1a1e0b723d Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 12 Feb 2016 12:48:48 -0500 Subject: [PATCH 0379/1476] Fixing rememberme authenticate tests --- .../Auth/RememberMeAuthenticateTest.php | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php index 960a573c2..150e00f37 100644 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -72,11 +72,6 @@ public function testAuthenticateHappy() ->disableOriginalConstructor() ->setMethods(['check', 'read']) ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('check') - ->with('remember_me') - ->will($this->returnValue(true)); $mockCookie ->expects($this->once()) ->method('read') @@ -105,11 +100,6 @@ public function testAuthenticateBadUser() ->disableOriginalConstructor() ->setMethods(['check', 'read']) ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('check') - ->with('remember_me') - ->will($this->returnValue(true)); $mockCookie ->expects($this->once()) ->method('read') @@ -140,11 +130,6 @@ public function testAuthenticateBadAgent() ->disableOriginalConstructor() ->setMethods(['check', 'read']) ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('check') - ->with('remember_me') - ->will($this->returnValue(true)); $mockCookie ->expects($this->once()) ->method('read') @@ -175,12 +160,9 @@ public function testAuthenticateNoCookie() ->getMock(); $mockCookie ->expects($this->once()) - ->method('check') + ->method('read') ->with('remember_me') - ->will($this->returnValue(false)); - $mockCookie - ->expects($this->never()) - ->method('read'); + ->will($this->returnValue(null)); $registry = new ComponentRegistry($this->controller); $registry->set('Cookie', $mockCookie); From 68fd64d342a96210a71dd2991860983023786684 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 12 Feb 2016 12:51:47 -0500 Subject: [PATCH 0380/1476] Fixing code pushed by mistake --- src/Controller/Traits/LoginTrait.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 6fcd9231e..e6ba296b0 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -99,7 +99,6 @@ public function failedSocialLogin($exception, $data, $flash = false) $this->Flash->success(__d('Users', 'Please enter your email')); } $this->request->session()->write(Configure::read('Users.Key.Session.social'), $data); - //$flash = false; return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); } if ($exception instanceof UserNotActiveException) { @@ -108,13 +107,12 @@ public function failedSocialLogin($exception, $data, $flash = false) $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); } } - /*if ($flash) { + if ($flash) { $this->Auth->config('authError', $msg); $this->Auth->config('flash.params', ['class' => 'success']); $this->request->session()->delete(Configure::read('Users.Key.Session.social')); - debug('delete 1'); die; $this->Flash->success(__d('Users', $msg)); - }*/ + } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } From 038918d3087b8069c2624bb9488e858b1eb0da7e Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 12 Feb 2016 13:04:48 -0500 Subject: [PATCH 0381/1476] Fixing mailer --- Docs/Documentation/Configuration.md | 13 +++++++++---- src/Mailer/UsersMailer.php | 6 ++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 70ebecc19..cd52f7278 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -21,23 +21,28 @@ Then in your config/users.php 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5' + 'redirectUri' => Router::url('/auth/facebook', true) ] - 'redirectUri' => Router::url('/auth/facebook', true) ], 'linkedIn' => [ 'className' => 'League\OAuth2\Client\Provider\LinkedIn', - 'redirectUri' => Router::url('/auth/linkedIn', true) + 'options' => [ + 'redirectUri' => Router::url('/auth/linkedIn', true) + ] ], 'instagram' => [ 'className' => 'League\OAuth2\Client\Provider\Instagram', - 'redirectUri' => Router::url('/auth/instagram', true) + 'options' => [ + 'redirectUri' => Router::url('/auth/instagram', true) + ] ], 'google' => [ 'className' => 'League\OAuth2\Client\Provider\Google', 'options' => [ 'userFields' => ['url', 'aboutMe'], + 'redirectUri' => Router::url('/auth/google', true) ] - 'redirectUri' => Router::url('/auth/google', true) + ] //etc ], diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 4f51359a5..b7d33c5b9 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -64,10 +64,11 @@ protected function resetPassword(EntityInterface $user, $template = 'CakeDC/User * * @param EntityInterface $user User entity * @param EntityInterface $socialAccount SocialAccount entity + * @param string $template string, note the first_name of the user will be prepended if exists * * @return array email send result */ - protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount) + protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount, $template = 'CakeDC/Users.social_account_validation') { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; //note: we control the space after the username in the previous line @@ -75,6 +76,7 @@ protected function socialAccountValidation(EntityInterface $user, EntityInterfac $this ->to($user['email']) ->subject($subject) - ->viewVars(compact('user', 'socialAccount')); + ->viewVars(compact('user', 'socialAccount')) + ->template($template); } } From 2eff35619eaf36069697450581a3f43ac8b1d4ef Mon Sep 17 00:00:00 2001 From: jorge gonzalez Date: Mon, 15 Feb 2016 16:23:17 +0000 Subject: [PATCH 0382/1476] fix twitter login redirect, add message to recaptcha --- src/Controller/Traits/LoginTrait.php | 2 +- src/View/Helper/UserHelper.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index e6ba296b0..9f9caa2a6 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -37,7 +37,6 @@ trait LoginTrait 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'), @@ -72,6 +71,7 @@ public function twitterLogin() $temporaryCredentials = $server->getTemporaryCredentials(); $this->request->session()->write('temporary_credentials', $temporaryCredentials); $server->authorize($temporaryCredentials); + return $this->response; } } /** diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 533ddd6f4..735fe4047 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -147,7 +147,9 @@ public function addReCaptcha() if (!Configure::read('Users.Registration.reCaptcha')) { return false; } - + if (!Configure::read('reCaptcha.key')) { + return $this->Html->tag('p', __d('Users', 'reCaptcha is not configured! Please configure reCaptcha.key or set Users.Registration.reCaptcha to false')); + } $this->Form->unlockField('g-recaptcha-response'); return $this->Html->tag('div', '', [ 'class' => 'g-recaptcha', From afea93e125e7334009f4a9bba99a3dcd498013ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 15 Feb 2016 16:43:08 +0000 Subject: [PATCH 0383/1476] update docs social config --- Docs/Documentation/Configuration.md | 54 ++++++------------------ Docs/Documentation/Installation.md | 17 +++++--- Docs/Documentation/SocialAuthenticate.md | 26 +++--------- 3 files changed, 28 insertions(+), 69 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index cd52f7278..82883a14f 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -12,56 +12,28 @@ Configure::write('Users.config', ['users']); Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); Configure::write('Users.Social.login', true); //to enable social login ``` - -Then in your config/users.php - -``` -'Opauth.providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.5' - 'redirectUri' => Router::url('/auth/facebook', true) - ] - ], - 'linkedIn' => [ - 'className' => 'League\OAuth2\Client\Provider\LinkedIn', - 'options' => [ - 'redirectUri' => Router::url('/auth/linkedIn', true) - ] - ], - 'instagram' => [ - 'className' => 'League\OAuth2\Client\Provider\Instagram', - 'options' => [ - 'redirectUri' => Router::url('/auth/instagram', true) - ] - ], - 'google' => [ - 'className' => 'League\OAuth2\Client\Provider\Google', - 'options' => [ - 'userFields' => ['url', 'aboutMe'], - 'redirectUri' => Router::url('/auth/google', true) - ] - - ] - //etc - ], - -``` Configuration for social login --------------------- -Create the facebook/twitter applications you want to use and setup the configuration like this: +Create the facebook, twitter, etc applications you want to use and setup the configuration like this: +In this example, we are using 2 providers: facebook and twitter. Note you'll need to add the providers to +your composer.json file. + +``` +$ composer require league/oauth2-facebook:@stable +$ composer require league/oauth1-client:@stable +``` + +NOTE: twitter uses league/oauth1-client package config/bootstrap.php ``` Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); -Configure::write('OAuth.providers.instagram.options.clientId', 'YOUR APP ID'); -Configure::write('OAuth.providers.instagram.options.clientSecret', 'YOUR APP SECRET'); - +Configure::write('OAuth.providers.twitter.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'); ``` Or use the config override option when loading the plugin (see above) @@ -73,7 +45,7 @@ The plugin is configured via the Configure class. Check the `vendor/cakedc/users 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 Opauth component for your application. +the AuthComponent and the OAuth component for your application. If you prefer to setup AuthComponent by yourself, you'll need to load AuthComponent before UsersAuthComponent and set diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 0e6e89caa..a586c144c 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -11,10 +11,11 @@ composer require cakedc/users if you want to use social login features... ``` -composer require league/oauth2-facebook:* -composer require league/oauth2-instagram:* -composer require league/oauth2-google:* -composer require league/oauth2-linkedin:* +composer require league/oauth2-facebook:@stable +composer require league/oauth2-instagram::@stable +composer require league/oauth2-google::@stable +composer require league/oauth2-linkedin::@stable +composer require league/oauth1-client:@stable ``` NOTE: you'll need to enable social login in your bootstrap.php file if you want to use it, social @@ -55,18 +56,20 @@ Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); Configure::write('Users.Social.login', true); //to enable social login ``` -Then in your config/users.php +If you want to use social login, then in your config/users.php ``` return [ 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', 'OAuth.providers.facebook.options.clientSecret' => 'YOUR APP SECRET', - 'OAuth.providers.instagram.options.clientId' => 'YOUR APP ID', - 'OAuth.providers.instagram.options.clientSecret' => 'YOUR APP SECRET', + 'OAuth.providers.twitter.options.clientId' => 'YOUR APP ID', + 'OAuth.providers.titter.options.clientSecret' => 'YOUR APP SECRET', //etc ]; ``` +Note: using social authentication is not required. + For more details, check the Configuration doc page Load the UsersAuth Component diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index 3da9c7e89..602611076 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -8,11 +8,11 @@ Create the Facebook/Twitter applications you want to use and setup the configura Config/bootstrap.php ``` -Configure::write('Opauth.Strategy.Facebook.app_id', 'YOUR APP ID'); -Configure::write('Opauth.Strategy.Facebook.app_secret', 'YOUR APP SECRET'); +Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); -Configure::write('Opauth.Strategy.Twitter.key', 'YOUR APP KEY'); -Configure::write('Opauth.Strategy.Twitter.secret', 'YOUR APP SECRET'); +Configure::write('OAuth.providers.twitter.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'); ``` You can also change the default settings for social authenticate: @@ -47,24 +47,8 @@ Configure::write('Users', [ ``` 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). -``` -Configure::write('Opauth', [ - 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'opauthInit'], - 'callback_url' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'opauthInit', 'callback'], - 'complete_url' => ['admin' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], - 'Strategy' => [ - 'Facebook' => [ - 'scope' => ['public_profile', 'user_friends', 'email'] - ], - 'Twitter' => [ - 'curl_cainfo' => false, - 'curl_capath' => false - ] - ] -]); -``` -In most situations you would not need to change any Opauth setting besides applications details. +In most situations you would not need to change any Oauth setting besides applications details. User Helper --------------------- From 7d12b972ce93ba4183989938997881c6133d52a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 15 Feb 2016 16:50:35 +0000 Subject: [PATCH 0384/1476] fix phpcs --- src/Auth/Social/Mapper/Google.php | 1 + src/Auth/SocialAuthenticate.php | 12 ++++++------ src/Controller/Traits/LoginTrait.php | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Auth/Social/Mapper/Google.php b/src/Auth/Social/Mapper/Google.php index 843cf75bb..86e0717b8 100644 --- a/src/Auth/Social/Mapper/Google.php +++ b/src/Auth/Social/Mapper/Google.php @@ -10,6 +10,7 @@ */ namespace CakeDC\Users\Auth\Social\Mapper; + use Cake\Utility\Hash; /** diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index c4dc681bf..a18c7e5e9 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -11,12 +11,6 @@ namespace CakeDC\Users\Auth; -use Cake\Auth\BaseAuthenticate; -use Cake\Event\Event; -use Cake\Event\EventDispatcherTrait; -use Cake\Event\EventManager; -use Cake\Network\Response; -use Cake\Utility\Hash; use CakeDC\Users\Auth\Exception\InvalidProviderException; use CakeDC\Users\Auth\Exception\InvalidSettingsException; use CakeDC\Users\Auth\Exception\MissingProviderConfigurationException; @@ -27,10 +21,16 @@ use CakeDC\Users\Exception\MissingProviderException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Model\Table\SocialAccountsTable; +use Cake\Auth\BaseAuthenticate; use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; +use Cake\Event\Event; +use Cake\Event\EventDispatcherTrait; +use Cake\Event\EventManager; use Cake\Network\Request; +use Cake\Network\Response; use Cake\ORM\TableRegistry; +use Cake\Utility\Hash; /** * Class SocialAuthenticate diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 9f9caa2a6..f557d5cbc 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -15,10 +15,10 @@ use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; use Cake\Event\Event; use Cake\Network\Exception\NotFoundException; -use CakeDC\Users\Model\Table\SocialAccountsTable; use League\OAuth1\Client\Server\Twitter; /** From 788ffc61c0053a83b0a83afe78778f5a3d2f7f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 15 Feb 2016 16:59:35 +0000 Subject: [PATCH 0385/1476] update docs --- .semver | 2 +- CHANGELOG.md | 73 +++++++++++++++++++--------------------------------- README.md | 22 +++------------- 3 files changed, 31 insertions(+), 66 deletions(-) diff --git a/.semver b/.semver index abcaef42f..63e74f429 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 3 :minor: 1 -:patch: 4 +:patch: 5 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 85b29decc..502f4841e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,61 +1,42 @@ Changelog ========= -Release 2.1.3 +Releases for CakePHP 3 ------------- -https://github.com/CakeDC/users/tree/2.1.3 +* 3.1.5 + * SocialAuthenticate improvements + * Authorize Rules. Owner rule + * Docs improvements -* Fixed unit tests for compatibility with CakePHP 2.7 +* 3.1.4 + * SocialAuthenticate refactored to drop Opauth in favor of Muffin/OAuth2 and league/oauth2 -Release 2.1.2 -------------- +* 3.1.3 + * UserHelper improvements -https://github.com/CakeDC/users/tree/2.1.2 +* 3.1.2 + * Fixes in RBAC permission matchers -* Minor improvements -* New translations (german and portuguese) +* 3.1.0 Migration to CakePHP 3.0 + * Unit test coverage improvements + * Refactor UsersTable to Behavior + * Add google authentication + * Add reCaptcha + * Link social accounts in profile -Release 2.1.1 +Releases for CakePHP 2 ------------- -https://github.com/CakeDC/users/tree/2.1.1 - - * [73aa350](https://github.com/cakedc/users/commit/73aa350) Fixing an issue with pagination settings for the admin_index() - * [3dd162d](https://github.com/cakedc/users/commit/3dd162d) Forgot password translation - * [09499fb](https://github.com/cakedc/users/commit/09499fb) Fixing some strings in the AllUsersTest.php to make sure the naming is correct - * [83f502b](https://github.com/cakedc/users/commit/83f502b) Changing the handling of the return_to parameter in the UsersController - * [3e9a378](https://github.com/cakedc/users/commit/3e9a378) Refs https://github.com/CakeDC/users/issues/189 Fixing the Email default "from" setting, some CS fixes and some code refactoring as well - * [d0f330e](https://github.com/cakedc/users/commit/d0f330e) Update Installation.md +* 2.1.3 + * Fixed unit tests for compatibility with CakePHP 2.7 +* 2.1.2 + * Minor improvements + * New translations (german and portuguese) -Release 2.1.0 -------------- +* 2.1.1 + * Forgot password -https://github.com/CakeDC/users/tree/2.1.0 - - * [aa5b58d](https://github.com/CakeDC/users/commit/aa5b58d) Fixing the PrgComponent mock so that the plugin tests work until the fix for the 2nd arg of the PrgConstuctor appears in the master branch. - * [f4f0726](https://github.com/CakeDC/users/commit/f4f0726) Fixing tests and working on the documentation - * [4b0b210](https://github.com/CakeDC/users/commit/4b0b210) Replacing Set with Hash - * [f9c07ec](https://github.com/CakeDC/users/commit/f9c07ec) Adding information about the legacy user details to the documentation - * [50f0597](https://github.com/CakeDC/users/commit/50f0597) Adding semver and CONTRIBUTING.md - * [a4e6a95](https://github.com/CakeDC/users/commit/a4e6a95) Fixing https://github.com/CakeDC/users/pull/174 - * [3a66dd2](https://github.com/CakeDC/users/commit/3a66dd2) Fixing some upper cased controller names in sidebar.ctp which causes the urls to not work - * [29537ad](https://github.com/CakeDC/users/commit/29537ad) Changing .travis and updating composer.json - * [effa068](https://github.com/CakeDC/users/commit/effa068) Fixing typo in error message - * [835a2a5](https://github.com/CakeDC/users/commit/835a2a5) Fixing missing ' in the readme.md - * [33b7029](https://github.com/CakeDC/users/commit/33b7029) Removed testTest - * [69b901e](https://github.com/CakeDC/users/commit/69b901e) Controller Test Fixed - * [aea36c3](https://github.com/CakeDC/users/commit/aea36c3) Fix testEditPassword - * [c07e7c6](https://github.com/CakeDC/users/commit/c07e7c6) Updated deprecated assertEqual - * [c62aa19](https://github.com/CakeDC/users/commit/c62aa19) Formatting fixes - * [f53b19c](https://github.com/CakeDC/users/commit/f53b19c) User password edit / unit tests - * [b63001b](https://github.com/CakeDC/users/commit/b63001b) Redundant Cookie::destroy() - * [eea58c1](https://github.com/CakeDC/users/commit/eea58c1) Added missing dependency (Utils Plugin) - * [4c08b47](https://github.com/CakeDC/users/commit/4c08b47) Changed portuguese translation path and fixed some strings - * [3caf6db](https://github.com/CakeDC/users/commit/3caf6db) Fixed some linting issues - * [226e3a4](https://github.com/CakeDC/users/commit/226e3a4) Code typos in readme - * [f93ce41](https://github.com/CakeDC/users/commit/f93ce41) Minor improvement to the flash message that shows the username in the UsersController.php - * [b6ee0ad](https://github.com/CakeDC/users/commit/b6ee0ad) Refs https://github.com/CakeDC/users/issues/145, fixing the links in the sidebar when not used from the plugin - * [720ebb5](https://github.com/CakeDC/users/commit/720ebb5) Refs https://github.com/CakeDC/users/pull/146 - * [46d6321](https://github.com/CakeDC/users/commit/46d6321) Renamed locale fre => fra, since 2.3 CakePHP uses ISO standard. +* 2.1.0 + * Bugfixes and improvements \ No newline at end of file diff --git a/README.md b/README.md index 4ceafd332..5dc7eb8a0 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | | 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | -| 3.x | [master](https://github.com/cakedc/users/tree/master) | 3.0.0 | stability is beta, but pretty stable now | +| 3.x | [master](https://github.com/cakedc/users/tree/master) | 3.x | stability is beta, but pretty stable now | +| 3.x | [develop](https://github.com/cakedc/users/tree/develop) | 3.x | stability is beta, unstable | | 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stability is beta, but pretty stable now | | 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stability is beta, but pretty stable now | @@ -22,7 +23,7 @@ The **Users** plugin is back! It covers the following features: * User registration * Login/logout -* Social login (Facebook, Twitter) +* Social login (Facebook, Twitter, Instagram, Google, Linkedin, etc) * Simple RBAC * Remember me (Cookie) * Manage user's profile @@ -52,23 +53,6 @@ Documentation For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory of this repository. -Roadmap ------- - - -* 3.1.4 << you are here - * SocialAuthenticate refactored to drop Opauth in favor of Muffin/OAuth2 and league/oauth2 -* 3.1.3 - * UserHelper improvements -* 3.1.2 - * Fixes in RBAC permission matchers -* 3.1.0 Migration to CakePHP 3.0 - * Unit test coverage improvements - * Refactor UsersTable to Behavior - * Add google authentication - * Add reCaptcha - * Link social accounts in profile - Support ------- From 18196f8b14d9c98c8ded9801c66fb64c24b4298f Mon Sep 17 00:00:00 2001 From: Curtis Gibby Date: Mon, 15 Feb 2016 13:52:18 -0700 Subject: [PATCH 0386/1476] Fix typo in exception string --- 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 f557d5cbc..bf00fca59 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -153,7 +153,7 @@ public function login() if (!$this->request->is('post') && !$socialLogin) { if ($this->Auth->user()) { - $msg = __d('Users', 'Your are already logged in'); + $msg = __d('Users', 'You are already logged in'); $this->Flash->error($msg); return $this->redirect($this->referer()); } From 443b43a142ffe132a45b0ce9c09cd6f716b3f5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 16 Feb 2016 10:17:11 +0000 Subject: [PATCH 0387/1476] change bake status to master --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5dc7eb8a0..ecd6d94ed 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ CakeDC Users Plugin =================== -[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=3.1.x)](http://travis-ci.org/CakeDC/users) +[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/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 aa7081b1c3aaa73747285964e4b675dba867ec40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Thu, 18 Feb 2016 14:41:41 +0100 Subject: [PATCH 0388/1476] Swedish translation --- src/Locale/sv/Users.mo | Bin 0 -> 12917 bytes src/Locale/sv/Users.po | 723 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 723 insertions(+) create mode 100644 src/Locale/sv/Users.mo create mode 100644 src/Locale/sv/Users.po diff --git a/src/Locale/sv/Users.mo b/src/Locale/sv/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..07925b46d0f1ae067550b7a334e34f0b255ca2b6 GIT binary patch literal 12917 zcmb`Ndypm7UB?>&Aq+2hg}9J#ct5f;JF@`-vn=c|I|~E*a(8wiM1h{UJ$HKVy?rm; zeP?$91QKD<1;qzM9*QCCs%5k)hI0Q%s?>6J16BSqDy#ll&l};TJa2{S_kQ>ja0#9O55e={Q&9Ck3r~Tchv&gRf-3hqRDb^f z8G7(0JO_RoY8+}*<=4P7;d;-_{{3DkRVDCTxa6Oog6j8qcszUwO3uUZKKOeugs0Ic zT?K8p89odzfqw?q!EZwK|Gu-FzDJ?t4WZ<3K#i*dnTp^+D0vP+jprFCIbMLb!p}hI z{og$Q6VgTSHdOu7&vtTN059hGQmFa9)pH)cpXbNmH!M7m)g0oQ8Mequ!_tQ}A&O(j%5jX;$g;&5Y!K>kSpyXeJQL5f0Q2MyhKW~Ak zHn3cm0z5^ZivQx&Pa9 z4MIwvH$kR2xE$}@!8xR#8=&N!gsMLc zCEs08dWxXNy$B`GLs0f`5K6AUh0^0cLdpGYsQUj4RsK|jSPRdESHfF78&LXt8sb{P zD^UG^8P343!6`V#cl$~4xG12xRJl#~@Q3{4Ts6z6Np4;3SkR zUIx|PBvk+RK*{xSD7}0h%FkYf(&N{m;_&z2iSPuBL-RfarN8r`^fL-I-W~87xClq# zXW_~4Yw$YwFYr|Oew3^@a5a?NTcFx$K=peFN}d;?=KmTK&Vy?ALWrpb+u(8V5t8)wDc@dX&Fg{QWl1MR>s9 zPr&>Az3>9*Mw0BPxa1?BCe=xXB%9Q=-@(S9cX7X$w1adW=~qd+NyYUPH?r}MlYW^r zPm<3R*C)Aoj`ZvPMGcxT8uK@& z!G^y-1GY$akuD|OLi$b8A<~JY$4L?CR+6rVNKMi{(m~S6qz{ma>jHlhiW75lQ71Pu zJ9eA7c2bM;xSeD->vg-E3uDWLt?W7ZHG}ChJ6V@q9dIx>=M~ zIZN$sYC>#BIa(O412rPN?c95rk9)=Z^oJLPsvZ__L{+ttQxu`M@U3#MJUV0zx#Ycoz7 zCeEyh&$ZFwTyx3P;;hpQm!jHQ(`iOw7U4CWC0l;J-E6k^%OJv94Usd0u~?hjAI+NC zw7p-3Bbiq1Apf!TkXUyrydjt_o;w|rh0T1e3H_aEblxrO*9wzTlKP(D7D@ZYOjr^A_ljs!82ju|VSkTIQZ))!Zr)=x@852ixK-Q(r{E z`MBOqL&Y64A2*|MbFq85j@Cvx3!RHcuy>WMMe|{|iG@aKOVtUT!M1jd*o5b8Cu~^n z(M{og&M5Upu3J4x&h6NG*v%K(Y5cJs19S0eUKSe^F~Q8)7~z6z*lb#t$X3plx44d~ z+P$&cH&s<$2r~?VC|z{Y7m$lae3Q-z!VGN_kJOjcKDQ9fxi>b-+gI&`XxWY26c+k0 z@@=_zTOmK#>3zypx4!ek)qiI`iNIwzw4L^?6q=esu6NdMPfbD;nh8rg7%7@8GGq?N zyp%c>=nRfz6|riGfeg)smaRg~{k>I+UG2Rl%*~7~`vaOOMbwf$Sg!DM=ds1oJR7kk zh`dJ!JJa@JTw@(CZp>Vm_-#eh>f}qou4tacJeiBCyPh%$+XOP2TJ0(?-xal@)+{O~ z!tc^TQ!{(r7Direb!p#M3nN3;&ZKXND&()NTy{T>QWoi7fz&4}JkwC<#4XdMtFBgH zaCfspxy3l_8$sU`xsA;(?F$O`)ds8z0=wNV$j8GnBwGiFf`Qysw9#KG^R-rMvOC*i zo3L9uC>tMG9;4cL&x^iZeC`YZt|7Y#W>DhXz%Itr+N=(;l2(|{E!Z+`wxgx8SI95( zR+#8|l(4w)$Bus?BM#wl7)*b1ZAG=MKarc@ksTa zIAN6Mc7wHkODby@rPP8ixr($Z*(ZlDZhJf?vl3ESW$+)YQ)c+`c4KR|w`S@?&eKWF3neug??&8(^WO~Rd*WB=yfhytZabcrO}M?to;+^y{Yqd^#G4Eo(dJ2`Mlzhb ztF7MNINBfF88zqHt!S;C$dB+{t)Mu zSi4V6Tcx^6o3Fx|?ZIzw3d@z(Xe#Zlud>0VC@&l6ahf=pZ6B~Yj*~1;yZ#H^HjIW+ z8$*8N=4SK6kcPdex|IzD^C6noZIDC<@_>)S#kk$g0%hvc4q8cE04TL(6_qlObNTReZFn!%gB6TBI~v-#V`kWXS@UjKM+W0&{pi?r!=vkm$F4VH*Nl&iesFYb zbd-X_yAVuuS1h;w8dpxAEyFWum}G2V^mV$YnZ^yXd-*6^qB^@Cb7NO;Hr3*KoQKW% zcHXY1;e3>gWYJASTRAD{hV^K8CJI~Qh0WiH8RR(Mra63|HaCK~S4GE7wm7tHdfQYr zwy}}Xp-HN+7agAA>ucQPsCFG6x^c2W+lZ8Ky>ZXXmf`EGa*~;S+3*zJSmR@8++5FB z;}D*fhRxwE?X;DRo1|kOvyJOF@V%^@jaMe-qK#(kstrST4d3dPU5$HZJJLDA*vR!G zA07&B5BZ9=CsQoTsacGh%?5kMB)9`HG1TS5DGpcTKq72#j-j>tB9~_xoH<2!8pkSj zUdhXfY723mhcyC(&7NOAn%bbKqZsY|+H(sg8s;n~A1Q07cWoTiMW$_F7iDnh{Qp7_LwNjb+!=2?L90{<~ z=vwU?4!=-=+z#*Ht9UkU)~J%y($H*OKFSVTM^(2haf(nr`D{LIn#gEHSw&sD8(}Bp zlexPXVpq&x)rdW>nojIIquJFIzRSuN%!FpPo$?)Bsj7IjO4m+EW)=@)guOMVWD3EQ zwTRFj>1Y^nl4Q>Ke3ofoht{I9Mm*ObmbP2LR42nudyLWNkwK#z!ZZ@>(zU&AqL7wl zF!3dbqMWYS2J>vhy>#o`mgU3E+}@h`sL72Ew6JAc`L<}EUD$fgvv#yl=ix*a?%X2I zkP&}MqXs8Ive_nMPk7adr2=NExzA368?`etPO)ZbCu0&4+r^KmU4n<{Y1=hjkDGa1 z_ns5%aF6Ao)mnokv)Gm|@KNMmK9X}lo8|2!Do(M`VR4MbDc16lq@I_pRZhRoM3`uK zm}T8{pqMX!S7=@;^ODx&+%6jRgo;9D|4RPcit=_%{=*)#gtq!Pq>H`>@If8>S~g>I^xQ3=JJHg ztdshUKjiXeDaGWNLzvcPqXi5tt}k$EoqG4jZTmvg_9enb>A%ioDWND(JWxQwPb)}= z-3AL^Oi&FuRIQ9riV0DWjT^XO8D#jbMhCcHt*fij@_50g;LqpEo>v!agwDTmC8}-oE&R`EcNHwu#Y`K-J20D z_e?|RoUvILK~Z(Ef4ga@O6|pZTre#{fosPF36>7KR1}H~_TR5r(fk8)8cLb{@amy2OP4 zsj+7xN{H>t>Io~Awp@`iYWLUZZ_Lh@J1Hxzp5qCOI;Na<)WwB6++Y}A^$<-!0OlPA!n@1RyKxU#ku+so^V%Nxn&1`DiX&*Zg|6IyvdRuJJ3Ybw0XCA} AHvj+t literal 0 HcmV?d00001 diff --git a/src/Locale/sv/Users.po b/src/Locale/sv/Users.po new file mode 100644 index 000000000..b13668079 --- /dev/null +++ b/src/Locale/sv/Users.po @@ -0,0 +1,723 @@ +# LANGUAGE translation of CakePHP Application +# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) +# +msgid "" +msgstr "" +"Project-Id-Version: Users\n" +"POT-Creation-Date: 2016-02-18 14:10+0100\n" +"PO-Revision-Date: 2016-02-18 14:24+0100\n" +"Last-Translator: Ulrik Södergren \n" +"Language-Team: CakeDC \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.7\n" + +#: Auth/SimpleRbacAuthorize.php:133 +msgid "" +"Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" +"Saknad konfigurationsfil: \"config / {0} .php\". Använder " +"standardbehörigheter" + +#: Auth/SocialAuthenticate.php:153 +msgid "Provider cannot be empty" +msgstr "Leverantör kan inte vara tomt" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Kontot har validerats" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Konto kunde inte valideras" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Ogiltig token och / eller social konto" + +#: Controller/SocialAccountsController.php:59 +msgid "SocialAccount already active" +msgstr "SocialAccount redan aktivt" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "SocialAccount kunde inte valideras" + +#: Controller/SocialAccountsController.php:79 +msgid "Email sent successfully" +msgstr "Epost har skickats." + +#: Controller/SocialAccountsController.php:81 +msgid "Email could not be sent" +msgstr "Epsot kunde inte skickas" + +#: Controller/SocialAccountsController.php:84 +msgid "Invalid account" +msgstr "Ogiltigt konto" + +#: Controller/SocialAccountsController.php:86 +msgid "Social Account already active" +msgstr "SocialAccount redan aktivt" + +#: Controller/SocialAccountsController.php:88 +msgid "Email could not be resent" +msgstr "E-post kan inte skickas om" + +#: Controller/Component/RememberMeComponent.php:69 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Ogiltig app salt, måste app salt vara åtminstone 256 bitar (32 byte) långt" + +#: Controller/Component/UsersAuthComponent.php:157 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Du kan inte aktivera epost-validering arbetsflöde om use_email är falskt" + +#: Controller/Traits/LoginTrait.php:92 +msgid "Issues trying to log in with your social account" +msgstr "Problem vid inloggning med ditt sociala konto" + +#: Controller/Traits/LoginTrait.php:96 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Lägg till din epost" + +#: Controller/Traits/LoginTrait.php:102 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ditt konto har inte verifierats ännu. Vänligen kontrollera din inbox för " +"instruktioner" + +#: Controller/Traits/LoginTrait.php:104 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Din sociala hänsyn har inte validerats ännu. Vänligen kontrollera din inbox " +"för instruktioner" + +#: Controller/Traits/LoginTrait.php:177 +msgid "Username or password is incorrect" +msgstr "Användarnamn eller lösenord är felaktigt" + +#: Controller/Traits/LoginTrait.php:198 +msgid "You've successfully logged out" +msgstr "Du har loggats ut" + +#: Controller/Traits/PasswordManagementTrait.php:53 +msgid "Password has been changed successfully" +msgstr "Lösenordsbytet lyckades!" + +#: Controller/Traits/PasswordManagementTrait.php:56;63 +msgid "Password could not be changed" +msgstr "Lösenordet kunde inte ändras" + +#: Controller/Traits/PasswordManagementTrait.php:59 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "Användaren hittades inte." + +#: Controller/Traits/PasswordManagementTrait.php:61 +msgid "The current password does not match" +msgstr "Den nuvarande lösenord matchar inte" + +#: Controller/Traits/PasswordManagementTrait.php:102 +msgid "Please check your email to continue with password reset process" +msgstr "Kontrollera din epost för att fortsätta lösenordsåterställningen" + +#: Controller/Traits/PasswordManagementTrait.php:105 Shell/UsersShell.php:266 +msgid "The password token could not be generated. Please try again" +msgstr "Lösenordstoken kunde inte skapas. Var god försök igen" + +#: Controller/Traits/PasswordManagementTrait.php:110 +#: Controller/Traits/UserValidationTrait.php:98 +msgid "User {0} was not found" +msgstr "Användaren {0} hittades inte" + +#: Controller/Traits/PasswordManagementTrait.php:112 +#: Controller/Traits/UserValidationTrait.php:94;102 +msgid "Token could not be reset" +msgstr "Token kunde inte återställas" + +#: Controller/Traits/ProfileTrait.php:52 +msgid "Not authorized, please login first" +msgstr "Inte auktoriserad, vänligen logga in först" + +#: Controller/Traits/RegisterTrait.php:74 Controller/Traits/SocialTrait.php:38 +msgid "The reCaptcha could not be validated" +msgstr "reCAPTCHA angavs inte korrekt" + +#: Controller/Traits/RegisterTrait.php:80 +msgid "The user could not be saved" +msgstr "Användaren kunde inte sparas" + +#: Controller/Traits/RegisterTrait.php:113 +msgid "You have registered successfully, please log in" +msgstr "Din registrering är klar, vänligen logga in" + +#: Controller/Traits/RegisterTrait.php:115 +msgid "Please validate your account before log in" +msgstr "Vänligen validera ditt konto innan inloggning" + +#: Controller/Traits/SimpleCrudTrait.php:76;105 +msgid "The {0} has been saved" +msgstr "{0} har sparats" + +#: Controller/Traits/SimpleCrudTrait.php:79;108 +msgid "The {0} could not be saved" +msgstr "{0} kunde inte sparas" + +#: Controller/Traits/SimpleCrudTrait.php:128 +msgid "The {0} has been deleted" +msgstr "{0} har tagits bort" + +#: Controller/Traits/SimpleCrudTrait.php:130 +msgid "The {0} could not be deleted" +msgstr "{0} kunde inte tas bort" + +#: Controller/Traits/UserValidationTrait.php:42 +msgid "User account validated successfully" +msgstr "Användarkontot har validerats" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account could not be validated" +msgstr "Användarkontot kunde inte valideras" + +#: Controller/Traits/UserValidationTrait.php:47 +msgid "User already active" +msgstr "Användaren redan aktiv" + +#: Controller/Traits/UserValidationTrait.php:53 +msgid "Reset password token was validated successfully" +msgstr "Återställning av lösenord lyckades." + +#: Controller/Traits/UserValidationTrait.php:57 +msgid "Reset password token could not be validated" +msgstr "Token för att återställa lösenord kunde inte valideras" + +#: Controller/Traits/UserValidationTrait.php:61 +msgid "Invalid validation type" +msgstr "Ogiltig valideringsmetod" + +#: Controller/Traits/UserValidationTrait.php:64 +msgid "Invalid token or user account already validated" +msgstr "Ogiltig token eller så har användaren konto redan validerats" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Token already expired" +msgstr "Token redan löpt ut" + +#: Controller/Traits/UserValidationTrait.php:92 +msgid "Token has been reset successfully. Please check your email." +msgstr "Token har återställts. Kontrollera din e-post." + +#: Controller/Traits/UserValidationTrait.php:100 +msgid "User {0} is already active" +msgstr "Användaren {0} är redan aktiv" + +#: Model/Behavior/PasswordBehavior.php:42 +msgid "Reference cannot be null" +msgstr "Referens får inte vara null" + +#: Model/Behavior/PasswordBehavior.php:47 +msgid "Token expiration cannot be empty" +msgstr "Giltighet för token kan inte vara tom" + +#: Model/Behavior/PasswordBehavior.php:53 +msgid "User not found" +msgstr "Användaren hittades inte" + +#: Model/Behavior/PasswordBehavior.php:95 +msgid "{0}Your reset password link" +msgstr "{0} Din länk för att återställa lösenord" + +#: Model/Behavior/PasswordBehavior.php:119 +msgid "The old password does not match" +msgstr "Det gamla lösenordet stämmer inte" + +#: Model/Behavior/RegisterBehavior.php:65 +msgid "Your account validation link" +msgstr "Din länk för att validera kontot" + +#: Model/Behavior/RegisterBehavior.php:86 +msgid "User not found for the given token and email." +msgstr "Hittade ingen användare som matchar angivet token eller epost" + +#: Model/Behavior/RegisterBehavior.php:89 +msgid "Token has already expired user with no token" +msgstr "Token har redan gått ut eller användare utan token" + +#: Model/Behavior/RegisterBehavior.php:108 +msgid "User account already validated" +msgstr "Kontot är redan aktiverat!" + +#: Model/Behavior/SocialAccountBehavior.php:82 +msgid "{0}Your social account validation link" +msgstr "{0} Din sociala konto svalideringslänk" + +#: Model/Behavior/SocialAccountBehavior.php:109;136 +msgid "Account already validated" +msgstr "Kontot är redan aktiverat!" + +#: Model/Behavior/SocialAccountBehavior.php:112;139 +msgid "Account not found for the given token and email." +msgstr "Kontot hittades inte för givet token och e-post." + +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "Det går inte att logga in användaren med refrens {0}" + +#: Model/Behavior/SocialBehavior.php:98 +msgid "Email not present" +msgstr "Epost saknas" + +#: Model/Table/UsersTable.php:80 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Dina lösenord matchar inte. Vänligen försök igen." + +#: Model/Table/UsersTable.php:158 +msgid "Username already exists" +msgstr "Användarnamnet är upptaget" + +#: Model/Table/UsersTable.php:164 +msgid "Email already exists" +msgstr "E-postadressen finns redan" + +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Verktyg för CakeDC User Plugin" + +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Aktivera en specifik användare" + +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "Lägga till en ny superadmin användare för teständamål" + +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "Ny användare" + +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Ändra rollen för en specifik användare" + +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "Inaktivare en specifik användare" + +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Ta bort en specifik användare" + +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "Återställ lösenord via e-post" + +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "Återställ lösenord för alla användare" + +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "Återställ lösenordet för en specifik användare" + +#: Shell/UsersShell.php:97 +msgid "User added:" +msgstr "Användare tillagd:" + +#: Shell/UsersShell.php:98;126 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:99;127 +msgid "Username: {0}" +msgstr "Användarnamn: {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Email: {0}" +msgstr "Epost: {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Password: {0}" +msgstr "Lösenord: {0}" + +#: Shell/UsersShell.php:125 +msgid "Superuser added:" +msgstr "Superanvändare tillagd:" + +#: Shell/UsersShell.php:131 +msgid "Superuser could not be added:" +msgstr "Superanvändaren kunde inte läggas till:" + +#: Shell/UsersShell.php:134 +msgid "Field: {0} Error: {1}" +msgstr "Fält: {0} fel: {1}" + +#: Shell/UsersShell.php:152;178 +msgid "Please enter a password." +msgstr "Ange ett lösenord." + +#: Shell/UsersShell.php:156 +msgid "Password changed for all users" +msgstr "Lösenordet ändrat för alla användare" + +#: Shell/UsersShell.php:157;185 +msgid "New password: {0}" +msgstr "Nytt lösenord: {0}" + +#: Shell/UsersShell.php:175;203;281;321 +msgid "Please enter a username." +msgstr "Ange ett användarnamn" + +#: Shell/UsersShell.php:184 +msgid "Password changed for user: {0}" +msgstr "Lösenordet ändrat för användare: {0}" + +#: Shell/UsersShell.php:206 +msgid "Please enter a role." +msgstr "Ange en roll." + +#: Shell/UsersShell.php:212 +msgid "Role changed for user: {0}" +msgstr "Rollen har ändrats för användare: {0}" + +#: Shell/UsersShell.php:213 +msgid "New role: {0}" +msgstr "Ny roll: {0}" + +#: Shell/UsersShell.php:228 +msgid "User was activated: {0}" +msgstr "Användaren aktiverades: {0}" + +#: Shell/UsersShell.php:243 +msgid "User was de-activated: {0}" +msgstr "Användaren avaktiverad: {0}" + +#: Shell/UsersShell.php:255 +msgid "Please enter a username or email." +msgstr "Skriv användarnamn eller epost" + +#: Shell/UsersShell.php:263 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Be användaren kontrollera sin epost för att fortsätta " +"lösenordsåterställningen" + +#: Shell/UsersShell.php:300 +msgid "The user was not found." +msgstr "Användaren hittades inte." + +#: Shell/UsersShell.php:327 +msgid "The user {0} was deleted successfully" +msgstr "Användaren {0} har tagits bort" + +#: Shell/UsersShell.php:329 +msgid "The user {0} was not deleted. Please try again" +msgstr "Användaren {0} raderades ej. Var god försök igen" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Hej {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Återställ ditt lösenord här" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +msgid "" +"If the link is not correcly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Om länken inte visas korrekt, vänligen kopiera följande adress till " +"webbläsaren {0}" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Tack" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Aktivera ditt sociala konto här" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Aktivera ditt konto här" + +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Om länken inte visas korrekt, vänligen kopiera följande adress till din " +"webbläsare {0}" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Kopiera följande adress till webbläsaren {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Kopiera följande adress till din webbläsare för att aktivera din sociala " +"inloggning {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:13 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:13;77 +msgid "Actions" +msgstr "Resurser" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:21 +#: Template/Users/view.ctp:17 +msgid "List Users" +msgstr "Lista användare" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:22 +#: Template/Users/view.ctp:19 +msgid "List Accounts" +msgstr "Lista konton" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:15 +msgid "Add User" +msgstr "Ny användare" + +#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:17 +#: Template/Users/edit.ctp:42 Template/Users/register.ctp:27 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:20 +msgid "Submit" +msgstr "Skicka" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Ange ditt nya lösenord" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Nuvarande lösenord" + +#: Template/Users/edit.ctp:16 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:99 +msgid "Delete" +msgstr "Radera" + +#: Template/Users/edit.ctp:18 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:16;99 +msgid "Are you sure you want to delete # {0}?" +msgstr "Är du säker på att du vill radera{0}" + +#: Template/Users/edit.ctp:28 Template/Users/view.ctp:15 +msgid "Edit User" +msgstr "Redigera användare" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nytt {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:95 +msgid "View" +msgstr "Visa" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Byt lösenord" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:97 +msgid "Edit" +msgstr "Ändra" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "föregående" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "nästa" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Ange ditt användarnamn och lösenord" + +#: Template/Users/login.ctp:26 +msgid "Remember me" +msgstr "Kom ihåg mig" + +#: Template/Users/login.ctp:55 +msgid "Login" +msgstr "Loggin" + +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:63 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:24 +msgid "Change Password" +msgstr "Ändra Lösenord" + +#: Template/Users/profile.ctp:27 Template/Users/view.ctp:28;68 +msgid "Username" +msgstr "Användarnamn" + +#: Template/Users/profile.ctp:29 Template/Users/view.ctp:30 +msgid "Email" +msgstr "Epost" + +#: Template/Users/profile.ctp:34 +msgid "Social Accounts" +msgstr "Sociala konton" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:70 +msgid "Avatar" +msgstr "Profilbild" + +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:67 +msgid "Provider" +msgstr "Utförare" + +#: Template/Users/profile.ctp:40 +msgid "Link" +msgstr "Länk" + +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Länk till {0}" + +#: Template/Users/register.ctp:23 +msgid "Accept TOS conditions?" +msgstr "Jag accepterar villkoren" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Ange din e-postadress för att återställa ditt lösenord" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Skicka nytt bekräftelsemejl" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "E-post/Användarnamn" + +#: Template/Users/view.ctp:16 +msgid "Delete User" +msgstr "Ta bort användare" + +#: Template/Users/view.ctp:18 +msgid "New User" +msgstr "Ny användare" + +#: Template/Users/view.ctp:26;65 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:32 +msgid "First Name" +msgstr "Förnamn" + +#: Template/Users/view.ctp:34 +msgid "Last Name" +msgstr "Efternamn" + +#: Template/Users/view.ctp:36;71 +msgid "Token" +msgstr "Token" + +#: Template/Users/view.ctp:38 +msgid "Api Token" +msgstr "Api-token" + +#: Template/Users/view.ctp:42;73 +msgid "Active" +msgstr "Aktivt" + +#: Template/Users/view.ctp:46;72 +msgid "Token Expires" +msgstr "Token förfaller" + +#: Template/Users/view.ctp:48 +msgid "Activation Date" +msgstr "Aktiveringsdatum" + +#: Template/Users/view.ctp:50 +msgid "Tos Date" +msgstr "Tos datum" + +#: Template/Users/view.ctp:52;75 +msgid "Created" +msgstr "Skapad" + +#: Template/Users/view.ctp:54;76 +msgid "Modified" +msgstr "Ändrad" + +#: Template/Users/view.ctp:61 +msgid "Related Accounts" +msgstr "relaterade konton" + +#: Template/Users/view.ctp:66 +msgid "User Id" +msgstr "Användar-ID" + +#: Template/Users/view.ctp:69 +msgid "Reference" +msgstr "Referens" + +#: Template/Users/view.ctp:74 +msgid "Data" +msgstr "Data" + +#: View/Helper/UserHelper.php:62 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:64 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:77 +msgid "Logout" +msgstr "Logga ut" + +#: View/Helper/UserHelper.php:115 +msgid "Welcome, {0}" +msgstr "Välkommen, {0}" + +#~ msgid "There was an error associating your social network account" +#~ msgstr "Det gick inte att associera ditt sociala nätverkskonto" + +#~ msgid "Invalid token and/or email" +#~ msgstr "Ogiltig token och / eller epost" + +#~ msgid "The \"tos\" property is not present" +#~ msgstr "\"tos\" fältet saknas" + +#~ msgid "+ {0} secs" +#~ msgstr "{0} sek" + +#~ msgid "Sign in with Facebook" +#~ msgstr "Logga in med Facebook" + +#~ msgid "Sign in with Twitter" +#~ msgstr "Logga in med Twitter" From 0914acf4b60d56a2cd298f23cc26e38767d220eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 19 Feb 2016 01:36:03 +0000 Subject: [PATCH 0389/1476] adding specific note about using email to login --- Docs/Documentation/Configuration.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 82883a14f..68bd89a77 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -120,6 +120,27 @@ Using the UsersAuthComponent default initialization, the component will load the * 'Users.Superuser' check [SuperuserAuthorize](SuperuserAuthorize.md) for configuration options * 'Users.SimpleRbac' check [SimpleRbacAuthorize](SimpleRbacAuthorize.md) for configuration options +## Using the user's email to login + +You need to configure 2 things: +* Change the Auth.authenticate.Form.fields configuration to let AuthComponent use the email instead of the username for user identify. Add this line to your bootstrap.ctp file, after CakeDC/Users Plugin is loaded + +```php +Configure::write('Auth.authenticate.Form.fields.username', 'email'); +``` + +* Override the login.ctp template to change the Form->input to "email". Add (or copy from the https://github.com/CakeDC/users/blob/master/src/Template/Users/login.ctp) the file login.ctp to path /src/Template/Plugin/CakeDC/Users/Users/login.ctp and ensure it has the following content + +```php + // ... inside the Form + Form->input('email', ['required' => true]) ?> + Form->input('password', ['required' => true]) ?> + // ... rest of your login.ctp code +``` + + + + Email Templates --------------- From 069ddc6d0d0042e0e411a6fb809e311adf70a562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 21 Feb 2016 17:17:16 +0000 Subject: [PATCH 0390/1476] refs #304 fix fixed alias in users shell --- src/Shell/UsersShell.php | 13 +++--- tests/TestCase/Shell/UsersShellTest.php | 56 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index dc544b6f3..908bfd502 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -295,7 +295,7 @@ protected function _changeUserActive($active) */ protected function _updateUser($username, $data) { - $user = $this->Users->find()->where(['Users.username' => $username])->first(); + $user = $this->Users->find()->where(['username' => $username])->first(); if (empty($user)) { $this->error(__d('Users', 'The user was not found.')); } @@ -320,14 +320,15 @@ public function deleteUser() if (empty($username)) { $this->error(__d('Users', 'Please enter a username.')); } - $user = $this->Users->find()->where(['Users.username' => $username])->first(); - $deleteAccounts = $this->Users->SocialAccounts->deleteAll(['user_id' => $user->id]); + $user = $this->Users->find()->where(['username' => $username])->first(); + if (isset($this->Users->SocialAccounts)) { + $this->Users->SocialAccounts->deleteAll(['user_id' => $user->id]); + } $deleteUser = $this->Users->delete($user); - if ($deleteAccounts && $deleteUser) { - $this->out(__d('Users', 'The user {0} was deleted successfully', $username)); - } else { + if (!$deleteUser) { $this->error(__d('Users', 'The user {0} was not deleted. Please try again', $username)); } + $this->out(__d('Users', 'The user {0} was deleted successfully', $username)); } /** diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index f773beb99..e3c4311d7 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Shell; +use CakeDC\Users\Shell\UsersShell; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOutput; use Cake\ORM\TableRegistry; @@ -25,6 +26,7 @@ class UsersShellTest extends TestCase */ public $fixtures = [ 'plugin.CakeDC/Users.users', + 'plugin.CakeDC/Users.social_accounts', ]; /** @@ -250,4 +252,58 @@ public function testResetPassword() $this->Shell->runCommand(['resetPassword', 'user-1', 'password']); } + + /** + * Change role + * + * @return void + */ + public function testChangeRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertSame('admin', $user['role']); + $this->Shell->runCommand(['changeRole', 'user-1', 'another-role']); + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertSame('another-role', $user['role']); + } + + /** + * Activate user + * + * @return void + */ + public function testActivateUser() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertFalse($user['active']); + $this->Shell->runCommand(['activateUser', 'user-1']); + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertTrue($user['active']); + } + + /** + * Delete user + * + * @return void + * @expected + */ + public function testDeleteUser() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + + $this->assertNotEmpty($this->Users->findById('00000000-0000-0000-0000-000000000001')->first()); + $this->assertNotEmpty($this->Users->SocialAccounts->findByUserId('00000000-0000-0000-0000-000000000001')->toArray()); + $this->Shell->runCommand(['deleteUser', 'user-1']); + $this->assertEmpty($this->Users->findById('00000000-0000-0000-0000-000000000001')->first()); + $this->assertEmpty($this->Users->SocialAccounts->findByUserId('00000000-0000-0000-0000-000000000001')->toArray()); + + $this->assertNotEmpty($this->Users->findById('00000000-0000-0000-0000-000000000005')->first()); + $this->Shell->runCommand(['deleteUser', 'user-5']); + $this->assertEmpty($this->Users->findById('00000000-0000-0000-0000-000000000005')->first()); + } } From ebc6e6ef45a42f1961ef4d55f8f0446feff74509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 21 Feb 2016 18:31:35 +0000 Subject: [PATCH 0391/1476] add license icon --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ecd6d94ed..063256b15 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ CakeDC Users Plugin [![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/CakeDC/users) [![Downloads](https://poser.pugx.org/CakeDC/users/d/total.png)](https://packagist.org/packages/CakeDC/users) [![Latest Version](https://poser.pugx.org/CakeDC/users/v/stable.png)](https://packagist.org/packages/CakeDC/users) +[![License](https://poser.pugx.org/CakeDC/users/license.svg)](https://packagist.org/packages/CakeDC/users) IMPORTANT: 3.1.x version is BETA status now, we are still improving and testing it. From 1e26c13d5bb0fb284e152990d54a43a84e400223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 21 Feb 2016 18:33:09 +0000 Subject: [PATCH 0392/1476] update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ec3d24a3f..c7ed3efd1 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "cakedc/users", - "description": "Users plugin for CakePHP 3.1", + "description": "Users Plugin for CakePHP 3", "type": "cakephp-plugin", "keywords": [ "cakephp", From 9620ca0b9891da13120c390aa319a32146416271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Fri, 26 Feb 2016 15:44:02 +0000 Subject: [PATCH 0393/1476] refs #update-auth-scope Added finder for auth since 'scope' is deprecated --- Docs/Documentation/Configuration.md | 4 ++-- config/users.php | 2 +- src/Model/Table/UsersTable.php | 14 ++++++++++++++ tests/TestCase/Model/Table/UsersTableTest.php | 14 ++++++++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 68bd89a77..c67884986 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -94,7 +94,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'Auth' => [ 'authenticate' => [ 'all' => [ - 'scope' => ['active' => 1] + 'finder' => 'auth', ], 'CakeDC/Users.RememberMe', 'Form', @@ -139,7 +139,7 @@ Configure::write('Auth.authenticate.Form.fields.username', 'email'); ``` - + Email Templates --------------- diff --git a/config/users.php b/config/users.php index edc5e2433..6dcd0aab6 100644 --- a/config/users.php +++ b/config/users.php @@ -91,7 +91,7 @@ ], 'authenticate' => [ 'all' => [ - 'scope' => ['active' => 1] + 'finder' => 'auth', ], 'CakeDC/Users.ApiKey', 'CakeDC/Users.RememberMe', diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index a34a6fb93..c27cfe492 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -13,6 +13,7 @@ use Cake\ORM\RulesChecker; use Cake\ORM\Table; +use Cake\ORM\Query; use Cake\Utility\Hash; use Cake\Validation\Validator; @@ -167,4 +168,17 @@ public function buildRules(RulesChecker $rules) return $rules; } + + /** + * Custom finder for Auth.authenticate + * + * @param Query $query Query object to modify + * @param array $options Query options + * @return Query + */ + public function findAuth(Query $query, array $options = []) + { + $query->where(["{$this->_alias}.active" => 1]); + return $query; + } } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index f9522fd60..2694b2387 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -21,6 +21,7 @@ use Cake\Routing\Router; use Cake\TestSuite\TestCase; use InvalidArgumentException; +use Cake\Utility\Hash; /** * Users\Model\Table\UsersTable Test Case @@ -311,4 +312,17 @@ public function testSocialLoginCreateNewAccount() $this->assertEquals('First Name', $result->first_name); $this->assertEquals('Last Name', $result->last_name); } + + /** + * Test findAuth method. + * + */ + public function testFindAuth() + { + $actual = $this->Users->find('auth')->toArray(); + $this->assertCount(8, $actual); + $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); + $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); + + } } From 92cc6be24e79436b9475ea0bf7ffe81c2b81d5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Fri, 26 Feb 2016 16:35:01 +0000 Subject: [PATCH 0394/1476] refs #update-auth-scope phpcs fixes --- src/Model/Table/UsersTable.php | 2 +- tests/TestCase/Model/Table/UsersTableTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index c27cfe492..a66033dae 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -11,9 +11,9 @@ namespace CakeDC\Users\Model\Table; +use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; -use Cake\ORM\Query; use Cake\Utility\Hash; use Cake\Validation\Validator; diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 2694b2387..9826c6d84 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -20,8 +20,8 @@ use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; -use InvalidArgumentException; use Cake\Utility\Hash; +use InvalidArgumentException; /** * Users\Model\Table\UsersTable Test Case From c294a1b653d948d94c8a3193723e15943e30057d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Fri, 26 Feb 2016 16:46:44 +0000 Subject: [PATCH 0395/1476] refs #update-auth-scope phpcs fix --- tests/TestCase/Model/Table/UsersTableTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 9826c6d84..8548b716b 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -323,6 +323,5 @@ public function testFindAuth() $this->assertCount(8, $actual); $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); - } } From 6e436ee90e578d872603fe19d74d63c963f4d03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Fri, 26 Feb 2016 17:41:21 +0000 Subject: [PATCH 0396/1476] refs #before-register-entity allow access to entity on before register event --- src/Controller/Traits/RegisterTrait.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index a6a832870..822618cd9 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -51,6 +51,7 @@ public function register() $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_REGISTER, [ 'usersTable' => $usersTable, 'options' => $options, + 'userEntity' => $user, ]); if ($event->result instanceof EntityInterface) { From 9d5febe311303acb47a2fdcb9422825d3a916072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Mon, 29 Feb 2016 09:31:40 +0000 Subject: [PATCH 0397/1476] refs #update-auth-scope changed finder name to 'active' --- Docs/Documentation/Configuration.md | 2 +- config/users.php | 2 +- src/Model/Table/UsersTable.php | 4 ++-- tests/TestCase/Model/Table/UsersTableTest.php | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index c67884986..c4744b6c6 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -94,7 +94,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'Auth' => [ 'authenticate' => [ 'all' => [ - 'finder' => 'auth', + 'finder' => 'active', ], 'CakeDC/Users.RememberMe', 'Form', diff --git a/config/users.php b/config/users.php index 6dcd0aab6..3bde0bae0 100644 --- a/config/users.php +++ b/config/users.php @@ -91,7 +91,7 @@ ], 'authenticate' => [ 'all' => [ - 'finder' => 'auth', + 'finder' => 'active', ], 'CakeDC/Users.ApiKey', 'CakeDC/Users.RememberMe', diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index a66033dae..7eac44ee3 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -170,13 +170,13 @@ public function buildRules(RulesChecker $rules) } /** - * Custom finder for Auth.authenticate + * Custom finder to filter active users * * @param Query $query Query object to modify * @param array $options Query options * @return Query */ - public function findAuth(Query $query, array $options = []) + public function findActive(Query $query, array $options = []) { $query->where(["{$this->_alias}.active" => 1]); return $query; diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 8548b716b..e316eebe5 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -314,12 +314,12 @@ public function testSocialLoginCreateNewAccount() } /** - * Test findAuth method. + * Test findActive method. * */ - public function testFindAuth() + public function testFindActive() { - $actual = $this->Users->find('auth')->toArray(); + $actual = $this->Users->find('active')->toArray(); $this->assertCount(8, $actual); $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); From ba370a0b74ec00f614af334b3ea3f6d95c47aa53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 5 Mar 2016 01:16:24 +0000 Subject: [PATCH 0398/1476] refs #311 relaxed to let adding extra fields to users table easier to do --- src/Mailer/UsersMailer.php | 3 +++ src/Model/Entity/SocialAccount.php | 27 ++++++++++++------------ src/Model/Entity/User.php | 33 +++++++++++++++--------------- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index b7d33c5b9..5fa1beffc 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -32,6 +32,8 @@ class UsersMailer extends Mailer protected function validation(EntityInterface $user, $subject, $template = 'CakeDC/Users.validation') { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + $user->hiddenProperties(['password', 'token_expires', 'api_token']); + $this ->to($user['email']) ->subject($firstName . $subject) @@ -51,6 +53,7 @@ protected function resetPassword(EntityInterface $user, $template = 'CakeDC/User { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $subject = __d('Users', '{0}Your reset password link', $firstName); + $user->hiddenProperties(['password', 'token_expires', 'api_token']); $this ->to($user['email']) diff --git a/src/Model/Entity/SocialAccount.php b/src/Model/Entity/SocialAccount.php index a14de160b..dbf4709a1 100644 --- a/src/Model/Entity/SocialAccount.php +++ b/src/Model/Entity/SocialAccount.php @@ -18,25 +18,24 @@ */ class SocialAccount extends Entity { - /** * Fields that can be mass assigned using newEntity() or patchEntity(). * * @var array */ protected $_accessible = [ - 'user_id' => true, - 'provider' => true, - 'username' => true, - 'reference' => true, - 'avatar' => true, - 'description' => true, - 'link' => true, - 'token' => true, - 'token_secret' => true, - 'token_expires' => true, - 'active' => true, - 'data' => true, - 'user' => true, + '*' => true, + 'id' => false, + ]; + + /** + * Fields that are excluded from JSON an array versions of the entity. + * + * @var array + */ + protected $_hidden = [ + 'token', + 'token_secret', + 'token_expires', ]; } diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 5e3a4c15d..b8a57751a 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -28,23 +28,22 @@ class User extends Entity * @var array */ protected $_accessible = [ - 'username' => true, - 'email' => true, - 'password' => true, - 'confirm_password' => true, - 'first_name' => true, - 'last_name' => true, - 'avatar' => true, - 'token' => true, - 'token_expires' => true, - 'api_token' => true, - 'activation_date' => true, - //tos is a boolean, coming from the "accept the terms of service" checkbox but it is not stored onto database - 'tos' => true, - 'tos_date' => true, - 'active' => true, - 'social_accounts' => true, - 'current_password' => true + '*' => true, + 'id' => false, + 'is_superuser' => false, + 'role' => false, + ]; + + /** + * Fields that are excluded from JSON an array versions of the entity. + * + * @var array + */ + protected $_hidden = [ + 'password', + 'token', + 'token_expires', + 'api_token', ]; /** From f28c56b50acf9200565eb0830f1ed88dd5fd672b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 7 Mar 2016 10:02:59 +0000 Subject: [PATCH 0399/1476] refs #279 refactor User entity to use Time, add unit tests to check es_AR locale --- src/Model/Behavior/Behavior.php | 2 +- src/Model/Entity/User.php | 21 ++--- tests/TestCase/Model/Entity/UserTest.php | 98 +++++++++++++++++++++++- 3 files changed, 106 insertions(+), 15 deletions(-) diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/Behavior.php index f80b0f250..a7e55b5fc 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/Behavior.php @@ -25,7 +25,7 @@ class Behavior extends BaseBehavior * * @param EntityInterface $user User to be updated. * @param bool $validateEmail email user to validate. - * @param type $tokenExpiration token to be updated. + * @param int $tokenExpiration seconds to expire from now * @return EntityInterface */ protected function _updateActive(EntityInterface $user, $validateEmail, $tokenExpiration) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 5e3a4c15d..8cc1aab0f 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Model\Entity; use Cake\Core\Configure; +use Cake\I18n\Time; use Cake\ORM\Entity; use Cake\Utility\Text; use DateTime; @@ -72,7 +73,7 @@ protected function _setConfirmPassword($password) protected function _setTos($tos) { if ((bool)$tos === true) { - $this->set('tos_date', new DateTime()); + $this->set('tos_date', Time::now()); } return $tos; } @@ -128,12 +129,7 @@ public function tokenExpired() return true; } - $tokenExpiresTime = $this->token_expires; - if (is_object($this->token_expires)) { - $tokenExpiresTime = $this->token_expires->format("Y-m-d H:i"); - } - - return strtotime($tokenExpiresTime) < strtotime("now"); + return new Time($this->token_expires) < Time::now(); } /** @@ -152,15 +148,14 @@ protected function _getAvatar() /** * Generate token_expires and token in a user - * @param string $tokenExpiration new token_expires user. - * + * @param int $tokenExpiration seconds to expire the token from Now * @return void */ - public function updateToken($tokenExpiration) + public function updateToken($tokenExpiration = 0) { - $expires = new DateTime(); - $expires->modify("+ $tokenExpiration secs"); - $this->token_expires = $expires; + $expiration = new Time(); + $this->token_expires = $expiration->addSeconds($tokenExpiration); + $this->token = str_replace('-', '', Text::uuid()); } } diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index 2788aa8ad..e812a7733 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -3,6 +3,8 @@ use CakeDC\Users\Model\Entity\User; use Cake\Auth\DefaultPasswordHasher; +use Cake\I18n\I18n; +use Cake\I18n\Time; use Cake\TestSuite\TestCase; /** @@ -10,7 +12,6 @@ */ class UserTest extends TestCase { - /** * setUp method * @@ -70,6 +71,27 @@ public function testTokenExpired() $this->assertFalse($isExpired); } + /** + * Test tokenExpired another locale + * + * @return void + */ + public function testTokenExpiredLocale() + { + I18n::locale('es_AR'); + $this->User->token_expires = '+1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertFalse($isExpired); + $this->User->token_expires = '-1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertTrue($isExpired); + } + + /** + * test + * + * @return void + */ public function testPasswordsAreEncrypted() { $pw = 'password'; @@ -84,6 +106,11 @@ public function testConfirmPasswordsAreEncrypted() $this->assertTrue((new DefaultPasswordHasher)->check($pw, $this->User->confirm_password)); } + /** + * test + * + * @return void + */ public function testCheckPassword() { $pw = 'password'; @@ -91,6 +118,11 @@ public function testCheckPassword() $this->assertFalse($this->User->checkPassword($pw, 'fail')); } + /** + * test + * + * @return void + */ public function testGetAvatar() { $this->assertNull($this->User->avatar); @@ -101,4 +133,68 @@ public function testGetAvatar() ]; $this->assertSame($avatar, $this->User->avatar); } + + /** + * test + * + * @return void + */ + public function testUpdateToken() + { + $now = Time::now(); + Time::setTestNow($now); + $this->assertNull($this->User['token']); + $this->assertNull($this->User['token_expires']); + $this->User->updateToken(); + $this->assertEquals($now, $this->User['token_expires']); + $this->assertNotNull($this->User['token']); + } + + /** + * test + * + * @return void + */ + public function testUpdateTokenExisting() + { + $now = Time::now(); + Time::setTestNow($now); + $this->User['token'] = 'aaa'; + $this->User['token_expires'] = $now; + $this->User->updateToken(); + $this->assertEquals($now, $this->User['token_expires']); + $this->assertNotEquals('aaa', $this->User['token']); + } + + /** + * test + * + * @return void + */ + public function testUpdateTokenAdd() + { + $now = Time::now(); + Time::setTestNow($now); + $this->assertNull($this->User['token']); + $this->assertNull($this->User['token_expires']); + $this->User->updateToken(20); + $this->assertEquals($now->addSeconds(20), $this->User['token_expires']); + $this->assertNotNull($this->User['token']); + } + + /** + * test + * + * @return void + */ + public function testUpdateTokenExistingAdd() + { + $now = Time::now(); + Time::setTestNow($now); + $this->User['token'] = 'aaa'; + $this->User['token_expires'] = $now; + $this->User->updateToken(20); + $this->assertEquals($now->addSecond(20), $this->User['token_expires']); + $this->assertNotEquals('aaa', $this->User['token']); + } } From 643c3edfaea6bd88b14d9b33453f7538a40b8e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 7 Mar 2016 19:05:42 +0000 Subject: [PATCH 0400/1476] refs # refactor now usage --- tests/TestCase/Model/Entity/UserTest.php | 27 ++++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index e812a7733..d7028a87c 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -20,6 +20,8 @@ class UserTest extends TestCase public function setUp() { parent::setUp(); + $this->now = Time::now(); + Time::setTestNow($this->now); $this->User = new User(); } @@ -31,6 +33,7 @@ public function setUp() public function tearDown() { unset($this->User); + Time::setTestNow(); parent::tearDown(); } @@ -141,12 +144,10 @@ public function testGetAvatar() */ public function testUpdateToken() { - $now = Time::now(); - Time::setTestNow($now); $this->assertNull($this->User['token']); $this->assertNull($this->User['token_expires']); $this->User->updateToken(); - $this->assertEquals($now, $this->User['token_expires']); + $this->assertEquals($this->now, $this->User['token_expires']); $this->assertNotNull($this->User['token']); } @@ -157,12 +158,10 @@ public function testUpdateToken() */ public function testUpdateTokenExisting() { - $now = Time::now(); - Time::setTestNow($now); $this->User['token'] = 'aaa'; - $this->User['token_expires'] = $now; + $this->User['token_expires'] = $this->now; $this->User->updateToken(); - $this->assertEquals($now, $this->User['token_expires']); + $this->assertEquals($this->now, $this->User['token_expires']); $this->assertNotEquals('aaa', $this->User['token']); } @@ -173,12 +172,12 @@ public function testUpdateTokenExisting() */ public function testUpdateTokenAdd() { - $now = Time::now(); - Time::setTestNow($now); $this->assertNull($this->User['token']); $this->assertNull($this->User['token_expires']); $this->User->updateToken(20); - $this->assertEquals($now->addSeconds(20), $this->User['token_expires']); + $nowModified = new Time('now'); + $nowModified->addSecond(20); + $this->assertEquals($nowModified, $this->User['token_expires']); $this->assertNotNull($this->User['token']); } @@ -189,12 +188,12 @@ public function testUpdateTokenAdd() */ public function testUpdateTokenExistingAdd() { - $now = Time::now(); - Time::setTestNow($now); $this->User['token'] = 'aaa'; - $this->User['token_expires'] = $now; + $this->User['token_expires'] = $this->now; $this->User->updateToken(20); - $this->assertEquals($now->addSecond(20), $this->User['token_expires']); + $nowModified = new Time('now'); + $nowModified->addSecond(20); + $this->assertEquals($nowModified, $this->User['token_expires']); $this->assertNotEquals('aaa', $this->User['token']); } } From 5c341edf2b3f36d626f22bac71f0cffaa8f8dffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 7 Mar 2016 19:13:18 +0000 Subject: [PATCH 0401/1476] refs # add now to Time constructor --- src/Model/Entity/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 8cc1aab0f..89a556173 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -153,7 +153,7 @@ protected function _getAvatar() */ public function updateToken($tokenExpiration = 0) { - $expiration = new Time(); + $expiration = new Time('now'); $this->token_expires = $expiration->addSeconds($tokenExpiration); $this->token = str_replace('-', '', Text::uuid()); From 8005548d0f5cf84f8056168f7efd9e49448725eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 7 Mar 2016 19:25:18 +0000 Subject: [PATCH 0402/1476] update travis to remove php5.4 and add php7 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cc347134b..97ee5fed5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: php php: - - 5.4 - 5.5 - 5.6 + - 7.0 sudo: false From 34f14be23bc7169d62e2c20eaffac873a64838ba Mon Sep 17 00:00:00 2001 From: Florencio Hernandez Date: Wed, 9 Mar 2016 09:59:04 +0000 Subject: [PATCH 0403/1476] Adding spanish translation --- src/Locale/es_ES.mo | Bin 0 -> 9620 bytes src/Locale/es_ES.po | 539 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 539 insertions(+) create mode 100644 src/Locale/es_ES.mo create mode 100644 src/Locale/es_ES.po diff --git a/src/Locale/es_ES.mo b/src/Locale/es_ES.mo new file mode 100644 index 0000000000000000000000000000000000000000..865263d3bae9886c86f5886e82e58166f2938eb9 GIT binary patch literal 9620 zcmbuEYm8l2b;oytozQ`_Nuba)P&OtnlbP|@aT0qR#~#Mx*o_~9XPm?>i8*u6o|zNh zd(ZVb_s)1?A*70k7Kv1RK!LVOML|`lKoId#KeQ=WNPVgK0#YlXQa)5|(+8D6O+WPY z`|rKax%Z666xt*2`#)zt*Iw(t)?R!3*SBu_xZ$}(c^lXQScW)2Tp+>ir-%WHS}BH&x79q-vPb`{tWomHyCpRcsKZZa1#6}@Imk{ za3;2|g6f|~{2-`#e;vFTd>-5ez6ff*&x8CkUyk*E1Zv)Ig4@AYz&C^61||Qi;9J3M zZ#3o>@NE$%LDe4y5!pNeYW@~@J@_=3fE`fsy#gKqzYA)=cid#myTC)B=4pYF<1#3D zp9T46KEjXY{{$%cJ`HM}&w`JDUj(I}e~)KDd^h-2Q0sgTl$@`E((eyJRAjdEq4BqX_kugYUEo>p=fG#d zp9Nn4rQa`uTK7-DJHfvLnabRRlEtsLgWBgbsP$&RcY=?C(pv`@i9>R{5^0Q{5mMT{s)K(&Gl~za^4K8|6SlXcnH)wZBTl65tM#j z0>!t#0wve?B5r4syqcXLDmDkf3Gf8SQsx;@a(xt(JTHQp_hnFe{9{o2{TonxxE|#} z9djdi7<@D6^$W_so(09P&w%Rx51{7z7f|xO21;N54N5=nU{Uen0Ql5(#w>y2+1FWI z`}%WGa{dsMJ#Iu9`@lOu+3iVC^Irxf|A%7zZ-R(yejk+m{sNR;zYWTce+%vezaQIg z!^xy48*wkFamPTde;Sm1mO!ny3PKfg5mdil0j1wx1J&;npvJubO3s%+?e`TBYM6fn zCC`7x`kOF<=Gh5q{wYxYyC2NJhd{0OyWqp%*Fc7ve*-OeGm~qb-Jte&8q|E}K*{xf zQ0wKO=KmllIe!&A2R;W%?|%=9e?I^<&vhvM4)6`&4sZ%Q4=#XDf?opV&$qC+^!Z*; zJh%)V1b+h*-~KY<4K!-ry`a{67?hok$M2^=x|$3;0Dc%e3|;{(xDE0^9djqBaR)&0 zbRLwPtDyAs(OCZiC_Q`?6#xDJRKIV6;`OVb_Vq?<%rAnwKMJ-Um8R`urp)|M+cCcK#e_!9N7=0>29$18-n*Zzu2|-{(N-<9SfL{~hoi z@J~U_^8--(-i~wc2X6=UeHN5_7eMjhBcS&AnOOfh(DMCf;OoGD0>y)W1%DZoGIj&+ z110CV3GYH_%6}=V|t+7B+On;P;QXZ#BR!3=5EafysyjZ6kr$~pAS31`7KFX?p z3qM_8nNm`=Q}$7AqUe!b^+->9DYExd6zO-7vOeK1KX_A~rl6@enBc>md}>4`wqDP-JUNV>*;6ik>r+ zUH;9OUjj3VY^_HzOV44-q+WQAP{hfzl*LtS9K8pWD>6 z9c#Z!dP6w~k`!ikHR-N6JD-&0dS0Z}cd!0Nb<)`EpeP*k)D1|Hm?M752tklJ)Nk|? zKcyfur{CHR?ow9v%UIbkLE%ak*{WrvURLQfdSaXbO6VpX7ssl5(*{SgqU_sK>T)cT z3e54;9AEZUZD-vJHY+_5S~(kS_1haZ&B|Uo*>LH&?X_J}I>^=A@B^0fb~|6sx+^wG zQ$#5(cJfADcT0Au$k!1kEYkIysElonSKqy!Et7VC+$QnOb_NIt50k#ta(%n!{s-(* z)-UZn_wBJu8+}*qgc9AAdXk!lyU>8A;?_-(PLXhRpU75ms=v{5=7bjY8ajbO%n7Vy zqYstgOH|`kwA61t=$n&SSxON&-g34wC=yZKE@y2wZFhvqU1)o$Flcp+Qq%GW(rjwUU)l;;;rqjr%tOkx&74BvbRc|N$!t=EvdIY${sU2Dq0Qis^P zh+}w)^XBZ1eqQbni}AJoMiu0$@TnfHO_ANExeKANlk{7wewLh5vaoLF+ezQzc80qXWg=248qwu=|hF)6G5AyqDd<>1~nIy)?9uE%&3HH}d_W3x|P-4HGIiK$)mDnECfwS_MA z=l_<(`N6VVJt9mX(vTcf`W#(KO;?Zbd5C7yOFb@TJ#{_2sNII?vu?~h%ww5bH;=n^ zEAO~*uex*jz_ya^-F@qVvcuUG6{CLhLXE-rN)BkRIk0!CQ?h3bPd^27Ig8PHN=+rx`i8S>6uDjGX1fsPpACyL# zyuAAZLO**&kdZwqORL)hS8D|}+BQX$%~NmyJxzu;aXg)PjC2O|P21Vzf;%#6Wt?(s z{`BI+tnyx(CX{VY+dWgeADEcBZ(`~}UZ?N7|K2GcI!>HHeoe8t-+nu_fBOEZ(C-8} z_8?ht6N@hC)Qdf&!~-@RZn1dUn#A4@kDWYza&9Qr?#ZdKS$c8EPb`w6P1`>Ktgl5WY#Ixz>MQbNwO-A5KVHs2;WYfl`_i%vOhyFLF|9^7+) z>{cxY@9Eli9<;l69vFLK;*k)v^J3c0=T6!D?#X?V4~{8CoLJNfoY-omChTq6y7K(o z!r17&>>Dr7=wg=GHeSVU)2xN6I9&*#+}w&aeRENp9k9W~ZX_{VN)vM`r-SVc(mbBg z1(R@AsbkfjI7a$_dWs}Xpjwew=I#3kxDm1hfAZypmQB*U8Wrsb2*jd~|E4%U~E@R66ax-(~r6kP?_%%q1jPLrk z_Klb4%Knv4u~~BG++HLNy*S8lP_~kFvTjmrzOW^orHtCJ@6s`|ncb>RcV2ev)#JNK zutCx`FgoY<6{oLXYT#)s- zr+8JviZLCjE^j#@Ea=J4fsvULA~daaD(@_DaXyyA3!;Xua|@XkcHK6K8Btse>I@u7 z!X`@-?ufq2$r``h=`wQD#FpG%GVO?qA2&d6Kjsn(x`fUZBq*$|cUmkmHtVik`IP>s zfJMW7jyN8w@^QGpZBBNQGjR@(&2~98x472DlXznnjP_UMdY0J2=7Wz!%GIYuVivQW z?)K45g4o01Gdu2rk8U8+kY5f(CU1Q^vKRWJcjee9%p2yR}5qqIk&F*h^WA!DY*oq3f{z`aPjjSMj?IW zI4v9!f>cU?R>A%1`5F6@lF2XbQwo+wreR^juu8iN@My@s6oDciv zkpfkt<`W#pTsir3PLjqeC~88boOE@tr_+cd$J0sbY~_SE{zRZ@Fg9_y*>kkZsbQWF zE}H)A2{}O1P^6&4H~X6lo!t#d`YA9kxU04O!LMRS~G*viOK)5mc{);O$c2qUOJ zHdx}2t*@v2Y1Z>2IBoDUl-Evh9xe(#%LxZjJdOz4gBC|mNVSv=a9Q=CJengU1JQ*D z2JF<^L=pw#AX7D}QUcP)zpa}ECq2~RBaQw-R}m5?=k$2}gqwLgIt6LjqN1?9H9` zp`H134bE#;=?*NqBA5STf5`twv%+w+kX;fJ_#2M;4!JTi#w^Iwhnw5*w-oU(Um_HW zTiB2uL>64WJ4)BBVo;rg8l7@n6$&Hu$D6SYIb7Iz#XTJm;aa4gqdjW(x%xC7>59rW LX|SHLa{d1SB0sJA literal 0 HcmV?d00001 diff --git a/src/Locale/es_ES.po b/src/Locale/es_ES.po new file mode 100644 index 000000000..b77faeb4a --- /dev/null +++ b/src/Locale/es_ES.po @@ -0,0 +1,539 @@ +# LANGUAGE translation of CakePHP Application +# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) +# +msgid "" +msgstr "" +"Project-Id-Version: CakeDC Users\n" +"POT-Creation-Date: 2016-03-07 20:35+0000\n" +"PO-Revision-Date: 2016-03-09 09:50+0000\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=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.7\n" +"Last-Translator: \n" +"Language: es_ES\n" + +#: Auth/SimpleRbacAuthorize.php:132 +msgid "" +"Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" +"Falta el archivo de configuración: \"config/{0}.php\". Utilizando permisos " +"predeterminados" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Cuenta validada correctamente" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "No se pudo validar la cuenta" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Token o cuenta social incorrecta" + +#: Controller/SocialAccountsController.php:59 +msgid "SocialAccount already active" +msgstr "Cuenta social ya activa" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "No se pudo validar la cuenta social " + +#: Controller/SocialAccountsController.php:79 +msgid "Email sent successfully" +msgstr "Email enviado correctamente" + +#: Controller/SocialAccountsController.php:81 +msgid "Email could not be sent" +msgstr "No se puede enviar el email" + +#: Controller/SocialAccountsController.php:84 +msgid "Invalid account" +msgstr "Cuenta inválida" + +#: Controller/SocialAccountsController.php:86 +msgid "Social Account already active" +msgstr "Cuenta social ya activa" + +#: Controller/SocialAccountsController.php:88 +msgid "Email could not be resent" +msgstr "No se puede reenviar el Email" + +#: Controller/Component/RememberMeComponent.php:70 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "App salt inválido, debe contener al menos 256 bits (32 bytes)" + +#: Controller/Component/UsersAuthComponent.php:156 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"No es posible activar el flujo de trabajo para la validación de email si " +"use_mail es falso" + +#: Controller/Traits/LoginTrait.php:55 +msgid "" +"The social account is not active. Please check your email for instructions. " +"{0}" +msgstr "" +"La cuenta social está inactiva. Por favor, compruebe las instrucciones en tu " +"correo. {0}" + +#: Controller/Traits/LoginTrait.php:58 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Por favor, introduzca su email" + +#: Controller/Traits/LoginTrait.php:82 +msgid "Username or password is incorrect" +msgstr "Usuario o contraseña incorrecta" + +#: Controller/Traits/LoginTrait.php:93 +msgid "There was an error associating your social network account" +msgstr "Hubo un error al asociar su cuenta de la red social" + +#: Controller/Traits/LoginTrait.php:113 +msgid "You've successfully logged out" +msgstr "Ha cerrado sesión correctamente" + +#: Controller/Traits/PasswordManagementTrait.php:53 +msgid "Password has been changed successfully" +msgstr "Contraseña cambiada correctamente" + +#: Controller/Traits/PasswordManagementTrait.php:56;63 +msgid "Password could not be changed" +msgstr "No es posible cambiar la contraseña" + +#: Controller/Traits/PasswordManagementTrait.php:59 +#: Controller/Traits/ProfileTrait.php:46 +msgid "User was not found" +msgstr "Usuario no encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:61 +msgid "The current password does not match" +msgstr "La contraseña actual no coincide" + +#: Controller/Traits/PasswordManagementTrait.php:93 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Por favor, compruebe su correo para continuar con el proceso de " +"restablecimiento de contraseña" + +#: Controller/Traits/PasswordManagementTrait.php:96 +msgid "The password token could not be generated. Please try again" +msgstr "" +"No se pudo generar el token de contraseña. Por favor, inténtelo de nuevo" + +#: Controller/Traits/PasswordManagementTrait.php:101 +#: Controller/Traits/UserValidationTrait.php:94 +msgid "User {0} was not found" +msgstr "Usuario {0} no encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:103 +#: Controller/Traits/UserValidationTrait.php:90;98 +msgid "Token could not be reset" +msgstr "No se puede restablecer el token" + +#: Controller/Traits/RegisterTrait.php:66 +msgid "The user could not be saved" +msgstr "No se ha podido guardar el usuario" + +#: Controller/Traits/RegisterTrait.php:82 +msgid "You have registered successfully, please log in" +msgstr "Se ha registrado correctamente, por favor ingrese" + +#: Controller/Traits/RegisterTrait.php:84 +msgid "Please validate your account before log in" +msgstr "Por favor, valide su cuenta antes de ingresar" + +#: Controller/Traits/SimpleCrudTrait.php:75;103 +msgid "The {0} has been saved" +msgstr "El {0} ha sido guardado" + +#: Controller/Traits/SimpleCrudTrait.php:78;106 +msgid "The {0} could not be saved" +msgstr "El {0} no ha podido guardarse" + +#: Controller/Traits/SimpleCrudTrait.php:125 +msgid "The {0} has been deleted" +msgstr "El {0} ha sido eliminado" + +#: Controller/Traits/SimpleCrudTrait.php:127 +msgid "The {0} could not be deleted" +msgstr "El {0} no ha podido eliminarse" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "Cuenta de usuario validada correctamente" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "No se pudo validar la cuenta de usuario" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "Usuario ya activo" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "Restablecimiento del token de contraseña validado correctamente" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "Restablecimiento del token de contraseña no pudo validarse" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token and/or email" +msgstr "Token y/o email inválido" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Token ya expirado" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid validation type" +msgstr "Tipo de validación inválido" + +#: Controller/Traits/UserValidationTrait.php:88 +msgid "Token has been reset successfully. Please check your email." +msgstr "" +"Se ha restablecido el token correctamente. Por favor compruebe su email." + +#: Controller/Traits/UserValidationTrait.php:96 +msgid "User {0} is already active" +msgstr "El usuario {0} ya está activo" + +#: Model/Table/SocialAccountsTable.php:208 +msgid "{0}Your social account validation link" +msgstr "{0} Enlace de validación de su cuenta social" + +#: Model/Table/SocialAccountsTable.php:235;263 +msgid "Account already validated" +msgstr "Cuenta ya activada" + +#: Model/Table/SocialAccountsTable.php:238;266 +msgid "Account not found for the given token and email." +msgstr "Cuenta no encontrada para el token y email proporcionado" + +#: Model/Table/UsersTable.php:84 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" +"Su contraseña y la comprobación no concuerdan. Por favor inténtelo de nuevo" + +#: Model/Table/UsersTable.php:178 +msgid "Username already exists" +msgstr "Nombre de usuario ya existente" + +#: Model/Table/UsersTable.php:184 +msgid "Email already exists" +msgstr "Email ya existente" + +#: Model/Table/UsersTable.php:213 +msgid "The \"tos\" property is not present" +msgstr "La propiedad \"tos\" no está presente" + +#: Model/Table/UsersTable.php:271 +msgid "Token has already expired user with no token" +msgstr "El token ha expirado usuario sin token" + +#: Model/Table/UsersTable.php:274 +msgid "User not found for the given token and email." +msgstr "Usuario no encontrado para el token y email proporcionado" + +#: Model/Table/UsersTable.php:341 +msgid "User not found" +msgstr "Usuario no encontrado" + +#: Model/Table/UsersTable.php:368 +msgid "+ {0} secs" +msgstr "+ {0} secs" + +#: Model/Table/UsersTable.php:420 +msgid "Unable to login user with reference {0}" +msgstr "No se puede iniciar sesión con el usuario con referencia {0}" + +#: Model/Table/UsersTable.php:453 +msgid "Email not present" +msgstr "Email no presente" + +#: Model/Table/UsersTable.php:541 +msgid "{0}Your account validation link" +msgstr "{0} Enlace para validar su cuenta" + +#: Model/Table/UsersTable.php:561 +msgid "{0}Your reset password link" +msgstr "{0} Enlace para restablecer su contraseña" + +#: Model/Table/UsersTable.php:585 +msgid "The old password does not match" +msgstr "La antigua contraseña no coincide" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Hola {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Restablezca su contraseña aquí" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Si el enlace no se muestra correctamente, por favor copie la siguiente " +"dirección en su navegador web {0}" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Gracias" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Active su acceso social aquí" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Active su cuenta aquí" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Por favor copie la siguiente dirección en su navegador web {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Por favor copie la siguiente dirección en su navegador web para activar su " +"acceso social {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:13 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:13;77 +msgid "Actions" +msgstr "Acciones" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:21 +#: Template/Users/view.ctp:17 +msgid "List Users" +msgstr "Listar Usuarios" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:22 +#: Template/Users/view.ctp:19 +msgid "List Accounts" +msgstr "Listar Cuentas" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:15 +msgid "Add User" +msgstr "Añadir Usuario" + +#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:13 +#: Template/Users/edit.ctp:42 Template/Users/register.ctp:26 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Enviar" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Por favor introduzca la nueva contraseña" + +#: Template/Users/change_password.ctp:7 +msgid "Current password" +msgstr "Contraseña actual" + +#: Template/Users/edit.ctp:16 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:99 +msgid "Delete" +msgstr "Eliminar" + +#: Template/Users/edit.ctp:18 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:16;99 +msgid "Are you sure you want to delete # {0}?" +msgstr "¿Está seguro que quiere eliminar # {0}?" + +#: Template/Users/edit.ctp:28 Template/Users/view.ctp:15 +msgid "Edit User" +msgstr "Editar Usuario" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nuevo {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:95 +msgid "View" +msgstr "Ver" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Cambiar contraseña" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:97 +msgid "Edit" +msgstr "Editar" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "anterior" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "siguiente" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Por favor introduzca su usuario y contraseña" + +#: Template/Users/login.ctp:26 +msgid "Remember me" +msgstr "Recordarme" + +#: Template/Users/login.ctp:49 +msgid "Login" +msgstr "Ingresar" + +#: Template/Users/profile.ctp:18 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:23 +msgid "Change Password" +msgstr "Cambiar contraseña" + +#: Template/Users/profile.ctp:26 Template/Users/view.ctp:28;68 +msgid "Username" +msgstr "Usuario" + +#: Template/Users/profile.ctp:28 Template/Users/view.ctp:30 +msgid "Email" +msgstr "Email" + +#: Template/Users/profile.ctp:33 +msgid "Social Accounts" +msgstr "Cuentas sociales" + +#: Template/Users/profile.ctp:37 Template/Users/view.ctp:70 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:67 +msgid "Provider" +msgstr "Proveedor" + +#: Template/Users/profile.ctp:39 +msgid "Link" +msgstr "Enlace" + +#: Template/Users/register.ctp:23 +msgid "Accept TOS conditions?" +msgstr "¿Acepta las condiciones del servicios?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Por favor introduzca su email para restablecer su contraseña" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Reenviar email de validación" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email o usuario" + +#: Template/Users/view.ctp:16 +msgid "Delete User" +msgstr "Eliminar Usuario" + +#: Template/Users/view.ctp:18 +msgid "New User" +msgstr "Nuevo Usuario" + +#: Template/Users/view.ctp:26;65 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:32 +msgid "First Name" +msgstr "Nombre" + +#: Template/Users/view.ctp:34 +msgid "Last Name" +msgstr "Apellidos" + +#: Template/Users/view.ctp:36;71 +msgid "Token" +msgstr "Token" + +#: Template/Users/view.ctp:38 +msgid "Api Token" +msgstr "Api Token" + +#: Template/Users/view.ctp:42;73 +msgid "Active" +msgstr "Activo" + +#: Template/Users/view.ctp:46;72 +msgid "Token Expires" +msgstr "Token caduca" + +#: Template/Users/view.ctp:48 +msgid "Activation Date" +msgstr "Fecha de activación" + +#: Template/Users/view.ctp:50 +msgid "Tos Date" +msgstr "Fecha Tos" + +#: Template/Users/view.ctp:52;75 +msgid "Created" +msgstr "Creado" + +#: Template/Users/view.ctp:54;76 +msgid "Modified" +msgstr "Modificado" + +#: Template/Users/view.ctp:61 +msgid "Related Accounts" +msgstr "Cuentas relacionadas" + +#: Template/Users/view.ctp:66 +msgid "User Id" +msgstr "Id Usuario" + +#: Template/Users/view.ctp:69 +msgid "Reference" +msgstr "Referencia" + +#: Template/Users/view.ctp:74 +msgid "Data" +msgstr "Datos" + +#: View/Helper/UserHelper.php:43 +msgid "Sign in with Facebook" +msgstr "Ingresar con Facebook" + +#: View/Helper/UserHelper.php:57 +msgid "Sign in with Twitter" +msgstr "Ingresar con Twitter" + +#: View/Helper/UserHelper.php:71 +msgid "Logout" +msgstr "Salir" + +#: View/Helper/UserHelper.php:109 +msgid "Welcome, {0}" +msgstr "Bienvenido, {0}" From 821708347f38e858ee5db6fd590731c546216f9c Mon Sep 17 00:00:00 2001 From: florenciohernandez Date: Wed, 9 Mar 2016 10:55:51 +0000 Subject: [PATCH 0404/1476] Ref feature/spanish-translation: Addin es folder and rename .po and .mo files --- src/Locale/{es_ES.mo => es/Users.mo} | Bin 9620 -> 9650 bytes src/Locale/{es_ES.po => es/Users.po} | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) rename src/Locale/{es_ES.mo => es/Users.mo} (82%) rename src/Locale/{es_ES.po => es/Users.po} (99%) diff --git a/src/Locale/es_ES.mo b/src/Locale/es/Users.mo similarity index 82% rename from src/Locale/es_ES.mo rename to src/Locale/es/Users.mo index 865263d3bae9886c86f5886e82e58166f2938eb9..8e4f8f1c6d459a55f71483279b0ffad245793220 100644 GIT binary patch delta 1022 zcmXZaOGwmF6vy#XgHIZ5%tzz%pN^)+q+;PCw8+Rvnqn$ytcV^{NlZg(2qpc4!e|jK zYSAo$2zo#+BIzM0Mzj(tf}}-4M4JlR7_lbMO7%d(OG%e{c0Y?Rzrsb4Qn$ z9W6G?HM1`zW~=ch7GS|jvvRD(cHE2=cmcC9g&ehe-ufgKGXI2`xPbZi8*|VXG;2UV z>U&$zTwB4Qn*|y5KAb=mkiZPQgi1Ju%kc&(z+KG4hp2teQRk*mg}%o!{DlF`DNPqt zhFV`!>ZSwrvY-SJT#EZ}0Q*r1-(WY+A+fBG(+;jhCEAI)VFFdy2&%A)s1965#lM3p z^Z~|j+-0EFXVPas22g>jFoX?QjS)PIXYmkzz>U~McC|E#m6*aVe2HQF;~CUKvGODF7a2Zac{`D+6IFEJs z7q?-E;OayIyLf*#!ayx~hI;+4upYmo0tIT)H?P4C<{jRA2vy)U4B{iyO<#NKv*+NC2);#CSYDfcGsxQWD_*SFAKsOWA0HSF?@pc@JQnXcb!2cTKHTZ--Lo~^J~2}==l=)oRBYn_ delta 992 zcmXZaPe@cz6vy#nIx}icI+kOj{duKk2I3PZP)DtW3rk8RTnzpTK~Y*n+gv<|pg*7+ zh0?$v!j)h;P`EG%X;Wbv0~b=OKvFO?YE|_8IdAoO_q==WIrrSV)IQbzYBSU8&oCQ| zn&q0=yJE9S{Dg)03r}F^xLG}x<4NqpY#c+D+I>I%439Bh#vra?K7PR*{Ek()>;I3% z%(J5eoR}RLM=fka70`hJ97H7?!2-O4ns*P6;3L$$r>J$as6rR96hC7Gw^0TC_2c0Z zFTGJ!NjiaxhnUcSqu7K>IEO9x23c#r(ZK?CSE5?f2|G}QB~gXlL?yh9I)H~N^dTm3 zLIJgY3&XgN+9-p*m*ZhPi!Kh}4eY}dUcw03)zU6Jg=5%^GgyrqzCnI!-#98?3+k%8 zD}JCKnQNn%zz294SJA<&(`H3jfm)bAo`-d!3LQapYTS>{qB`*!L%4#P_a4vS59DB; ztbtJd_K@}Ed74OF4sKnQ>4u?=JoyI(Tj=Jl4bnq>n!*AGzK{h|Q zDr_ddCHYWGo}ga;3p|e>P#f)|P97-ZU0^9{+>I*m7V1qrMxFGfAD>5u@kh+W9n@R+ zi9M)x)V5+T9}Z67bzDGI_z(4HvMbUXN038U3@=~;b;rZ0>5!Wra2pygx|3_sz0}v@ G_3(cuMq\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -14,6 +14,7 @@ msgstr "" "X-Generator: Poedit 1.8.7\n" "Last-Translator: \n" "Language: es_ES\n" +"X-Poedit-SourceCharset: UTF-8\n" #: Auth/SimpleRbacAuthorize.php:132 msgid "" From cc8a716e052cf2dda564dc655920a7fa057cefdc Mon Sep 17 00:00:00 2001 From: Thinking Media Date: Thu, 10 Mar 2016 10:58:04 -0500 Subject: [PATCH 0405/1476] grammar --- Docs/Documentation/SimpleRbacAuthorize.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/SimpleRbacAuthorize.md b/Docs/Documentation/SimpleRbacAuthorize.md index 17e173465..ef21ca282 100644 --- a/Docs/Documentation/SimpleRbacAuthorize.md +++ b/Docs/Documentation/SimpleRbacAuthorize.md @@ -6,7 +6,7 @@ Setup SimpleRbacAuthorize is configured by default, but you can customize the way it works easily -Example, in you AppController, you can configure the way the SimpleRbac works by setting the options: +Example, in your AppController, you can configure the way the SimpleRbac works by setting the options: ```php $config['Auth']['authorize']['Users.SimpleRbac'] = [ From a8d9bde418aca0acfc3d001057c9e74e24eb1499 Mon Sep 17 00:00:00 2001 From: florenciohernandez Date: Fri, 11 Mar 2016 06:52:27 +0000 Subject: [PATCH 0406/1476] fix spanish translations --- src/Locale/es/Users.mo | Bin 9650 -> 9657 bytes src/Locale/es/Users.po | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo index 8e4f8f1c6d459a55f71483279b0ffad245793220..3cdcb7eb72785aedd845f1caf735aa4e74cb9fdf 100644 GIT binary patch delta 791 zcmXZaODIH97{Kv^@eD(Gj2Vx^cx!5gOfh*ZMa>E|4DzVn@PPW#UKPOcrMODUDhJ%=i^C#eU{4a38Kq>=A7(olOFsGCc zT_}lau^RnYg#$Q-OE`j0*o8r=H{c?c<34uaCHnB!wyE4qB#tmk3Qk}F#_V_%nX9%i zgooITAE>dRLa9RRMOinF#khd7(M^<-I;Tb(=Xd^bUV8rHU YquQ9##&mRY%5uAJ(~{<_cYW{p1D0i39RL6T delta 784 zcmXZaODM!a9KiAMT2@|L-n-Udz4Ho*&7&kDt6a1m$zhYQ>s3nfKM*;%b8sYO53&hG zNiGznIB}5+xjDEg-=F=TKJ%Mqe!uz6%z4jo&(Te^VN*(3vz1ClJKC`vE!c^1=)p)F zzzH106uiL}e8wzHWwXXg%)vgi;xtOWMNGmKlzLlsW&9V|Wg>=&ee_}w8|cP8 zY{NIyn4hau8n&bC^I``2Q4YF}a#M%q`~}KQJYg)p7z||LJLX}W4tG|D-Nd~pH?ob= z@i$UirLkBJR)?9`k5YINYjG9jMo%#TFHxTQ4mG}F5gNY?x)`{~{{L3kOuUG4BPUpl zS6G4{D2Z$Z;m!-Nk+{)}=TQ#0iCK7n(&@E1e}|g*6QlS_DxUV`GbG^GM`8F=7NI1rLV8dQScYDdH(m?v#8xNA)KoXs*M=U_-BGrV>9L6^?GNagIp4g` Szu*hyW#3vN7D8Y8A^HzM@l{^{ diff --git a/src/Locale/es/Users.po b/src/Locale/es/Users.po index 4548ab00c..88cbcdae2 100644 --- a/src/Locale/es/Users.po +++ b/src/Locale/es/Users.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" "POT-Creation-Date: 2016-03-07 20:35+0000\n" -"PO-Revision-Date: 2016-03-09 10:53+0000\n" +"PO-Revision-Date: 2016-03-09 21:06+0000\n" "Language-Team: CakeDC \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -78,7 +78,7 @@ msgid "" "The social account is not active. Please check your email for instructions. " "{0}" msgstr "" -"La cuenta social está inactiva. Por favor, compruebe las instrucciones en tu " +"La cuenta social está inactiva. Por favor, compruebe las instrucciones en su " "correo. {0}" #: Controller/Traits/LoginTrait.php:58 Template/Users/social_email.ctp:16 @@ -255,7 +255,7 @@ msgstr "No se puede iniciar sesión con el usuario con referencia {0}" #: Model/Table/UsersTable.php:453 msgid "Email not present" -msgstr "Email no presente" +msgstr "No se encuentra el email" #: Model/Table/UsersTable.php:541 msgid "{0}Your account validation link" From abaeeb52fa704fd951c85725901efc4086308edc Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 15 Mar 2016 07:51:49 -0500 Subject: [PATCH 0407/1476] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c7ed3efd1..ce4106d22 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ }, "require": { "php": ">=5.4.16", - "cakephp/cakephp": "~3.1" + "cakephp/cakephp": "~3.2" }, "require-dev": { "phpunit/phpunit": "*", From 3c0fc9ffb0a9404a6838b96a289f50e19a8559d7 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 15 Mar 2016 15:41:56 -0300 Subject: [PATCH 0408/1476] Refs #306 ensuring user is active when trying to reset password --- .../Traits/PasswordManagementTrait.php | 4 ++++ src/Model/Behavior/PasswordBehavior.php | 6 +++++ .../Traits/PasswordManagementTraitTest.php | 22 +++++++++++++++++++ .../Model/Behavior/PasswordBehaviorTest.php | 14 ++++++++++++ 4 files changed, 46 insertions(+) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index b7045ce57..dafdba623 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Controller\Traits; use CakeDC\Users\Exception\UserNotFoundException; +use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Exception\WrongPasswordException; use Cake\Core\Configure; use Exception; @@ -101,6 +102,7 @@ public function requestResetPassword() 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => false, 'sendEmail' => true, + 'ensureActive' => true ]); if ($resetUser) { $msg = __d('Users', 'Please check your email to continue with password reset process'); @@ -112,6 +114,8 @@ public function requestResetPassword() return $this->redirect(['action' => 'login']); } catch (UserNotFoundException $exception) { $this->Flash->error(__d('Users', 'User {0} was not found', $reference)); + } catch (UserNotActiveException $exception) { + $this->Flash->error(__d('Users', 'The user is not active')); } catch (Exception $exception) { $this->Flash->error(__d('Users', 'Token could not be reset')); } diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 4f13207f7..0bc19f2e5 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -14,6 +14,7 @@ use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; +use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Exception\WrongPasswordException; use CakeDC\Users\Model\Behavior\Behavior; use Cake\Datasource\EntityInterface; @@ -71,6 +72,11 @@ public function resetToken($reference, array $options = []) $user->active = false; $user->activation_date = null; } + if (Hash::Get($options, 'ensureActive')) { + if (!$user->active) { + throw new UserNotActiveException("User not active"); + } + } $user->updateToken($expiration); $saveResult = $this->_table->save($user); $template = !empty($options['emailTemplate']) ? $options['emailTemplate'] : 'CakeDC/Users.reset_password'; diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 3c64ebb75..a90a86c9e 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -157,4 +157,26 @@ public function testRequestPasswordHappy() $this->Trait->requestResetPassword(); $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000001')->token); } + + /** + * test requestResetPassword + * + * @return void + */ + public function testRequestResetPasswordUserNotActive() + { + $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); + $this->_mockRequestPost(); + $this->_mockFlash(); + $reference = 'user-1'; + $this->Trait->request->expects($this->once()) + ->method('data') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($this->any()) + ->method('error') + ->with('The user is not active'); + $this->Trait->requestResetPassword(); + $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000001')->token); + } } diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 238a7923d..18b4c3290 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -146,4 +146,18 @@ public function testResetTokenUserAlreadyActive() 'checkActive' => true, ]); } + + /** + * Test resetToken + * + * @expectedException CakeDC\Users\Exception\UserNotActiveException + */ + public function testResetTokenUserNotActive() + { + $user = TableRegistry::get('CakeDC/Users.Users')->findAllByUsername('user-1')->first(); + $this->Behavior->resetToken('user-1', [ + 'ensureActive' => true, + 'expiration' => 3600 + ]); + } } From c407d7fc9344949e9fa62b9b421ea148444355cd Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 15 Mar 2016 15:50:50 -0300 Subject: [PATCH 0409/1476] Refs #306 fixing PHPCS --- src/Controller/Traits/PasswordManagementTrait.php | 2 +- src/Model/Behavior/PasswordBehavior.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index dafdba623..5c76767d1 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; use Cake\Core\Configure; use Exception; diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 0bc19f2e5..f42e1a23b 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -13,8 +13,8 @@ use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\UserAlreadyActiveException; -use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; use CakeDC\Users\Model\Behavior\Behavior; use Cake\Datasource\EntityInterface; From 09f9cb6e166d6077aeeeea264c1b2eab6cd7a32f Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 15 Mar 2016 16:27:00 -0300 Subject: [PATCH 0410/1476] Refs #306 adding __d() and fixing mistype --- src/Model/Behavior/PasswordBehavior.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index f42e1a23b..044cb80b3 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -67,14 +67,14 @@ public function resetToken($reference, array $options = []) } if (Hash::get($options, 'checkActive')) { if ($user->active) { - throw new UserAlreadyActiveException("User account already validated"); + throw new UserAlreadyActiveException(__d('Users', "User account already validated")); } $user->active = false; $user->activation_date = null; } - if (Hash::Get($options, 'ensureActive')) { + if (Hash::get($options, 'ensureActive')) { if (!$user->active) { - throw new UserNotActiveException("User not active"); + throw new UserNotActiveException(__d('Users', "User not active")); } } $user->updateToken($expiration); From ebc15264a338668da97072fa100ad5d628517f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 15 Mar 2016 23:11:20 +0000 Subject: [PATCH 0411/1476] fix typo --- Docs/Documentation/Installation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index a586c144c..930b40062 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -12,9 +12,9 @@ if you want to use social login features... ``` composer require league/oauth2-facebook:@stable -composer require league/oauth2-instagram::@stable -composer require league/oauth2-google::@stable -composer require league/oauth2-linkedin::@stable +composer require league/oauth2-instagram:@stable +composer require league/oauth2-google:@stable +composer require league/oauth2-linkedin:@stable composer require league/oauth1-client:@stable ``` From 592eb1d2ba7465a78f7effb3fc9192abb7c9c2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 15 Mar 2016 23:16:49 +0000 Subject: [PATCH 0412/1476] fix typo --- 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 930b40062..d90929a46 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -62,7 +62,7 @@ return [ 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', 'OAuth.providers.facebook.options.clientSecret' => 'YOUR APP SECRET', 'OAuth.providers.twitter.options.clientId' => 'YOUR APP ID', - 'OAuth.providers.titter.options.clientSecret' => 'YOUR APP SECRET', + 'OAuth.providers.twitter.options.clientSecret' => 'YOUR APP SECRET', //etc ]; From a8e113f1ff9051cd964a114db43c06205f0d3eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 16 Mar 2016 00:46:24 +0000 Subject: [PATCH 0413/1476] fix twitter blank page, fix twitter missing provider issue, improve default login page display only configured providers --- config/routes.php | 3 --- config/users.php | 7 +++++- src/Controller/Traits/LoginTrait.php | 5 ++-- src/Model/Behavior/SocialBehavior.php | 15 ++++++----- src/Template/Users/login.ctp | 10 +------- src/View/Helper/UserHelper.php | 36 +++++++++++++++++++++++---- 6 files changed, 50 insertions(+), 26 deletions(-) diff --git a/config/routes.php b/config/routes.php index 191175c95..6c4331798 100644 --- a/config/routes.php +++ b/config/routes.php @@ -15,9 +15,6 @@ $routes->fallbacks('DashedRoute'); }); -//if (!Configure::check('OAuth.path')) { -// Configure::load('CakeDC/Users.users'); -//} Router::connect('/auth/twitter', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', diff --git a/config/users.php b/config/users.php index 3bde0bae0..d297a207f 100644 --- a/config/users.php +++ b/config/users.php @@ -109,7 +109,12 @@ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => Router::url('/auth/facebook', true) + 'redirectUri' => Router::url('/auth/facebook', true) + ] + ], + 'twitter' => [ + 'options' => [ + 'redirectUri' => Router::url('/auth/twitter', true) ] ], 'linkedIn' => [ diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index bf00fca59..5c8eee0c8 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -70,10 +70,11 @@ public function twitterLogin() } else { $temporaryCredentials = $server->getTemporaryCredentials(); $this->request->session()->write('temporary_credentials', $temporaryCredentials); - $server->authorize($temporaryCredentials); - return $this->response; + $url = $server->getAuthorizationUrl($temporaryCredentials); + return $this->redirect($url); } } + /** * @param Event $event event * @return void diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index f2f50ca05..48adafda4 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -118,10 +118,10 @@ protected function _createSocialUser($data, $options = []) * @param string $validateEmail email to validate. * @param string $tokenExpiration token_expires data. * @return EntityInterface + * @todo refactor */ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) { - $accountData['provider'] = Hash::get($data, 'provider'); $accountData['username'] = Hash::get($data, 'username'); $accountData['reference'] = Hash::get($data, 'id'); $accountData['avatar'] = Hash::get($data, 'avatar'); @@ -140,6 +140,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail } $accountData['data'] = serialize(Hash::get($data, 'raw')); $accountData['active'] = true; + $dataValidated = Hash::get($data, 'validated'); if (empty($existingUser)) { @@ -181,18 +182,20 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['validated'] = !empty($dataValidated); $userData['tos_date'] = date("Y-m-d H:i:s"); $userData['gender'] = Hash::get($data, 'gender'); - //$userData['timezone'] = Hash::get($data, 'timezone'); $userData['social_accounts'][] = $accountData; - $user = $this->_table->newEntity($userData, ['associated' => ['SocialAccounts']]); + + $user = $this->_table->newEntity($userData); $user = $this->_updateActive($user, false, $tokenExpiration); } else { if ($useEmail && empty($dataValidated)) { $accountData['active'] = false; } - $user = $this->_table->patchEntity($existingUser, [ - 'social_accounts' => [$accountData] - ], ['associated' => ['SocialAccounts']]); + $user = $existingUser; } + $socialAccount = $this->_table->SocialAccounts->newEntity($accountData); + //ensure provider is present in Entity + $socialAccount['provider'] = Hash::get($data, 'provider'); + $user['social_accounts'] = [$socialAccount]; return $user; } diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 3ea2712fc..1a0168514 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -43,15 +43,7 @@ use Cake\Core\Configure; ?>

- - - $options) : ?> - - User->socialLogin($provider); ?> - - - + User->socialLoginList()); ?> Form->button(__d('Users', 'Login')); ?> Form->end() ?>
diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 735fe4047..fe4511716 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -58,11 +58,37 @@ public function socialLogin($name, $options = []) if (empty($options['label'])) { $options['label'] = 'Sign in with'; } - return $this->Html->link($this->Html->tag('i', '', [ - 'class' => __d('Users', 'fa fa-{0}', strtolower($name)), - ]) . __d('Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)), "/auth/$name", [ - 'escape' => false, 'class' => __d('Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ? :'', strtolower($name)) - ]); + $icon = $this->Html->tag('i', '', [ + 'class' => __d('Users', 'fa fa-{0}', strtolower($name)), + ]); + $providerTitle = __d('Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)); + $providerClass = __d('Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', strtolower($name)); + return $this->Html->link($icon . $providerTitle, "/auth/$name", [ + 'escape' => false, 'class' => $providerClass + ]); + } + + /** + * All available Social Login Icons + * + * @return array Links to Social Login Urls + */ + public function socialLoginList() + { + if (!Configure::read('Users.Social.login')) { + return []; + } + $outProviders = []; + $providers = Configure::read('OAuth.providers'); + foreach ($providers as $provider => $options) { + if (!empty($options['options']['redirectUri']) && + !empty($options['options']['clientId']) && + !empty($options['options']['clientSecret'])) { + $outProviders[] = $this->socialLogin($provider); + } + } + + return $outProviders; } /** From f9b290f430b5e760d99d0bf3adf8ddef0f54cbc1 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Wed, 16 Mar 2016 14:32:10 -0300 Subject: [PATCH 0414/1476] Refs #306 using array access to enable not hydrated finds --- src/Model/Behavior/PasswordBehavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 044cb80b3..6eccdd182 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -73,7 +73,7 @@ public function resetToken($reference, array $options = []) $user->activation_date = null; } if (Hash::get($options, 'ensureActive')) { - if (!$user->active) { + if (!$user['active']) { throw new UserNotActiveException(__d('Users', "User not active")); } } From 89e0ea930623233c9df5b2d7a43d8d802a51ad82 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 22 Mar 2016 14:49:20 -0300 Subject: [PATCH 0415/1476] Refs #306 adding email config to enable it on tests --- .../Controller/Traits/BaseTraitTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 131d58aa5..6f6abf63d 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -185,4 +185,21 @@ protected function _mockDispatchEvent(Event $event = null) ->method('dispatchEvent') ->will($this->returnValue($event)); } + + /** + * Config email + * + * @return void + */ + protected function _configEmail() + { + \Cake\Mailer\Email::configTransport('default', [ + 'className' => 'Debug' + ]); + \Cake\Mailer\Email::config('default', [ + 'transport' => 'default', + 'from' => 'test@test.com', + 'log' => true + ]); + } } From bf2564edd92b805d54d52aae9c299982b24ef395 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 22 Mar 2016 14:49:40 -0300 Subject: [PATCH 0416/1476] Refs #306 improving test coverage --- .../Controller/Traits/PasswordManagementTraitTest.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index a90a86c9e..564bcda66 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -142,20 +142,21 @@ public function testRequestResetPasswordGet() */ public function testRequestPasswordHappy() { - $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); + $this->assertEquals('6614f65816754310a5f0553436dd89e9', $this->table->get('00000000-0000-0000-0000-000000000002')->token); $this->_mockRequestPost(); $this->_mockAuthLoggedIn(); $this->_mockFlash(); - $reference = 'user-1'; + $this->_configEmail(); + $reference = 'user-2'; $this->Trait->request->expects($this->once()) ->method('data') ->with('reference') ->will($this->returnValue($reference)); $this->Trait->Flash->expects($this->any()) ->method('success') - ->with('Password has been changed successfully'); + ->with('Please check your email to continue with password reset process'); $this->Trait->requestResetPassword(); - $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000001')->token); + $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000002')->token); } /** From 7347cddaf8f1b721beb47faefe4a1aff0db937b6 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 22 Mar 2016 15:08:24 -0300 Subject: [PATCH 0417/1476] Refs #306 removing email configuration and using the existing one --- .../Controller/Traits/BaseTraitTest.php | 17 ----------------- .../Traits/PasswordManagementTraitTest.php | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 6f6abf63d..131d58aa5 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -185,21 +185,4 @@ protected function _mockDispatchEvent(Event $event = null) ->method('dispatchEvent') ->will($this->returnValue($event)); } - - /** - * Config email - * - * @return void - */ - protected function _configEmail() - { - \Cake\Mailer\Email::configTransport('default', [ - 'className' => 'Debug' - ]); - \Cake\Mailer\Email::config('default', [ - 'transport' => 'default', - 'from' => 'test@test.com', - 'log' => true - ]); - } } diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 564bcda66..dbcad9d41 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -27,6 +27,7 @@ public function setUp() { $this->traitClassName = 'CakeDC\Users\Controller\Traits\PasswordManagementTrait'; $this->traitMockMethods = ['set', 'redirect', 'validate']; + $this->mockDefaultEmail = true; parent::setUp(); } @@ -146,7 +147,6 @@ public function testRequestPasswordHappy() $this->_mockRequestPost(); $this->_mockAuthLoggedIn(); $this->_mockFlash(); - $this->_configEmail(); $reference = 'user-2'; $this->Trait->request->expects($this->once()) ->method('data') From fb1b1ac925a1594b0df2d5225b95fd863ded9e31 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 22 Mar 2016 16:05:30 -0300 Subject: [PATCH 0418/1476] Refs #306 improving PasswordManagementTraitTest coverage --- src/Model/Behavior/PasswordBehavior.php | 11 ++- .../Controller/Traits/BaseTraitTest.php | 6 +- .../Traits/PasswordManagementTraitTest.php | 87 +++++++++++++++++++ 3 files changed, 98 insertions(+), 6 deletions(-) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 6eccdd182..0169fabdf 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -18,6 +18,7 @@ use CakeDC\Users\Exception\WrongPasswordException; use CakeDC\Users\Model\Behavior\Behavior; use Cake\Datasource\EntityInterface; +use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Mailer\Email; use Cake\Utility\Hash; use InvalidArgumentException; @@ -106,9 +107,13 @@ protected function _getUser($reference) */ public function changePassword(EntityInterface $user) { - $currentUser = $this->_table->get($user->id, [ - 'contain' => [] - ]); + try { + $currentUser = $this->_table->get($user->id, [ + 'contain' => [] + ]); + } catch (RecordNotFoundException $e) { + throw new UserNotFoundException(__d('Users', "User not found")); + } if (!empty($user->current_password)) { if (!$user->checkPassword($user->current_password, $currentUser->password)) { diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 131d58aa5..807c2652b 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -138,13 +138,13 @@ protected function _mockRequestPost($with = 'post') * * @return void */ - protected function _mockAuthLoggedIn() + protected function _mockAuthLoggedIn($user = array()) { $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) ->disableOriginalConstructor() ->getMock(); - $user = [ + $user += [ 'id' => '00000000-0000-0000-0000-000000000001', 'password' => '12345', ]; @@ -154,7 +154,7 @@ protected function _mockAuthLoggedIn() $this->Trait->Auth->expects($this->any()) ->method('user') ->with('id') - ->will($this->returnValue('00000000-0000-0000-0000-000000000001')); + ->will($this->returnValue($user['id'])); } /** diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index dbcad9d41..0eb22ed74 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -69,6 +69,51 @@ public function testChangePasswordHappy() $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); } + /** + * test + * + * @return void + */ + public function testChangePasswordWithError() + { + $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'wrong_new', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Password could not be changed'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithInvalidUser() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'new', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User was not found'); + $this->Trait->changePassword(); + } + /** * test * @@ -159,6 +204,48 @@ public function testRequestPasswordHappy() $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000002')->token); } + /** + * test + * + * @return void + */ + public function testRequestPasswordInvalidUser() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); + $this->_mockFlash(); + $reference = 'invalid-id'; + $this->Trait->request->expects($this->once()) + ->method('data') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($this->any()) + ->method('error') + ->with('User invalid-id was not found'); + $this->Trait->requestResetPassword(); + } + + /** + * test + * + * @return void + */ + public function testRequestPasswordEmptyReference() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); + $this->_mockFlash(); + $reference = ''; + $this->Trait->request->expects($this->once()) + ->method('data') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($this->any()) + ->method('error') + ->with('Token could not be reset'); + $this->Trait->requestResetPassword(); + } + /** * test requestResetPassword * From 100e7ccf984f55745c96b8cf29def12d46f99087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 23 Mar 2016 00:37:39 +0000 Subject: [PATCH 0419/1476] fix initial migration to use uuids, add missing FK --- config/Migrations/20150513201111_initial.php | 135 +++++++------------ 1 file changed, 52 insertions(+), 83 deletions(-) diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php index d1e11e0ec..b9e09fc69 100644 --- a/config/Migrations/20150513201111_initial.php +++ b/config/Migrations/20150513201111_initial.php @@ -13,171 +13,140 @@ class Initial extends AbstractMigration { - public function up() + public function change() { - $table = $this->table('social_accounts', ['id' => false, 'primary_key' => ['id']]); + $table = $this->table('users', ['id' => false, 'primary_key' => ['id']]); $table - ->addColumn('id', 'char', [ - 'default' => null, - 'limit' => 36, + ->addColumn('id', 'uuid', [ 'null' => false, ]) - ->addColumn('user_id', 'string', [ - 'default' => null, - 'limit' => 36, - 'null' => false, - ]) - ->addColumn('provider', 'string', [ - 'default' => null, + ->addColumn('username', 'string', [ 'limit' => 255, 'null' => false, ]) - ->addColumn('username', 'string', [ + ->addColumn('email', 'string', [ 'default' => null, 'limit' => 255, 'null' => true, ]) - ->addColumn('reference', 'string', [ - 'default' => null, + ->addColumn('password', 'string', [ 'limit' => 255, 'null' => false, ]) - ->addColumn('avatar', 'string', [ + ->addColumn('first_name', 'string', [ 'default' => null, - 'limit' => 255, + 'limit' => 50, 'null' => true, ]) - ->addColumn('description', 'text', [ + ->addColumn('last_name', 'string', [ 'default' => null, - 'limit' => null, + 'limit' => 50, 'null' => true, ]) - ->addColumn('link', 'string', [ + ->addColumn('token', 'string', [ 'default' => null, 'limit' => 255, - 'null' => false, + 'null' => true, ]) - ->addColumn('token', 'string', [ + ->addColumn('token_expires', 'datetime', [ 'default' => null, - 'limit' => 500, - 'null' => false, + 'null' => true, ]) - ->addColumn('token_secret', 'string', [ + ->addColumn('api_token', 'string', [ 'default' => null, - 'limit' => 500, + 'limit' => 255, 'null' => true, ]) - ->addColumn('token_expires', 'datetime', [ + ->addColumn('activation_date', 'datetime', [ + 'default' => null, + 'null' => true, + ]) + ->addColumn('tos_date', 'datetime', [ 'default' => null, - 'limit' => null, 'null' => true, ]) ->addColumn('active', 'boolean', [ - 'default' => true, + 'default' => false, 'null' => false, ]) - ->addColumn('data', 'text', [ - 'default' => null, - 'limit' => null, + ->addColumn('is_superuser', 'boolean', [ + 'default' => false, 'null' => false, ]) + ->addColumn('role', 'string', [ + 'default' => 'user', + 'limit' => 255, + 'null' => true, + ]) ->addColumn('created', 'datetime', [ - 'default' => null, - 'limit' => null, 'null' => false, ]) ->addColumn('modified', 'datetime', [ - 'default' => null, - 'limit' => null, 'null' => false, ]) ->create(); - $table = $this->table('users', ['id' => false, 'primary_key' => ['id']]); + + $table = $this->table('social_accounts', ['id' => false, 'primary_key' => ['id']]); $table - ->addColumn('id', 'char', [ - 'default' => null, - 'limit' => 36, + ->addColumn('id', 'uuid', [ 'null' => false, ]) - ->addColumn('username', 'string', [ - 'default' => null, + ->addColumn('user_id', 'uuid', [ + 'null' => false, + ]) + ->addColumn('provider', 'string', [ 'limit' => 255, 'null' => false, ]) - ->addColumn('email', 'string', [ + ->addColumn('username', 'string', [ 'default' => null, 'limit' => 255, 'null' => true, ]) - ->addColumn('password', 'string', [ - 'default' => null, + ->addColumn('reference', 'string', [ 'limit' => 255, 'null' => false, ]) - ->addColumn('first_name', 'string', [ - 'default' => null, - 'limit' => 50, - 'null' => true, - ]) - ->addColumn('last_name', 'string', [ - 'default' => null, - 'limit' => 50, - 'null' => true, - ]) - ->addColumn('token', 'string', [ + ->addColumn('avatar', 'string', [ 'default' => null, 'limit' => 255, 'null' => true, ]) - ->addColumn('token_expires', 'datetime', [ + ->addColumn('description', 'text', [ 'default' => null, - 'limit' => null, 'null' => true, ]) - ->addColumn('api_token', 'string', [ - 'default' => null, + ->addColumn('link', 'string', [ 'limit' => 255, - 'null' => true, + 'null' => false, ]) - ->addColumn('activation_date', 'datetime', [ + ->addColumn('token', 'string', [ + 'limit' => 500, + 'null' => false, + ]) + ->addColumn('token_secret', 'string', [ 'default' => null, - 'limit' => null, + 'limit' => 500, 'null' => true, ]) - ->addColumn('tos_date', 'datetime', [ + ->addColumn('token_expires', 'datetime', [ 'default' => null, - 'limit' => null, 'null' => true, ]) ->addColumn('active', 'boolean', [ - 'default' => false, + 'default' => true, 'null' => false, ]) - ->addColumn('is_superuser', 'boolean', [ - 'default' => false, + ->addColumn('data', 'text', [ 'null' => false, ]) - ->addColumn('role', 'string', [ - 'default' => 'user', - 'limit' => 255, - 'null' => true, - ]) ->addColumn('created', 'datetime', [ - 'default' => null, - 'limit' => null, 'null' => false, ]) ->addColumn('modified', 'datetime', [ - 'default' => null, - 'limit' => null, 'null' => false, ]) + ->addForeignKey('user_id', 'users', 'id', array('delete' => 'CASCADE', 'update' => 'CASCADE')) ->create(); } - - public function down() - { - $this->dropTable('social_accounts'); - $this->dropTable('users'); - } } From 51c5a2f30f86aa70d397a8748b0624fe47314245 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Thu, 24 Mar 2016 13:40:41 -0300 Subject: [PATCH 0420/1476] Refs #306 fixing phpcs issue --- tests/TestCase/Controller/Traits/BaseTraitTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 807c2652b..e386973dd 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -138,7 +138,7 @@ protected function _mockRequestPost($with = 'post') * * @return void */ - protected function _mockAuthLoggedIn($user = array()) + protected function _mockAuthLoggedIn($user = []) { $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) From 97515bd4e6a4f3e2976d9e43c56206cc06356b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 27 Mar 2016 18:28:11 +0100 Subject: [PATCH 0421/1476] refactor login() to use redirectUrl instead of referrer --- src/Controller/Traits/LoginTrait.php | 12 ++++++------ tests/TestCase/Controller/Traits/LoginTraitTest.php | 6 +++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 5c8eee0c8..cd851226d 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -152,17 +152,17 @@ public function login() $socialLogin = $this->_isSocialLogin(); + if ($this->request->is('post')) { + $user = $this->Auth->identify(); + return $this->_afterIdentifyUser($user, $socialLogin); + } if (!$this->request->is('post') && !$socialLogin) { if ($this->Auth->user()) { $msg = __d('Users', 'You are already logged in'); $this->Flash->error($msg); - return $this->redirect($this->referer()); + $url = $this->Auth->redirectUrl(); + return $this->redirect($url); } - return; - } - if ($this->request->is('post')) { - $user = $this->Auth->identify(); - return $this->_afterIdentifyUser($user, $socialLogin); } } diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index e60b6db8d..254d50f87 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -230,7 +230,11 @@ public function testLoginGet() ->setMethods(['is']) ->disableOriginalConstructor() ->getMock(); - $this->Trait->request->expects($this->once()) + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + $this->Trait->request->expects($this->at(1)) ->method('is') ->with('post') ->will($this->returnValue(false)); From 6d304cc2a44fdaabfa3529f55e1faf002e06bd53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 27 Mar 2016 18:34:39 +0100 Subject: [PATCH 0422/1476] improve time based tests --- tests/TestCase/Model/Entity/UserTest.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index d7028a87c..6c264460f 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -175,9 +175,7 @@ public function testUpdateTokenAdd() $this->assertNull($this->User['token']); $this->assertNull($this->User['token_expires']); $this->User->updateToken(20); - $nowModified = new Time('now'); - $nowModified->addSecond(20); - $this->assertEquals($nowModified, $this->User['token_expires']); + $this->assertEquals('20 seconds', $this->User['token_expires']->diffForHumans($this->now)); $this->assertNotNull($this->User['token']); } @@ -191,9 +189,7 @@ public function testUpdateTokenExistingAdd() $this->User['token'] = 'aaa'; $this->User['token_expires'] = $this->now; $this->User->updateToken(20); - $nowModified = new Time('now'); - $nowModified->addSecond(20); - $this->assertEquals($nowModified, $this->User['token_expires']); + $this->assertEquals('20 seconds', $this->User['token_expires']->diffForHumans($this->now)); $this->assertNotEquals('aaa', $this->User['token']); } } From 141e61001d87f7efc068760fd06cf65aa545ce3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 27 Mar 2016 18:49:53 +0100 Subject: [PATCH 0423/1476] fix tests --- tests/TestCase/Controller/Traits/BaseTraitTest.php | 4 ++-- tests/TestCase/Model/Entity/UserTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 131d58aa5..f02c2edb5 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -95,7 +95,7 @@ public function tearDown() protected function _mockRequestGet() { $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'referer']) + ->setMethods(['is', 'referer', 'data']) ->getMock(); $this->Trait->request->expects($this->any()) ->method('is') @@ -125,7 +125,7 @@ protected function _mockFlash() protected function _mockRequestPost($with = 'post') { $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'data']) + ->setMethods(['is', 'data', 'allow']) ->getMock(); $this->Trait->request->expects($this->any()) ->method('is') diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index 6c264460f..51894aa2e 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -175,7 +175,7 @@ public function testUpdateTokenAdd() $this->assertNull($this->User['token']); $this->assertNull($this->User['token_expires']); $this->User->updateToken(20); - $this->assertEquals('20 seconds', $this->User['token_expires']->diffForHumans($this->now)); + $this->assertEquals('20 seconds after', $this->User['token_expires']->diffForHumans($this->now)); $this->assertNotNull($this->User['token']); } @@ -189,7 +189,7 @@ public function testUpdateTokenExistingAdd() $this->User['token'] = 'aaa'; $this->User['token_expires'] = $this->now; $this->User->updateToken(20); - $this->assertEquals('20 seconds', $this->User['token_expires']->diffForHumans($this->now)); + $this->assertEquals('20 seconds after', $this->User['token_expires']->diffForHumans($this->now)); $this->assertNotEquals('aaa', $this->User['token']); } } From 65b9488843cbd4f15f791f09a8f6d21e0654e783 Mon Sep 17 00:00:00 2001 From: Pedro Fernandes Steimbruch Date: Tue, 29 Mar 2016 11:19:13 -0300 Subject: [PATCH 0424/1476] Refs #306 fixing tests on pgsql --- .../Controller/Traits/PasswordManagementTraitTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 0eb22ed74..bbd83d76c 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -100,7 +100,7 @@ public function testChangePasswordWithError() public function testChangePasswordWithInvalidUser() { $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); + $this->_mockAuthLoggedIn(['id' => '12312312-0000-0000-0000-000000000002', 'password' => 'invalid-pass']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) ->method('data') @@ -214,14 +214,14 @@ public function testRequestPasswordInvalidUser() $this->_mockRequestPost(); $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); $this->_mockFlash(); - $reference = 'invalid-id'; + $reference = '12312312-0000-0000-0000-000000000002'; $this->Trait->request->expects($this->once()) ->method('data') ->with('reference') ->will($this->returnValue($reference)); $this->Trait->Flash->expects($this->any()) ->method('error') - ->with('User invalid-id was not found'); + ->with('User 12312312-0000-0000-0000-000000000002 was not found'); $this->Trait->requestResetPassword(); } From 9c8cc61f98212459b81e29334ea936d3499c5089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sat, 2 Apr 2016 17:50:36 +0100 Subject: [PATCH 0425/1476] Fix outdated docs --- Docs/Documentation/UserHelper.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md index 062b8111e..146b23c68 100644 --- a/Docs/Documentation/UserHelper.md +++ b/Docs/Documentation/UserHelper.md @@ -25,9 +25,7 @@ You can use the helper included with the plugin to create Facebook/Twitter butto In templates ```php -$this->User->facebookLogin(); - -$this->User->twitterLogin(); +$this->User->socialLogin($provider); //provider is 'facebook', 'twitter', etc ``` We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. From e431530160243ad776d79fd9fbfa0de35618bcd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sat, 2 Apr 2016 17:51:45 +0100 Subject: [PATCH 0426/1476] Update UserHelper.md --- Docs/Documentation/UserHelper.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md index 146b23c68..3d36e41df 100644 --- a/Docs/Documentation/UserHelper.md +++ b/Docs/Documentation/UserHelper.md @@ -25,7 +25,7 @@ You can use the helper included with the plugin to create Facebook/Twitter butto In templates ```php -$this->User->socialLogin($provider); //provider is 'facebook', 'twitter', etc +echo $this->User->socialLogin($provider); //provider is 'facebook', 'twitter', etc ``` We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. From 2dde941aad1cd2448fb002d786e8ec287474ecc1 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Sun, 3 Apr 2016 16:26:16 -0500 Subject: [PATCH 0427/1476] Get large avatar from facebook. Improve profile message to consider username too. --- src/Auth/Social/Mapper/Facebook.php | 2 +- src/View/Helper/UserHelper.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Auth/Social/Mapper/Facebook.php b/src/Auth/Social/Mapper/Facebook.php index 0a2193984..95f3c52c3 100644 --- a/src/Auth/Social/Mapper/Facebook.php +++ b/src/Auth/Social/Mapper/Facebook.php @@ -39,6 +39,6 @@ class Facebook extends AbstractMapper */ protected function _avatar() { - return self::FB_GRAPH_BASE_URL . Hash::get($this->_rawData, 'id') . '/picture?type=normal'; + return self::FB_GRAPH_BASE_URL . Hash::get($this->_rawData, 'id') . '/picture?type=large'; } } diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index fe4511716..977dab1c2 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -149,7 +149,7 @@ public function welcome() } $profileUrl = Configure::read('Users.Profile.route'); - $label = __d('Users', 'Welcome, {0}', $this->Html->link($this->request->session()->read('Auth.User.first_name'), $profileUrl)); + $label = __d('Users', 'Welcome, {0}', $this->Html->link($this->request->session()->read('Auth.User.first_name') ?: $this->request->session()->read('Auth.User.username'), $profileUrl)); return $this->Html->tag('span', $label, ['class' => 'welcome']); } From 2afff101ead464acf8878777b5bf8c871ee3e14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 6 Apr 2016 12:42:36 +0100 Subject: [PATCH 0428/1476] Add specific note about callback urls --- Docs/Documentation/Installation.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index d90929a46..0a4278478 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -65,8 +65,12 @@ return [ 'OAuth.providers.twitter.options.clientSecret' => 'YOUR APP SECRET', //etc ]; - ``` +IMPORTANT: Remember you'll need to configure your social login application **callback url** to use the provider specific endpoint, for example: +* Facebook App Callback URL --> `http://yourdomain.com/auth/facebook` +* Twitter App Callback URL --> `http://yourdomain.com/auth/twitter` +* Google App Callback URL --> `http://yourdomain.com/auth/google` +* etc. Note: using social authentication is not required. From 2df6ff9b14185cbbe3392b89116740779e9761f1 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Wed, 6 Apr 2016 09:43:46 -0500 Subject: [PATCH 0429/1476] Update SimpleRbacAuthorize.md --- Docs/Documentation/SimpleRbacAuthorize.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/SimpleRbacAuthorize.md b/Docs/Documentation/SimpleRbacAuthorize.md index ef21ca282..f0a34c71d 100644 --- a/Docs/Documentation/SimpleRbacAuthorize.md +++ b/Docs/Documentation/SimpleRbacAuthorize.md @@ -9,7 +9,7 @@ SimpleRbacAuthorize is configured by default, but you can customize the way it w Example, in your AppController, you can configure the way the SimpleRbac works by setting the options: ```php -$config['Auth']['authorize']['Users.SimpleRbac'] = [ +$config['Auth']['authorize']['CakeDC/Users.SimpleRbac'] = [ //autoload permissions.php 'autoload_config' => 'permissions', //role field in the Users table From 8e975e00296ce13a81a9e708b3639f4530913ed0 Mon Sep 17 00:00:00 2001 From: Brandt Heisey Date: Sat, 9 Apr 2016 08:58:20 -0400 Subject: [PATCH 0430/1476] Update Configuration.md Small typo, change ```bootstrap.ctp``` to ```bootstrap.php``` on line 126 --- 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 c4744b6c6..95a1746ea 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -123,7 +123,7 @@ Using the UsersAuthComponent default initialization, the component will load the ## 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.ctp file, after CakeDC/Users Plugin is loaded +* Change the Auth.authenticate.Form.fields configuration to let AuthComponent use the email instead of the username for user identify. Add this line to your bootstrap.php file, after CakeDC/Users Plugin is loaded ```php Configure::write('Auth.authenticate.Form.fields.username', 'email'); From 51b6b4962fbe2317dd6b21fa6387e6ba92e02a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 10 Apr 2016 02:48:14 +0100 Subject: [PATCH 0431/1476] refs #351 improve reCaptcha, add documentation and some cleanup --- Docs/Documentation/Configuration.md | 10 +++++ Docs/Documentation/Installation.md | 11 ++++- Docs/Documentation/Overview.md | 2 +- Docs/Documentation/UserHelper.md | 8 ++-- config/users.php | 10 +++++ src/Auth/SocialAuthenticate.php | 7 +++- src/Controller/Traits/LoginTrait.php | 21 ++++++++++ src/Controller/Traits/ReCaptchaTrait.php | 13 +++--- src/Controller/Traits/RegisterTrait.php | 11 ++--- src/Controller/UsersController.php | 2 + src/Template/Users/login.ctp | 5 ++- src/Template/Users/register.ctp | 4 +- src/Template/Users/social_email.ctp | 1 - src/View/Helper/UserHelper.php | 23 ++--------- .../Controller/Traits/RegisterTraitTest.php | 41 ++++++++++++++++++- tests/TestCase/View/Helper/UserHelperTest.php | 10 ++--- 16 files changed, 125 insertions(+), 54 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index c4744b6c6..9307be00f 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -38,6 +38,16 @@ Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRE Or use the config override option when loading the plugin (see above) +Configuration for reCaptcha +--------------------- +``` +Configure::write('Users.reCaptcha.key', 'YOUR RECAPTCHA KEY'); +Configure::write('Users.reCaptcha.secret', 'YOUR RECAPTCHA SECRET'); +Configure::write('Users.reCaptcha.registration', true); //enable on registration +Configure::write('Users.reCaptcha.login', true); //enable on login +``` + + Configuration options --------------------- diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index d90929a46..02a6c5f7c 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -8,7 +8,7 @@ Composer composer require cakedc/users ``` -if you want to use social login features... +If you want to use social login features... ``` composer require league/oauth2-facebook:@stable @@ -25,6 +25,15 @@ login is disabled by default. Check the [Configuration](Configuration.md) page f Configure::write('Users.Social.login', true); //to enable social login ``` +If you want to use reCaptcha features... + +``` +composer require google/recaptcha:@stable +``` + +NOTE: you'll need to configure the reCaptcha key and secret, check the [Configuration](Configuration.md) +page for more details. + Creating Required Tables ------------------------ If you want to use the Users tables to store your users and social accounts: diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md index 0e98fc30e..4e2e392ba 100644 --- a/Docs/Documentation/Overview.md +++ b/Docs/Documentation/Overview.md @@ -14,5 +14,5 @@ The plugin itself is already capable of: * Simple roles management * Simple Rbac and SuperUser Authorize * RememberMe using cookie feature -* reCaptcha for user registration +* reCaptcha for user registration and login diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md index 3d36e41df..2191f4c1f 100644 --- a/Docs/Documentation/UserHelper.md +++ b/Docs/Documentation/UserHelper.md @@ -57,12 +57,10 @@ It displays a welcome message for the user including the name and a link to the $this->User->welcome(); ``` -reCAPTCHA +reCaptcha ----------------- -If you have configured reCAPTCHA for registration and have the proper key/secret configured then you will see the reCAPTCHA in registration page automatically. - -You could also use it in another templates with the following methods: +Handles the reCaptcha input display: ```php $this->User->addReCaptchaScript(); @@ -70,4 +68,4 @@ $this->User->addReCaptchaScript(); $this->User->addReCaptcha(); ``` -Note that the script is added automatically if the feature is enabled in config. +Note reCaptcha script is added to script block when `addReCaptcha` method is called. diff --git a/config/users.php b/config/users.php index d297a207f..59a239ce8 100644 --- a/config/users.php +++ b/config/users.php @@ -34,6 +34,16 @@ //determines if the reCaptcha is enabled for registration 'reCaptcha' => true, ], + 'reCaptcha' => [ + //reCaptcha key goes here + 'key' => null, + //reCaptcha secret + 'secret' => null, + //use reCaptcha in registration + 'registration' => false, + //use reCaptcha in login, valid values are false, true + 'login' => false, + ], 'Tos' => [ //determines if the user should include tos accepted 'required' => true, diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index a18c7e5e9..26cc411ed 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -354,7 +354,12 @@ public function getUser(Request $request) } $provider = $this->_getProviderName($request); - $user = $this->_mapUser($provider, $rawData); + try { + $user = $this->_mapUser($provider, $rawData); + } catch (MissingProviderException $ex) { + $request->session()->delete(Configure::read('Users.Key.Session.social')); + throw $ex; + } if ($user['provider'] === SocialAccountsTable::PROVIDER_TWITTER) { $request->session()->write(Configure::read('Users.Key.Session.social'), $user); } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index cd851226d..9d9e0a19b 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -153,6 +153,10 @@ public function login() $socialLogin = $this->_isSocialLogin(); if ($this->request->is('post')) { + if (!$this->_checkReCaptcha()) { + $this->Flash->error(__d('Users', 'Invalid reCaptcha')); + return; + } $user = $this->Auth->identify(); return $this->_afterIdentifyUser($user, $socialLogin); } @@ -166,6 +170,23 @@ public function login() } } + /** + * Check reCaptcha if enabled for login + * + * @return bool + */ + protected function _checkReCaptcha() + { + if (!Configure::read('Users.reCaptcha.login')) { + return true; + } + + return $this->validateReCaptcha( + $this->request->data('g-recaptcha-response'), + $this->request->clientIp() + ); + } + /** * Update remember me and determine redirect url after user identified * @param array $user user data after identified diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php index 825e410f8..44359a202 100644 --- a/src/Controller/Traits/ReCaptchaTrait.php +++ b/src/Controller/Traits/ReCaptchaTrait.php @@ -12,7 +12,6 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; -use ReCaptcha\ReCaptcha; /** * Covers registration features and email token validation @@ -30,13 +29,12 @@ trait ReCaptchaTrait */ public function validateReCaptcha($recaptchaResponse, $clientIp) { - $validReCaptcha = true; $recaptcha = $this->_getReCaptchaInstance(); if (!empty($recaptcha)) { $response = $recaptcha->verify($recaptchaResponse, $clientIp); - $validReCaptcha = $response->isSuccess(); + return $response->isSuccess(); } - return $validReCaptcha; + return false; } /** @@ -46,10 +44,9 @@ public function validateReCaptcha($recaptchaResponse, $clientIp) */ protected function _getReCaptchaInstance() { - $useReCaptcha = (bool)Configure::read('Users.Registration.reCaptcha'); - $reCaptchaSecret = Configure::read('reCaptcha.secret'); - if ($useReCaptcha && !empty($reCaptchaSecret)) { - return new ReCaptcha($reCaptchaSecret); + $reCaptchaSecret = Configure::read('Users.reCaptcha.secret'); + if (!empty($reCaptchaSecret)) { + return new \ReCaptcha\ReCaptcha($reCaptchaSecret); } return null; } diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 822618cd9..1aa65882f 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -24,7 +24,6 @@ trait RegisterTrait { use PasswordManagementTrait; - use ReCaptchaTrait; /** * Register a new user @@ -70,9 +69,8 @@ public function register() return; } - $validPost = $this->_validateRegisterPost(); - if (!$validPost) { - $this->Flash->error(__d('Users', 'The reCaptcha could not be validated')); + if (!$this->_validateRegisterPost()) { + $this->Flash->error(__d('Users', 'Invalid reCaptcha')); return; } @@ -92,14 +90,13 @@ public function register() */ protected function _validateRegisterPost() { - if (!Configure::read('Users.Registration.reCaptcha')) { + if (!Configure::read('Users.reCaptcha.registration')) { return true; } - $validReCaptcha = $this->validateReCaptcha( + return $this->validateReCaptcha( $this->request->data('g-recaptcha-response'), $this->request->clientIp() ); - return $validReCaptcha; } /** diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 45cd15827..72235a8fc 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -15,6 +15,7 @@ use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Controller\Traits\ProfileTrait; +use CakeDC\Users\Controller\Traits\ReCaptchaTrait; use CakeDC\Users\Controller\Traits\RegisterTrait; use CakeDC\Users\Controller\Traits\SimpleCrudTrait; use CakeDC\Users\Controller\Traits\SocialTrait; @@ -31,6 +32,7 @@ class UsersController extends AppController { use LoginTrait; use ProfileTrait; + use ReCaptchaTrait; use RegisterTrait; use SimpleCrudTrait; use SocialTrait; diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 1a0168514..24b791185 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -20,6 +20,9 @@ use Cake\Core\Configure; Form->input('username', ['required' => true]) ?> Form->input('password', ['required' => true]) ?> User->addReCaptcha(); + } if (Configure::check('Users.RememberMe.active')) { echo $this->Form->input(Configure::read('Users.Key.Data.rememberMe'), [ 'type' => 'checkbox', @@ -28,7 +31,6 @@ use Cake\Core\Configure; ]); } ?> -

Html->link(__d('users', 'Reset Password'), ['action' => 'requestResetPassword']); } ?> -

User->socialLoginList()); ?> Form->button(__d('Users', 'Login')); ?> diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index f217de2f4..2c1467db3 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -24,7 +24,9 @@ use Cake\Core\Configure; if (Configure::read('Users.Tos.required')) { echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); } - echo $this->User->addReCaptcha(); + if (Configure::read('Users.reCaptcha.registration')) { + echo $this->User->addReCaptcha(); + } ?> Form->button(__d('Users', 'Submit')) ?> diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp index 4ac0f9071..52cc6086e 100644 --- a/src/Template/Users/social_email.ctp +++ b/src/Template/Users/social_email.ctp @@ -16,7 +16,6 @@ Form->input('email') ?> - User->addReCaptcha(); ?> Form->button(__d('Users', 'Submit')); ?> Form->end() ?>
diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index fe4511716..049f053b4 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -33,19 +33,6 @@ class UserHelper extends Helper */ protected $_defaultConfig = []; - /** - * beforeLayout callback loads reCaptcha if enabled - * - * @param Event $event event - * @return void - */ - public function beforeLayout(Event $event) - { - if (Configure::read('Users.Registration.reCaptcha')) { - $this->addReCaptchaScript(); - } - } - /** * Social login link * @@ -170,16 +157,14 @@ public function addReCaptchaScript() */ public function addReCaptcha() { - if (!Configure::read('Users.Registration.reCaptcha')) { - return false; - } - if (!Configure::read('reCaptcha.key')) { - return $this->Html->tag('p', __d('Users', 'reCaptcha is not configured! Please configure reCaptcha.key or set Users.Registration.reCaptcha to false')); + if (!Configure::read('Users.reCaptcha.key')) { + return $this->Html->tag('p', __d('Users', 'reCaptcha is not configured! Please configure Users.reCaptcha.key')); } + $this->addReCaptchaScript(); $this->Form->unlockField('g-recaptcha-response'); return $this->Html->tag('div', '', [ 'class' => 'g-recaptcha', - 'data-sitekey' => Configure::read('reCaptcha.key') + 'data-sitekey' => Configure::read('Users.reCaptcha.key') ]); } } diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 0ea8e721e..1454e212b 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -63,8 +63,40 @@ public function testValidateEmail() * * @return void */ - public function testRegisterHappy() + public function testRegister() { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->data = [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ]; + + $this->Trait->register(); + + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterReCaptcha() + { + Configure::write('Users.reCaptcha.registration', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); $this->_mockAuth(); @@ -90,6 +122,7 @@ public function testRegisterHappy() $this->Trait->register(); $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + Configure::write('Users.reCaptcha.registration', false); } /** @@ -99,6 +132,7 @@ public function testRegisterHappy() */ public function testRegisterValidationErrors() { + Configure::write('Users.reCaptcha.registration', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); $this->_mockAuth(); @@ -123,6 +157,7 @@ public function testRegisterValidationErrors() $this->Trait->register(); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + Configure::write('Users.reCaptcha.registration', false); } /** @@ -132,6 +167,7 @@ public function testRegisterValidationErrors() */ public function testRegisterRecaptchaNotValid() { + Configure::write('Users.reCaptcha.registration', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); $this->_mockAuth(); @@ -139,7 +175,7 @@ public function testRegisterRecaptchaNotValid() $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) ->method('error') - ->with('The reCaptcha could not be validated'); + ->with('Invalid reCaptcha'); $this->Trait->expects($this->once()) ->method('validateRecaptcha') ->will($this->returnValue(false)); @@ -154,6 +190,7 @@ public function testRegisterRecaptchaNotValid() $this->Trait->register(); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + Configure::write('Users.reCaptcha.registration', false); } /** diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 6da81b94f..5e5038f70 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -206,11 +206,9 @@ public function testWelcomeNotLoggedInUser() */ public function testAddReCaptcha() { - $siteKey = Configure::read('reCaptcha.key'); - Configure::write('reCaptcha.key', 'testKey'); + Configure::write('Users.reCaptcha.key', 'testKey'); $result = $this->User->addReCaptcha(); $this->assertEquals('
', $result); - Configure::write('reCaptcha.key', $siteKey); } /** @@ -220,11 +218,11 @@ public function testAddReCaptcha() */ public function testAddReCaptchaEmpty() { - Configure::write('Users.Registration.reCaptcha', false); $result = $this->User->addReCaptcha(); - $this->assertFalse($result); + $expected = '

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

'; + $this->assertEquals($expected, $result); } - + /** * Test add ReCaptcha field * From 300d54157040ba1302d817708beed3327c520c61 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 15 Apr 2016 08:17:24 -0500 Subject: [PATCH 0432/1476] Fix router initialization in config file. fixes #359 --- config/users.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/users.php b/config/users.php index d297a207f..48496a0de 100644 --- a/config/users.php +++ b/config/users.php @@ -109,31 +109,31 @@ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => Router::url('/auth/facebook', true) + 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', ] ], 'twitter' => [ 'options' => [ - 'redirectUri' => Router::url('/auth/twitter', true) + 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', ] ], 'linkedIn' => [ 'className' => 'League\OAuth2\Client\Provider\LinkedIn', 'options' => [ - 'redirectUri' => Router::url('/auth/linkedIn', true) + 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', ] ], 'instagram' => [ 'className' => 'League\OAuth2\Client\Provider\Instagram', 'options' => [ - 'redirectUri' => Router::url('/auth/instagram', true) + 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', ] ], 'google' => [ 'className' => 'League\OAuth2\Client\Provider\Google', 'options' => [ 'userFields' => ['url', 'aboutMe'], - 'redirectUri' => Router::url('/auth/google', true) + 'redirectUri' => Router::fullBaseUrl() . '/auth/google', ] ], ], From 91796b6dba7d75aa4e97e7212c350c9ceb09b6bb Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 15 Apr 2016 08:25:37 -0500 Subject: [PATCH 0433/1476] Fix unit tests for facebook --- tests/TestCase/Auth/SocialAuthenticateTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index babfae221..80e40ab20 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -404,7 +404,7 @@ public function testMapUser($data, $mappedData) $result = $mapUser->invoke($this->SocialAuthenticate, 'Facebook', $data); unset($result['raw']); - $this->assertEquals($result, $mappedData); + $this->assertEquals($mappedData, $result); } /** @@ -432,7 +432,7 @@ public function providerMapper() 'first_name' => 'My first name', 'last_name' => 'My lastname.', 'email' => 'myemail@example.com', - 'avatar' => 'https://graph.facebook.com/my-facebook-id/picture?type=normal', + '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, From f42931d282c664d3ceb6668d923ddc51c2408537 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 15 Apr 2016 08:35:51 -0500 Subject: [PATCH 0434/1476] Fix PHP CS issue --- 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 48adafda4..319340c1f 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -68,7 +68,6 @@ public function socialLogin(array $data, array $options) $existingAccount->$user ]); } - } else { throw new AccountNotActiveException([ $existingAccount->provider, From f1402ef08c322c214d4c8e7790ebad195450e839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Fri, 15 Apr 2016 17:53:30 +0100 Subject: [PATCH 0435/1476] refs #fix-translation-string fixed transaltion string in pot file and spanish translation --- src/Locale/Users.pot | 2 +- src/Locale/es/Users.mo | Bin 9657 -> 9650 bytes src/Locale/es/Users.po | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 551c6cda2..3efabc9f5 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -243,7 +243,7 @@ msgid "Email not present" msgstr "" #: Model/Table/UsersTable.php:541 -msgid "{0}Your account validation link" +msgid "Your account validation link" msgstr "" #: Model/Table/UsersTable.php:561 diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo index 3cdcb7eb72785aedd845f1caf735aa4e74cb9fdf..421ce4ba1bf00309b9e9566221553c1181222840 100644 GIT binary patch delta 1173 zcmXZaT}YE*6u|MbmO8&?np0PrZ+=WGtdt`M1wkJd z@j~4w5qVPtjs}6$MM6YD7*at&kT)SkQ8xv3)&ID6Fn-VXIp=wwg|0_ksX1q|QbguF zA_s91*JE~>hzs*E2TO4?R-zAsc-A2@hH$cn0;{TgXpifn^C)cF8z#8%s5_IMaIfm4`;=THM)!VP#Gb^k27 zan75}EKDOozo0eWy9_G1K3pay)2ZTJy6N-EfF z;2zXC$CEU)!U@y^r%^Mzh^*vVG8x?^SI|i^q`(oi*?w9HQ0lLn7{#i zkL}n@biL8!B#kXJW-)|Mu?hd#HZrLP_o4-Cgmy(y{dV8;u-2qd_aACpHVAX#jRLiWGdT-pCAU#eb04;$^WW z7DWAoy{Li5uowk`o_#O2e zPi?012HZzKWcN>_CU^t&{mDZbTImaWVhIiUKhTM8%GbA0g8f*7emsu`rcf(g#-sQX zHPN>E%-iWiJ--{bV;|}#zKqsPPG|8H9sPA=kV)%zPS_E*`dqhjV~kDkPgs9lZyb_- zmAjH(Zid5SiD=xIGDjmrW;`+$HAW-R5$m33$Z9B?EetgI_Zt3|{ehMpyZ!0qGN-%h hP;}G`4;$lV%(S<~jLC!%P7FumruDXN+8VDv{2z0ji-!OJ delta 1147 zcmXZaUr5tY6u|MbrfpW!wsOv9`AauTWiXXiCYnT$DEJT=jL2MzU}TeQldy0_)I-r9 z_yrLJNsM|a3I~B8^-vTNBtlS7QPfLGWe^cQM17CH-(Y<1pWi*_o_p^^&t%Voyfe2$ zMDpb#Mfern_yb+|2dnWP2C>>NQipAL(jjsHm(l-FA+iDI(1*T&NEL>03vS1?cmg&4 zb!4gB3P^5oVv>Q?47|pr_zlbO7nY#2QluU|sPmg~6?WL}vd0ghZr}(O<0;gH=Wr!n zMqNLSrFf?@XMOmP0bMwSy3-ldioYX!kdiglhH6m9n^6Pxq9*9WCD@NCOrR!wfgSh` z2_-=m8@LHI&z>9&tuTWca13>4XHie!Dr$l}YDM=jjs?`C_i)Z044}rT!w^QX2K#V7 z9>;z72Df31?0TZP5gO}gjAJ`K#t8nkZDdjd$59g|QLid(_s<}o$|Y>WyV!|e(7<{g z5YI=tQP&M1&qT7wMssqJh91>~J@EwfB;KMv!cV9b&Ea}1Gpx#*u$%sF)DyXhTJZvs zTdMe2H`a!Fg>lrx!`Oo7v6%ewh{g&Ao}w3L(ZJ7Ghebr~!bV)YDr~1ehI%4XsIUJy zZp3-iIDuNL@&;_B-)Z+pQ8#!6_5I0x8d~YJJu!<0{h#PWFXii7D961R#wI+C1{Sav zU!iWWHf+6_2x{CIQj2t80}h~G@dY$*xVpSqI{MpbA;acxSJH9JjJvOCJUPlgV=lO7 z93zG4l8?*HXXX7BiDYspo6Z;`iNVytL?$(qHU?Aa!)DNb+tU(>wi?Y%TcfeYXteOs S?<_UvL!;*Vkk5>V\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -258,8 +258,8 @@ msgid "Email not present" msgstr "No se encuentra el email" #: Model/Table/UsersTable.php:541 -msgid "{0}Your account validation link" -msgstr "{0} Enlace para validar su cuenta" +msgid "Your account validation link" +msgstr "Enlace para validar su cuenta" #: Model/Table/UsersTable.php:561 msgid "{0}Your reset password link" From 259a850db4186ca2a22cf93c987b808d69d25d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 18 Apr 2016 15:24:26 +0100 Subject: [PATCH 0436/1476] update version to 3.2.0 --- .semver | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.semver b/.semver index 63e74f429..24895fae3 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 3 -:minor: 1 -:patch: 5 +:minor: 2 +:patch: 0 :special: '' From a80ed8bceb367d14b30e80189ef97e9aab7269c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 18 Apr 2016 15:26:08 +0100 Subject: [PATCH 0437/1476] update composer requirements --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index ce4106d22..0102ca750 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,6 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "php": ">=5.4.16", "cakephp/cakephp": "~3.2" }, "require-dev": { From e47038847ea7c1f9753fe14a69a5c0d54d54dc9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 18 Apr 2016 16:10:15 +0100 Subject: [PATCH 0438/1476] Update required versions --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 063256b15..54bd0a84a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ 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) -IMPORTANT: 3.1.x version is BETA status now, we are still improving and testing it. +IMPORTANT: 3.2.x version is BETA status now. Versions and branches --------------------- @@ -46,8 +46,8 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.1+ -* PHP 5.4.16+ Note CakePHP 3.2 requires PHP 5.5 so 5.4 compatibility would be dropped sooner than later... +* CakePHP 3.2+ +* PHP 5.5.9+ Documentation ------------- From 6b65be1628519da8565e8e38f96015466cdf9563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Tue, 19 Apr 2016 09:53:23 -0300 Subject: [PATCH 0439/1476] pt_BR translation files --- src/Locale/pt_BR/pt_BR.mo | Bin 0 -> 9535 bytes src/Locale/pt_BR/pt_BR.po | 537 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 537 insertions(+) create mode 100644 src/Locale/pt_BR/pt_BR.mo create mode 100644 src/Locale/pt_BR/pt_BR.po diff --git a/src/Locale/pt_BR/pt_BR.mo b/src/Locale/pt_BR/pt_BR.mo new file mode 100644 index 0000000000000000000000000000000000000000..e6fce0f98abef586b7228728a780b09638bc5cca GIT binary patch literal 9535 zcmbW6TZ~;-dB;~mE-(p&1eZ%2%Bo3Xo6L;Imn6^XbQnQfo5 z_sQP-%q3AoB#2OvD59uMA83VTq=X;1541%MytHc7i`w6R zt-bfTcnm6AUgx*>y0342-?zRse&f!Y{?zcSlI|kC{x)N-!Y|y)56{*KWB6yb@$+7| z8-4&j0e=TNI0HXfeSZV0=?~#=!Pnu3;J?Fn!S~%}%q?&Wd^?oyL3^?uY891vQW7pyvA`*ZB`#pFM z{6|Pv=A8&x`t?Dmb}SE|k7}4(^4o!Bg-p_}g&bouQwnpya&_HIL6h z>F29(7Je5>uKx`Yp}FxrVV>`Xs(&w>g!`e!=|IWh6)5?<2BmL*2Q{ysRJ@r*@@lq0 zL~QoKDR>+*lzA3vUY~)Q&nr;&qLMw43wNc52YVpgwnI`K<)1vkbmZ1D&E2-NKO_?PWM3B?=*C92UPzr z!He)^sQzw6h+6MGP~VS3t#1jczZ`136{z{X2xZ5A2DRQRQ2P4SD*u0=>c5>$)I8n` zCHD_O&G!*_20jTt2EPJl;q45rbv_E|!nEQ2@Dot_@vVyg4At)k=v3oxhSJYzD7hYl zR56dkJ#Y!`f>)sQ@kdbecnh+1=2iwpWsHT|&j+FO=jkfH1GPV&fExGHP=4X_kS@%( zq2~JroP+-f&%uXnDE|}463uH+<9;7Xul@;YKmH4DgSTNM+V}gR^l&fKJWfLkFT&06 z1$Yo%g__S#;coZ~sQPzPNq%k@)OtP&HQpzo*838C7=8_E{%=*h9i!*f+y}MKC!yqZ z5pIPmQ2YKxh-)%mfxid;8cNRZLWx+qc??>(1RsZg1U1heR{VRYeflZX{C*BK-%Whn z0QKx39rADCXLacPJnu(HlI3ZVWQU6|Pm#2KJ<9?9T+wSmlFvFz(%wBmib)qpCrOUf zAz6}iS@K^Y9V2P&h}P^Q>G?y_l79<7DOeqv6N48Zzle|1l+FWJGKS;M^pFNWNseFy} zdxE6r{UqtJ4x+uISaFg=^@kyacs{O zE;n<%#LjD4W-j;rGlS}7B|-*eW@FcJjQwHB4dF16C^v_eqO|So>8L1HvOKQ8d(AhZ zlf(}7^W4!-Q@|`DbJ%xTAxz{5;y3!KJ|!S?M8C~GxYeX6iz;(u3vyR5$VMeY`P!A< zNKH1Uj}X$R>#DY@KDq}-le{SHNmY3)kqFGO*c@B*yV^<8%Qh*zBD69V+A2G1HcpCO zCt7pyr0sQFR5+BYx8@rxW}Qy9lB8`L#W7PUEc@g)b;T{%g*;nfI$@C1>qNcT=2-pR z>)9gel#@29-fXwe1kuB&v>L9oJMVwME+l1Px9-|$7uHHwY(pi|cGF3thue{WSH+Es zDs`$9uBlULt8}Vd>p62=gL(-aM1qd;Th}LX4WRc3+aK8ch++H1{o0yU%?L$D)#RH}Jo2 z{f*bF{okmATX48fCvS$CnA3T-oW!`SGj0*jm$n>l9XXkSvYl~V*Ii&;SnC=2gxH=B z&RfbAR-*iYKdOB4h>Fy+iG3f})LlVgnku8(68atyMR3DslXfaw_o{L#}6T|4{p5lI`bawqo`V4ugm^I7vDRNVR#ki&DqUmR&16QV{7GF?c{3r zsT!>@&u-()1y|UO%GQ$aCF7K=_j;r9rYv}*k=3+a>hKCKp0<_pmHC>D+7Y^-@kgCg zJ;NZTrb%nuZgn6hX;J3=aJEi+SE2r-prfv$h?emyD#PMNi^7?Box;&}jei+$(-buI zQFbX;gsSE_6Xh_KGT>#}!7{2fr>^ACz1$oQ;Q;r)_Q+~4!6HrgszVs(bD6J?Kt|+D zWykLO0!?YGNsx=z+cXQ-GE~_+PT#|bAzWAf)3hx@Byui|7CKH2B!nwo{(hXiHgLZ; zIy)?9u4i==jc!I`jH7j$?2)Neb*j*=vMS$q6SajZ&F8NQ;(TN6Thk(RAf+KVsO334 zl!~rx;o}hXrkAE&74)Dd?qWN}=|w-8r-4 zfvK6@Q#&5AGka!t-9I(6Yi5RuQ)if;y4axJL$kYghkC~eu=`QlP0hQg+YI)wq7GE) zK#RfS)-;>_$i#_bCyorJwPSi_;t;hs;iu+_&t`3jRJIe7Ch1;9IXMQu@7(;+sXc>w zd6X6$t5Zi%rx<@TYxfXBPMq!#nRTX)W_h=mwQ0|P7W;PYCA3w^zOAW!#O~O(cjC#Z zM}x!8@>zR2bBg45Oz)X~a6;kX)Vv1Zv{va{8t3a@w(~Aobx9uChnE~-@d55dTr%DGe@a1)Ag&F?PW2V zi7yFTOL1u73kfHvnMZNtJM_N`NgA!ctfn+9y?=C73=vw^9r-5fudXI#X69(|4czY> z(VGlGJ!uNjGyP;JGwN%5l2$c9t$eDa3z9}ela@oVZ%5a0(n4uibHC`XU&#})n%mpF z>)IAawR<+Q&k&Qwc=b!_hr1gsMlWwC`jQ;s(NbiF-w)+U6ldnF3K+j1b(oFB?eA+* zUUM)3UD(JE7|I^Hy)m(Vk(pCLbYpvw6L>HCK{qb1OOJ$$ATA2MuI_61rW98vSv3L) z^{Q5WU+_i5;h8x}RdcF?dSLOo!<}`OqenNmpaDfm8P0Ygi51&(n=5g{42P4$=PpLe zSw2ZYFHyt7wfhN$cvfOkxBha*`p9KY_{%m@3-`F7DM`A#eno#oFlV{DS+p$bb(-C; zOS4IJyg`N7NtaMvmfCZjjPN$)7~SBWR~^l6JHn}ac{Oylwb(XX8q~5o7DaT9YUy6? zhZ(4oAIf_LY!}C}u@BK=f6W2LnkM{3OpC>TX3LtE+(pwhfk!BAWHBh4yta_7LQu6p z!UD#69Bnmj+E!8@nZac6FbDGd2UWE z}N3HM|cldi-H_s2D?QR|mR0 zhyDaQv?D=8ql;+E!ZTvUfg$VcmFzzb=pt-Y=f2$xD!0lyS3m8Tjv zG^P@`_+=f4*xOi1IIa=hMuo%87PAD!)Y;xtR#vF;Sk~vf=y&}svc5#hbq>Ojuy;Wx zjlVM1q0ZG<>o#a^@#6j1cTITr3wnp2+MfH5vT7Pv&_Dj)1(otl| zfx6h~uU-?6^f2ad0OJ4$7gzmtC)`{^kKx*yXZ_kwR?*-{NLQT|9Cg$(p&{Wj?uB4w z(6ovN&T{nos1aotIu{hvDGVT#Xk4`y?2s30ww8z|?*@Y#QTcJd)XUfZYBlL*hX0Ad d8aTtWoz;zYcp|kmjh;lRJzQ&}=~iCc{2#6!t?vK; literal 0 HcmV?d00001 diff --git a/src/Locale/pt_BR/pt_BR.po b/src/Locale/pt_BR/pt_BR.po new file mode 100644 index 000000000..a0ad95366 --- /dev/null +++ b/src/Locale/pt_BR/pt_BR.po @@ -0,0 +1,537 @@ +# LANGUAGE translation of CakePHP Application +# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) +# +msgid "" +msgstr "" +"Project-Id-Version: CakeDC Users\n" +"POT-Creation-Date: 2016-04-19 08:35-0300\n" +"PO-Revision-Date: 2016-04-19 09:44-0300\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=2; plural=(n > 1);\n" +"X-Generator: Poedit 1.8.7\n" +"Last-Translator: André Teixeira \n" +"Language: pt_BR\n" + +#: Auth/SimpleRbacAuthorize.php:132 +msgid "" +"Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" +"Arquivo de configuração ausente: \"config/{0}.php\". Usando permissões padrão" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Conta validada com êxito" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "A conta não pode ser validada" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Token e/ou conta social inválido(s)" + +#: Controller/SocialAccountsController.php:59 +msgid "SocialAccount already active" +msgstr "Conta social já ativa" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "A conta social não pode ser validada" + +#: Controller/SocialAccountsController.php:79 +msgid "Email sent successfully" +msgstr "Email enviado com sucesso" + +#: Controller/SocialAccountsController.php:81 +msgid "Email could not be sent" +msgstr "O email não pode ser enviado" + +#: Controller/SocialAccountsController.php:84 +msgid "Invalid account" +msgstr "Conta inválida" + +#: Controller/SocialAccountsController.php:86 +msgid "Social Account already active" +msgstr "Conta social já ativa" + +#: Controller/SocialAccountsController.php:88 +msgid "Email could not be resent" +msgstr "O email não pode ser reenviado" + +#: Controller/Component/RememberMeComponent.php:70 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Salt da aplicação inválido, o salt da aplicação deve ser de pelo menos 256 " +"bits (32 bytes)" + +#: Controller/Component/UsersAuthComponent.php:156 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Você não pode habilitar o fluxo de validação por email se use_email for false" + +#: Controller/Traits/LoginTrait.php:55 +msgid "" +"The social account is not active. Please check your email for instructions. " +"{0}" +msgstr "" +"A conta social não está ativa. Por favor verifique seu email para " +"instruções. {0}" + +#: Controller/Traits/LoginTrait.php:58 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Por favor indique seu email" + +#: Controller/Traits/LoginTrait.php:82 +msgid "Username or password is incorrect" +msgstr "Nome de usuário e/ou senha incorreto(s)" + +#: Controller/Traits/LoginTrait.php:93 +msgid "There was an error associating your social network account" +msgstr "Houve um erro associando sua conta social" + +#: Controller/Traits/LoginTrait.php:113 +msgid "You've successfully logged out" +msgstr "Você desconectou-se com êxito" + +#: Controller/Traits/PasswordManagementTrait.php:53 +msgid "Password has been changed successfully" +msgstr "Senha alterada com êxito" + +#: Controller/Traits/PasswordManagementTrait.php:56;63 +msgid "Password could not be changed" +msgstr "A senha não pode ser alterada" + +#: Controller/Traits/PasswordManagementTrait.php:59 +#: Controller/Traits/ProfileTrait.php:46 +msgid "User was not found" +msgstr "O usuário não foi encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:61 +msgid "The current password does not match" +msgstr "A senha atual não corresponde" + +#: Controller/Traits/PasswordManagementTrait.php:93 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Por favor, verifique seu email para continuar o processo de redefinição de " +"senha" + +#: Controller/Traits/PasswordManagementTrait.php:96 +msgid "The password token could not be generated. Please try again" +msgstr "O token de senha não pode ser gerado. Por favor, tente novamente" + +#: Controller/Traits/PasswordManagementTrait.php:101 +#: Controller/Traits/UserValidationTrait.php:94 +msgid "User {0} was not found" +msgstr "O usuário {0} não foi encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:103 +#: Controller/Traits/UserValidationTrait.php:90;98 +msgid "Token could not be reset" +msgstr "O token não pode ser redefinido" + +#: Controller/Traits/RegisterTrait.php:66 +msgid "The user could not be saved" +msgstr "O usuário não pode ser salvo" + +#: Controller/Traits/RegisterTrait.php:82 +msgid "You have registered successfully, please log in" +msgstr "Você registrou-se com sucesso, por favor, autentique-se" + +#: Controller/Traits/RegisterTrait.php:84 +msgid "Please validate your account before log in" +msgstr "Por favor, valide sua conta antes de autenticar" + +#: Controller/Traits/SimpleCrudTrait.php:75;103 +msgid "The {0} has been saved" +msgstr "O {0} foi salvo" + +#: Controller/Traits/SimpleCrudTrait.php:78;106 +msgid "The {0} could not be saved" +msgstr "O {0} não pode ser salvo" + +#: Controller/Traits/SimpleCrudTrait.php:125 +msgid "The {0} has been deleted" +msgstr "O {0} foi deletado" + +#: Controller/Traits/SimpleCrudTrait.php:127 +msgid "The {0} could not be deleted" +msgstr "O {0} não pode ser deletado" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "Conta de usuário validada com êxito" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "A conta de usuário não pode ser validada" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "Usuário já ativo" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "Token de redefinição de senha validado com êxito" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "O token de redefinição de senha não pode ser validado" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token and/or email" +msgstr "Token e/ou email inválido(s)" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Token expirado" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid validation type" +msgstr "Tipo de validação inválido" + +#: Controller/Traits/UserValidationTrait.php:88 +msgid "Token has been reset successfully. Please check your email." +msgstr "O token foi redefinido com êxito. Por favor, verifique seu email." + +#: Controller/Traits/UserValidationTrait.php:96 +msgid "User {0} is already active" +msgstr "O usuário {0} já está ativo" + +#: Model/Table/SocialAccountsTable.php:208 +msgid "{0}Your social account validation link" +msgstr "{0}Seu link de validação da conta social" + +#: Model/Table/SocialAccountsTable.php:235;263 +msgid "Account already validated" +msgstr "Conta já validada" + +#: Model/Table/SocialAccountsTable.php:238;266 +msgid "Account not found for the given token and email." +msgstr "Conta não encontrada com a combinação de token e email" + +#: Model/Table/UsersTable.php:84 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" +"Sua senha não corresponde com a confirmação. Por favor, tente novamente" + +#: Model/Table/UsersTable.php:178 +msgid "Username already exists" +msgstr "Nome de usuário em uso" + +#: Model/Table/UsersTable.php:184 +msgid "Email already exists" +msgstr "Email em uso" + +#: Model/Table/UsersTable.php:213 +msgid "The \"tos\" property is not present" +msgstr "A propriedade “tos” não está presente" + +#: Model/Table/UsersTable.php:271 +msgid "Token has already expired user with no token" +msgstr "Token expirado, usuário sem token" + +#: Model/Table/UsersTable.php:274 +msgid "User not found for the given token and email." +msgstr "Usuário não encontrado com a combinação de token e email" + +#: Model/Table/UsersTable.php:341 +msgid "User not found" +msgstr "Usuário não encontrado" + +#: Model/Table/UsersTable.php:368 +msgid "+ {0} secs" +msgstr "+ {0} segundos" + +#: Model/Table/UsersTable.php:420 +msgid "Unable to login user with reference {0}" +msgstr "Incapaz de autenticar usuário com a referência {0}" + +#: Model/Table/UsersTable.php:453 +msgid "Email not present" +msgstr "Email ausente" + +#: Model/Table/UsersTable.php:541 +msgid "Your account validation link" +msgstr "Seu link de validação da conta" + +#: Model/Table/UsersTable.php:561 +msgid "{0}Your reset password link" +msgstr "{0}Seu link de redefinição de senha" + +#: Model/Table/UsersTable.php:585 +msgid "The old password does not match" +msgstr "A senha antiga não confere" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Olá {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Redefina sua senha aqui" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Se o link não está exibido corretamente, por favor, copie o seguinte " +"endereço em seu navegador {0}" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Obrigado" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Ative sua autenticação social aqui" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Ative sua conta aqui" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Por favor, copie o endereço a seguir em seu navegador {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Por favor, copie o endereço a seguir em seu navegador para ativar sua " +"autenticação social {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:13 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:13;77 +msgid "Actions" +msgstr "Ações" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:21 +#: Template/Users/view.ctp:17 +msgid "List Users" +msgstr "Listar usuários" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:22 +#: Template/Users/view.ctp:19 +msgid "List Accounts" +msgstr "Listar contas" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:15 +msgid "Add User" +msgstr "Adicionar usuário" + +#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:13 +#: Template/Users/edit.ctp:42 Template/Users/register.ctp:26 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Enviar" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Por favor, indique a nova senha" + +#: Template/Users/change_password.ctp:7 +msgid "Current password" +msgstr "Senha atual" + +#: Template/Users/edit.ctp:16 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:99 +msgid "Delete" +msgstr "Deletar" + +#: Template/Users/edit.ctp:18 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:16;99 +msgid "Are you sure you want to delete # {0}?" +msgstr "Tem certeza que deseja deletar # {0}?" + +#: Template/Users/edit.ctp:28 Template/Users/view.ctp:15 +msgid "Edit User" +msgstr "Editar usuário" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Novo {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:95 +msgid "View" +msgstr "Visualizar" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Mudar senha" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:97 +msgid "Edit" +msgstr "Editar" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "anterior" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "próximo" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Por favor, indique seu nome de usuário e senha" + +#: Template/Users/login.ctp:26 +msgid "Remember me" +msgstr "Lembrar" + +#: Template/Users/login.ctp:49 +msgid "Login" +msgstr "Autenticar" + +#: Template/Users/profile.ctp:18 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:23 +msgid "Change Password" +msgstr "Mudar senha" + +#: Template/Users/profile.ctp:26 Template/Users/view.ctp:28;68 +msgid "Username" +msgstr "Nome de usuário" + +#: Template/Users/profile.ctp:28 Template/Users/view.ctp:30 +msgid "Email" +msgstr "Email" + +#: Template/Users/profile.ctp:33 +msgid "Social Accounts" +msgstr "Contas sociais" + +#: Template/Users/profile.ctp:37 Template/Users/view.ctp:70 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:67 +msgid "Provider" +msgstr "Provedor" + +#: Template/Users/profile.ctp:39 +msgid "Link" +msgstr "Link" + +#: Template/Users/register.ctp:23 +msgid "Accept TOS conditions?" +msgstr "Concordar com TOS?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Por favor, indique seu email para redefinir sua senha" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Reenviar email de validação" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email ou nome de usuário" + +#: Template/Users/view.ctp:16 +msgid "Delete User" +msgstr "Deletar usuário" + +#: Template/Users/view.ctp:18 +msgid "New User" +msgstr "Novo usuário" + +#: Template/Users/view.ctp:26;65 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:32 +msgid "First Name" +msgstr "Nome" + +#: Template/Users/view.ctp:34 +msgid "Last Name" +msgstr "Sobrenome" + +#: Template/Users/view.ctp:36;71 +msgid "Token" +msgstr "Token" + +#: Template/Users/view.ctp:38 +msgid "Api Token" +msgstr "Api Token" + +#: Template/Users/view.ctp:42;73 +msgid "Active" +msgstr "Ativo" + +#: Template/Users/view.ctp:46;72 +msgid "Token Expires" +msgstr "Expiração do token" + +#: Template/Users/view.ctp:48 +msgid "Activation Date" +msgstr "Data de ativação" + +#: Template/Users/view.ctp:50 +msgid "Tos Date" +msgstr "Data TOS" + +#: Template/Users/view.ctp:52;75 +msgid "Created" +msgstr "Criado" + +#: Template/Users/view.ctp:54;76 +msgid "Modified" +msgstr "Modificado" + +#: Template/Users/view.ctp:61 +msgid "Related Accounts" +msgstr "Contas relacionadas" + +#: Template/Users/view.ctp:66 +msgid "User Id" +msgstr "Id de usuário" + +#: Template/Users/view.ctp:69 +msgid "Reference" +msgstr "Referência" + +#: Template/Users/view.ctp:74 +msgid "Data" +msgstr "Dados" + +#: View/Helper/UserHelper.php:43 +msgid "Sign in with Facebook" +msgstr "Inscrever-se com Facebook" + +#: View/Helper/UserHelper.php:57 +msgid "Sign in with Twitter" +msgstr "Inscrever-se com Twitter" + +#: View/Helper/UserHelper.php:71 +msgid "Logout" +msgstr "Desconectar" + +#: View/Helper/UserHelper.php:109 +msgid "Welcome, {0}" +msgstr "Bem-vindo(a), {0}" From 876906e1c37e738c0b4e1194fdf5d0617d4b8669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Tue, 19 Apr 2016 09:54:17 -0300 Subject: [PATCH 0440/1476] Improving flash message --- 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 9d9e0a19b..bbde330f0 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -206,7 +206,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false) return $this->redirect($url); } else { if (!$socialLogin) { - $message = __d('Users', 'Username or password is incorrect'); + $message = __d('Users', 'Username and/or password is incorrect'); $this->Flash->error($message, 'default', [], 'auth'); } From d787d009d3c113253290e495d87c82fa62a81348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Tue, 19 Apr 2016 09:54:41 -0300 Subject: [PATCH 0441/1476] Adding missing "space" --- src/Controller/SocialAccountsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 5606f204b..c83b462f1 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -56,7 +56,7 @@ public function validateAccount($provider, $reference, $token) } catch (RecordNotFoundException $exception) { $this->Flash->error(__d('Users', 'Invalid token and/or social account')); } catch (AccountAlreadyActiveException $exception) { - $this->Flash->error(__d('Users', 'SocialAccount already active')); + $this->Flash->error(__d('Users', 'Social Account already active')); } catch (Exception $exception) { $this->Flash->error(__d('Users', 'Social Account could not be validated')); } From b8a20b0ee7c59194988ac585357bd435b4a011c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Tue, 19 Apr 2016 10:16:42 -0300 Subject: [PATCH 0442/1476] Rollback --- 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 bbde330f0..9d9e0a19b 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -206,7 +206,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false) return $this->redirect($url); } else { if (!$socialLogin) { - $message = __d('Users', 'Username and/or password is incorrect'); + $message = __d('Users', 'Username or password is incorrect'); $this->Flash->error($message, 'default', [], 'auth'); } From 6cd3ae6359595b514ef45f7a50ac5df19b70de33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Tue, 19 Apr 2016 10:38:21 -0300 Subject: [PATCH 0443/1476] Updating default plugin .pot file --- src/Locale/Users.pot | 398 ++++++++++++++++++++++++++++++++----------- 1 file changed, 298 insertions(+), 100 deletions(-) diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 3efabc9f5..2efe2c07e 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -1,11 +1,11 @@ # LANGUAGE translation of CakePHP Application -# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) +# Copyright 2010 - 2016, Cake Development Corporation (http://cakedc.com) # #, fuzzy msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2015-08-04 10:52+0000\n" +"POT-Creation-Date: 2016-04-19 13:13+0000\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: CakeDC \n" "Language-Team: CakeDC \n" @@ -14,10 +14,34 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: Auth/SimpleRbacAuthorize.php:132 +#: Auth/ApiKeyAuthenticate.php:55 +msgid "Type {0} is not valid" +msgstr "" + +#: Auth/ApiKeyAuthenticate.php:59 +msgid "Type {0} has no associated callable" +msgstr "" + +#: Auth/ApiKeyAuthenticate.php:68 +msgid "SSL is required for ApiKey Authentication" +msgstr "" + +#: Auth/SimpleRbacAuthorize.php:141 msgid "Missing configuration file: \"config/{0}.php\". Using default permissions" msgstr "" +#: Auth/SocialAuthenticate.php:410 +msgid "Provider cannot be empty" +msgstr "" + +#: Auth/Rules/AbstractRule.php:77 +msgid "Table alias is empty, please define a table alias, we could not extract a default table from the request" +msgstr "" + +#: Auth/Rules/Owner.php:67;70 +msgid "Missing column {0} in table {1} while checking ownership permissions for user {2}" +msgstr "" + #: Controller/SocialAccountsController.php:52 msgid "Account validated successfully" msgstr "" @@ -30,8 +54,8 @@ msgstr "" msgid "Invalid token and/or social account" msgstr "" -#: Controller/SocialAccountsController.php:59 -msgid "SocialAccount already active" +#: Controller/SocialAccountsController.php:59;86 +msgid "Social Account already active" msgstr "" #: Controller/SocialAccountsController.php:61 @@ -50,208 +74,371 @@ msgstr "" msgid "Invalid account" msgstr "" -#: Controller/SocialAccountsController.php:86 -msgid "Social Account already active" -msgstr "" - #: Controller/SocialAccountsController.php:88 msgid "Email could not be resent" msgstr "" -#: Controller/Component/RememberMeComponent.php:70 +#: Controller/Component/RememberMeComponent.php:69 msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" msgstr "" -#: Controller/Component/UsersAuthComponent.php:156 +#: Controller/Component/UsersAuthComponent.php:157 msgid "You can't enable email validation workflow if use_email is false" msgstr "" -#: Controller/Traits/LoginTrait.php:55 -msgid "The social account is not active. Please check your email for instructions. {0}" +#: Controller/Traits/LoginTrait.php:95 +msgid "Issues trying to log in with your social account" msgstr "" -#: Controller/Traits/LoginTrait.php:58 +#: Controller/Traits/LoginTrait.php:100 #: Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "" -#: Controller/Traits/LoginTrait.php:82 -msgid "Username or password is incorrect" +#: Controller/Traits/LoginTrait.php:106 +msgid "Your user has not been validated yet. Please check your inbox for instructions" msgstr "" -#: Controller/Traits/LoginTrait.php:93 -msgid "There was an error associating your social network account" +#: Controller/Traits/LoginTrait.php:108 +msgid "Your social account has not been validated yet. Please check your inbox for instructions" msgstr "" -#: Controller/Traits/LoginTrait.php:113 -msgid "You've successfully logged out" +#: Controller/Traits/LoginTrait.php:157 +#: Controller/Traits/RegisterTrait.php:73 +msgid "Invalid reCaptcha" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:53 -msgid "Password has been changed successfully" +#: Controller/Traits/LoginTrait.php:165 +msgid "You are already logged in" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:56;63 +#: Controller/Traits/LoginTrait.php:209 +msgid "Username or password is incorrect" +msgstr "" + +#: Controller/Traits/LoginTrait.php:230 +msgid "You've successfully logged out" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:53;60;68 msgid "Password could not be changed" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:59 -#: Controller/Traits/ProfileTrait.php:46 +#: Controller/Traits/PasswordManagementTrait.php:57 +msgid "Password has been changed successfully" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:64 +#: Controller/Traits/ProfileTrait.php:49 msgid "User was not found" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:61 +#: Controller/Traits/PasswordManagementTrait.php:66 msgid "The current password does not match" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:93 +#: Controller/Traits/PasswordManagementTrait.php:108 msgid "Please check your email to continue with password reset process" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:96 +#: Controller/Traits/PasswordManagementTrait.php:111 +#: Shell/UsersShell.php:266 msgid "The password token could not be generated. Please try again" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:101 -#: Controller/Traits/UserValidationTrait.php:94 +#: Controller/Traits/PasswordManagementTrait.php:116 +#: Controller/Traits/UserValidationTrait.php:98 msgid "User {0} was not found" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:103 -#: Controller/Traits/UserValidationTrait.php:90;98 +#: Controller/Traits/PasswordManagementTrait.php:118 +msgid "The user is not active" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:120 +#: Controller/Traits/UserValidationTrait.php:94;102 msgid "Token could not be reset" msgstr "" -#: Controller/Traits/RegisterTrait.php:66 +#: Controller/Traits/ProfileTrait.php:52 +msgid "Not authorized, please login first" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:79 msgid "The user could not be saved" msgstr "" -#: Controller/Traits/RegisterTrait.php:82 +#: Controller/Traits/RegisterTrait.php:111 msgid "You have registered successfully, please log in" msgstr "" -#: Controller/Traits/RegisterTrait.php:84 +#: Controller/Traits/RegisterTrait.php:113 msgid "Please validate your account before log in" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:75;103 +#: Controller/Traits/SimpleCrudTrait.php:76;105 msgid "The {0} has been saved" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:78;106 +#: Controller/Traits/SimpleCrudTrait.php:79;108 msgid "The {0} could not be saved" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:125 +#: Controller/Traits/SimpleCrudTrait.php:128 msgid "The {0} has been deleted" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:127 +#: Controller/Traits/SimpleCrudTrait.php:130 msgid "The {0} could not be deleted" msgstr "" -#: Controller/Traits/UserValidationTrait.php:43 +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:42 msgid "User account validated successfully" msgstr "" -#: Controller/Traits/UserValidationTrait.php:45 +#: Controller/Traits/UserValidationTrait.php:44 msgid "User account could not be validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:48 +#: Controller/Traits/UserValidationTrait.php:47 msgid "User already active" msgstr "" -#: Controller/Traits/UserValidationTrait.php:54 +#: Controller/Traits/UserValidationTrait.php:53 msgid "Reset password token was validated successfully" msgstr "" -#: Controller/Traits/UserValidationTrait.php:58 +#: Controller/Traits/UserValidationTrait.php:57 msgid "Reset password token could not be validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:65 -msgid "Invalid token and/or email" +#: Controller/Traits/UserValidationTrait.php:61 +msgid "Invalid validation type" msgstr "" -#: Controller/Traits/UserValidationTrait.php:67 -msgid "Token already expired" +#: Controller/Traits/UserValidationTrait.php:64 +msgid "Invalid token or user account already validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid validation type" +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Token already expired" msgstr "" -#: Controller/Traits/UserValidationTrait.php:88 +#: Controller/Traits/UserValidationTrait.php:92 msgid "Token has been reset successfully. Please check your email." msgstr "" -#: Controller/Traits/UserValidationTrait.php:96 +#: Controller/Traits/UserValidationTrait.php:100 msgid "User {0} is already active" msgstr "" -#: Model/Table/SocialAccountsTable.php:208 +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "" + +#: Mailer/UsersMailer.php:78 msgid "{0}Your social account validation link" msgstr "" -#: Model/Table/SocialAccountsTable.php:235;263 +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:67;115 +msgid "User not found" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:110 +msgid "User account already validated" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:120 +msgid "The old password does not match" +msgstr "" + +#: Model/Behavior/RegisterBehavior.php:88 +msgid "User not found for the given token and email." +msgstr "" + +#: Model/Behavior/RegisterBehavior.php:91 +msgid "Token has already expired user with no token" +msgstr "" + +#: Model/Behavior/SocialAccountBehavior.php:101;128 msgid "Account already validated" msgstr "" -#: Model/Table/SocialAccountsTable.php:238;266 +#: Model/Behavior/SocialAccountBehavior.php:104;131 msgid "Account not found for the given token and email." msgstr "" -#: Model/Table/UsersTable.php:84 +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "" + +#: Model/Behavior/SocialBehavior.php:97 +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:178 +#: Model/Table/UsersTable.php:159 msgid "Username already exists" msgstr "" -#: Model/Table/UsersTable.php:184 +#: Model/Table/UsersTable.php:165 msgid "Email already exists" msgstr "" -#: Model/Table/UsersTable.php:213 -msgid "The \"tos\" property is not present" +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" msgstr "" -#: Model/Table/UsersTable.php:271 -msgid "Token has already expired user with no token" +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" msgstr "" -#: Model/Table/UsersTable.php:274 -msgid "User not found for the given token and email." +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" msgstr "" -#: Model/Table/UsersTable.php:341 -msgid "User not found" +#: Shell/UsersShell.php:57 +msgid "Add a new user" msgstr "" -#: Model/Table/UsersTable.php:368 -msgid "+ {0} secs" +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" msgstr "" -#: Model/Table/UsersTable.php:420 -msgid "Unable to login user with reference {0}" +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" msgstr "" -#: Model/Table/UsersTable.php:453 -msgid "Email not present" +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" msgstr "" -#: Model/Table/UsersTable.php:541 -msgid "Your account validation link" +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" msgstr "" -#: Model/Table/UsersTable.php:561 -msgid "{0}Your reset password link" +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" msgstr "" -#: Model/Table/UsersTable.php:585 -msgid "The old password does not match" +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "" + +#: Shell/UsersShell.php:97 +msgid "User added:" +msgstr "" + +#: Shell/UsersShell.php:98;126 +msgid "Id: {0}" +msgstr "" + +#: Shell/UsersShell.php:99;127 +msgid "Username: {0}" +msgstr "" + +#: Shell/UsersShell.php:100;128 +msgid "Email: {0}" +msgstr "" + +#: Shell/UsersShell.php:101;129 +msgid "Password: {0}" +msgstr "" + +#: Shell/UsersShell.php:125 +msgid "Superuser added:" +msgstr "" + +#: Shell/UsersShell.php:131 +msgid "Superuser could not be added:" +msgstr "" + +#: Shell/UsersShell.php:134 +msgid "Field: {0} Error: {1}" +msgstr "" + +#: Shell/UsersShell.php:152;178 +msgid "Please enter a password." +msgstr "" + +#: Shell/UsersShell.php:156 +msgid "Password changed for all users" +msgstr "" + +#: Shell/UsersShell.php:157;185 +msgid "New password: {0}" +msgstr "" + +#: Shell/UsersShell.php:175;203;281;321 +msgid "Please enter a username." +msgstr "" + +#: Shell/UsersShell.php:184 +msgid "Password changed for user: {0}" +msgstr "" + +#: Shell/UsersShell.php:206 +msgid "Please enter a role." +msgstr "" + +#: Shell/UsersShell.php:212 +msgid "Role changed for user: {0}" +msgstr "" + +#: Shell/UsersShell.php:213 +msgid "New role: {0}" +msgstr "" + +#: Shell/UsersShell.php:228 +msgid "User was activated: {0}" +msgstr "" + +#: Shell/UsersShell.php:243 +msgid "User was de-activated: {0}" +msgstr "" + +#: Shell/UsersShell.php:255 +msgid "Please enter a username or email." +msgstr "" + +#: Shell/UsersShell.php:263 +msgid "Please ask the user to check the email to continue with password reset process" +msgstr "" + +#: Shell/UsersShell.php:300 +msgid "The user was not found." +msgstr "" + +#: Shell/UsersShell.php:329 +msgid "The user {0} was not deleted. Please try again" +msgstr "" + +#: Shell/UsersShell.php:331 +msgid "The user {0} was deleted successfully" msgstr "" #: Template/Email/html/reset_password.ctp:21 @@ -269,8 +456,7 @@ 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}" +msgid "If the link is not correcly displayed, please copy the following address in your web browser {0}" msgstr "" #: Template/Email/html/reset_password.ctp:30 @@ -290,6 +476,10 @@ msgstr "" msgid "Activate your account here" msgstr "" +#: Template/Email/html/validation.ctp:27 +msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" +msgstr "" + #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" @@ -319,14 +509,14 @@ msgid "List Accounts" msgstr "" #: Template/Users/add.ctp:22 -#: Template/Users/register.ctp:15 +#: Template/Users/register.ctp:16 msgid "Add User" msgstr "" #: Template/Users/add.ctp:32 -#: Template/Users/change_password.ctp:13 +#: Template/Users/change_password.ctp:17 #: Template/Users/edit.ctp:42 -#: Template/Users/register.ctp:26 +#: Template/Users/register.ctp:32 #: Template/Users/request_reset_password.ctp:8 #: Template/Users/resend_token_validation.ctp:20 #: Template/Users/social_email.ctp:19 @@ -337,7 +527,7 @@ msgstr "" msgid "Please enter the new password" msgstr "" -#: Template/Users/change_password.ctp:7 +#: Template/Users/change_password.ctp:10 msgid "Current password" msgstr "" @@ -388,51 +578,56 @@ msgstr "" msgid "Please enter your username and password" msgstr "" -#: Template/Users/login.ctp:26 +#: Template/Users/login.ctp:29 msgid "Remember me" msgstr "" -#: Template/Users/login.ctp:49 +#: Template/Users/login.ctp:48 msgid "Login" msgstr "" #: Template/Users/profile.ctp:18 +#: View/Helper/UserHelper.php:51 msgid "{0} {1}" msgstr "" -#: Template/Users/profile.ctp:23 +#: Template/Users/profile.ctp:24 msgid "Change Password" msgstr "" -#: Template/Users/profile.ctp:26 +#: Template/Users/profile.ctp:27 #: Template/Users/view.ctp:28;68 msgid "Username" msgstr "" -#: Template/Users/profile.ctp:28 +#: Template/Users/profile.ctp:29 #: Template/Users/view.ctp:30 msgid "Email" msgstr "" -#: Template/Users/profile.ctp:33 +#: Template/Users/profile.ctp:34 msgid "Social Accounts" msgstr "" -#: Template/Users/profile.ctp:37 +#: Template/Users/profile.ctp:38 #: Template/Users/view.ctp:70 msgid "Avatar" msgstr "" -#: Template/Users/profile.ctp:38 +#: Template/Users/profile.ctp:39 #: Template/Users/view.ctp:67 msgid "Provider" msgstr "" -#: Template/Users/profile.ctp:39 +#: Template/Users/profile.ctp:40 msgid "Link" msgstr "" -#: Template/Users/register.ctp:23 +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "" + +#: Template/Users/register.ctp:25 msgid "Accept TOS conditions?" msgstr "" @@ -516,19 +711,22 @@ msgstr "" msgid "Data" msgstr "" -#: View/Helper/UserHelper.php:43 -msgid "Sign in with Facebook" +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" msgstr "" -#: View/Helper/UserHelper.php:57 -msgid "Sign in with Twitter" +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " msgstr "" -#: View/Helper/UserHelper.php:71 +#: View/Helper/UserHelper.php:90 msgid "Logout" msgstr "" -#: View/Helper/UserHelper.php:109 +#: View/Helper/UserHelper.php:139 msgid "Welcome, {0}" msgstr "" +#: View/Helper/UserHelper.php:161 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" From 3e6a968e9b1a509d7840dbc33c974da41b536927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Tue, 19 Apr 2016 10:38:43 -0300 Subject: [PATCH 0444/1476] New pt_BR translations after plugin .pot file update --- src/Locale/pt_BR/pt_BR.mo | Bin 9535 -> 14231 bytes src/Locale/pt_BR/pt_BR.po | 497 ++++++++++++++++++++++++++++---------- 2 files changed, 371 insertions(+), 126 deletions(-) diff --git a/src/Locale/pt_BR/pt_BR.mo b/src/Locale/pt_BR/pt_BR.mo index e6fce0f98abef586b7228728a780b09638bc5cca..12049d19a9a0cf269b75d83cd67fdcd9665fb602 100644 GIT binary patch literal 14231 zcmb`N50G8eUB^!m3Zy{Fe-LRe0ZIbdO*RxrHiTr!A4v1J$tF;wz}@%m?%w3RcOUoO zw|{~NXwilOih>rX*nmKx;!LM9YOOlDRmZkdN1cM5>6EFhZJlv+nAUcxMg4rwIrqMI z-|n_W`zGgo-@WJG@BIFs-{vc49RHZ%^8)Q>X!R3}`5O4UOZeim_B3P80oQ@&gL}bu zfQP`<;8FklDey#|zXWRBSHYhK{|kI4c+OH|_-C%>>#g86@FZ{-I0zmD8EWnaPX-?a z-vvGeYW!b<{4<~T_+{`Cp8plpzNf$482*{_`8poF9J~Nr1#12d@NM8e@LcdVP~)aR z?ROW*(artfS>T62o#UgR#(xSt9sGNbU-$373yM{z(Rns_KB(tap!OXGj{`?Q(YXb@ z1KbIQ;7g#+we$@7z;}YYGIj7`a0*-nJ^_l3&w{JLe*#7KnP<9lTnOrX%fM5?K~QvD z3+h}qfTCv?_+D@nya9X;lpOxe9<00@uo{xg>0-pyp z?+f5=@XO#v@Cul76L=V02hM@#fp35eG3TIU7lBuRdcO#NBf=$YTPB@BzQe2`aTXyzAuBak1v7i!S938 z>#NvI`g;q=5zQ0`Y33nN`#lSaAD;t7=YN9yGv_i163iM<^LBue{}?E_OoFi7Oo1Br zAQ*tpf-Awl0@s7z2F2G^EG|0Nf|_?LDE_3N^x_Fn`tUTUaewadpF#2aWDbu?nX^Ih zX9XxbUk46=H-b9X6e#*122pMEf`9%rsB^puT0I3d{(GSGWhtBMTtlFqH-fV35IhAO z2Vtqnz)j#opyd4pkbmaC`GQn)AwrP-4TCp>_khyhe+0GPWr361Mo{Z-2Sv|ra0I*w z6h9sZVVyY!${zj%yyq>(d>z!e>KKu58r1#|fa|~)K+*X%Q0u(m`%i$WvX4tZ>BTxw z^KSzs*E{|5G^lkR0L918fYP(qz)Qh@0i~BqSwwO<$Kx_k@*D)!f6%{wKdAL%P<%~5 z(e(%@y?z{oHReT7^F9kozJCX5-d92K|C^x3eFsEj<}8Sjyw-p^?PYW^oc(eq~>{}w!n=hwhB z;I}~8+XXli@%Khh`fvyoUyg#>?-?)#e-GRTo`=)B13U~4gP#X=o)d9q(&J0P)!_9Y zq?rs9|DObOU(W{`&`|se@;ORIq+4qg0bmEQkr2Z~FcvFh%_A6#xDP)PCOpWoKr{ z$?;6^1RgI2rJpOn)4=P%0Ne#43ey6$@8jV0;HN>+`9B~gXih@-=YcE1cY|9&t#bs_ zIgWx_=VPGw@eiQ(`#yLEcp6N8J9rVOb=H8Qe+MZ4{6YWzDNyVEfyY-s(e)po=AXyr zlE(@VRWu`@<{tvJ@4es>@Hy~w@Drf;HwV5Kd<~S`hfpT*^AH$-4}k9hKMqFVcfk<6 z6=6%xe+r%qei0O3Ui0`Za3{~NgVL|-u5om11I3R9_!dx~TOC;al&${)O*BK2{oKd5 zbmc+XbF?RDn`phCbNs_JC_eoL?G)N}+ATEco<5laa}W3=?OFePuSfA>FYR||H_%WU z^Xs$&G<_bRiQlq?kJ9wfdBjUhz~)2^P`nzY6`$YY$8Q%8;KMXnV13>}a05;Hs?UdL zchVlC-9|f1JAw8-8fIeS0bmk+@sZs0IYPq?*pGb0qqGif8}0qH57MNwAD~I5zev;P zItS({kFuAa^1mfJL~d@RJ>%c~vd0#XH3HCQtF@21~=1WPqOV@G<~GMzeJ1mz(;nphc-f+r2Ps_pCz=PrJbt>K94&v zId~UMdVZAFrfsDuUdRW^&Ue!EnV?Cp^*KZvqixXxpEGG6v%k7u5ApME+IreP|9aMA z4ctw;!#{r*#C*-q)9U_R0B-cZFYDDC#lCY>}0J>ip48ufK$Ni7Z=K_i)nTS0F>M-H~I zwi^%B>%jrLG(W9J83(~qRh^7!yRGmI2hG&%}5#r zP{%6%$8-p9^CYN8jfgW{9Ne|~ZkWyi!_;h^3|kXXus6)I=_IWe&+Wcv@ia{uk)>rG zS2iOziEDEwO(QldXLHcdY>7hnx-dVtSeh7ONwa+LzvpeT6@4-Ka_rhFi5mM|Do!*L zXL;sdR&*wfG6-9!r{}%Ys9hO}Hi^5fuo?Ne8eUZzOTw_2YPQ8uqi%l&Thla2`8lMw zX_g1OwZ@IH9k;!1w!3j=`?%HDM%+3a#F{uM0j`K;!=Dv-0>M&Ns zJCUT(m!?SoJJHF&ySU6fNzeHy-=OcLlbc;}mT9kA(&#i>nyCHqa15J6iGu0Lm|wNY zsCHPxlIa#pOvdd1SJBj5JgGHK>1%M;n!9^eY>megoivnh3&vSyI9P`J<>e~28Ej9s zmknZ5TDBgIhn)si&|TE*O6vGOta~@E$y%s>6ejKzUvK0dx=%X!ZtN-SdYBgi63G@8;*mR%Q;LEgf&7QuNTRS}_IkUO+??Y4-{!wLyN9~cMX&JHTh`tWVLZPu>b9Fa+M!Vi( z?a!eBvv z-L5fj>@=_aGzfcthE2IZ`Cz2v%fReBrn;o zl+8K|;&D_T?s-vJ$oGy~zmEK1IJ8@}D1$ssIBpRmz4y1HRtD3G{zVoX&EzR$Gp6v^ zE>euANz-~Maf6J}jN(?Uj&kCIaWrjiiW;?~8LhN}eIFOvkQiHRjT$Ih zWUP8n?aT5Ya!TS7EH5zyNA9(U$GI&9@wim`b~gY5$HPVz*##!?FnFg4QgtG8)klnwRx^{y_bu!(uvEE!qaRo9c+9ehSt=(w{e z-K_}uU2UC>@^XP5!;D*F$&BTG+{*H_{e=Rqbw*uOLCsjYCU1mIl z^ZIF8#4*E-dn!&kndwFcZ~N|&LK&leQ4vqdS59FD%Q=IGqgkWnb>jx@S)7|H`E5l| z^z|{YUs5D*hoV|Ou)RKT5Y0r7hAXPNWbdBQ0bBQ=Yd{5^;b6_`p{oa0zk6V4T`;tI zc<7pe)mN@w&A@?uoKQsj zkYRMoNoXTc7?Pd#yyRN!5>vN-p^O@&nwbb9YEL=x>^zpN$2F8loBADlUp0xSQ%Tvy z)@2c~9ilztl*)mSD?U!;!*a2{nTF&!u*rcLjhaC%O7rMQ7?4jgJ&O*BII4A!QLQBI z>PTALOsLh&|IPJFDLe!$#<9(59M%)FUkh;fPS}7I^(3P>m|0#d&g?CYAXi50<&W=J zbWfEN!_-z4d#7#fsV%~SPL`NGPBHp4Eydk(dx7kQ`-@(?Ahi%x4~t47ajQjqvn(m( z>Bjk4R_h2e)DaR_eRT12bJ%Pr_NT2f@(Y)@o2AU22F4-B+EZZM&t*H1=X0d1j68*n z=mv?#&ctIeXajZ5#T@d8cZB8fa4Jbx($S8!0HX`$cAfH;|I3 zFv(h$dRLh2u>m|p;i6JmAfpI}*ve)Klr6hJq0gv*uBuclY^4$^Q84|qXrfd%M=$#)7eu9>!Z` z=!#3GhN{I4M~qa15+`zm#jc`h z$S6vCaTI$~m5h66elr{NO^x|urViU_dd;GI*=2jT7q+5ii*@#g1Gx*!*&lbpg5$`J zN`>!Ig(q_)m-6ZMt(@QK^r4VD;RB}56MFBG^Uku6l7x6~-glEEe807vQeLi#8WCQI zu&5w~Ao$v!?j4B}d^D-(+>0#=3Z#X$Ea0B{MpIt(iJ@wSjnJl4vc{d%S5q9^J{Qw{ zfm-gU$1g*LOB8usaHDDkecSmIvWORpPb&uE{7Ng{=j}{h-f~;iIzS@P@st~TrTK7t43%7+MQ2eO6DV1Qkso0`ps(ixPUlBkYgW3p=iv&TJNHwx| z`=C$Hy)h~xT8k}{df(A6Y(@Mcx5wM6f)w*NU*%zGQFiqSdFYeedNPdQY(`uV-Y2H& zNc1v956iGd(qwNP=vgHQcz(fbKLhF5K)90SKS_TuK(pWhatZ-tt>9AYQrfON6|31P09VohS(-Zy{q}Zwdj?km1ZjCA*ClrGc ziUVCYrQCwQvfwOi9>@yi?YfU!g|0GW5q^?zO(`j^b~`>w%JciilbEzm5yukNI~Qk5 zu_8wKb?>n0YH1=pTWFX)WbfD?al&#=d3h{0fq?m)#j*M+@`JUp8{+Oywsc!uF{`Ci zSD3XI2j@_#;wgNK)d4rwyBWXCJc%5^@7Y~ZGz!KxUn#kt5h3k15bCxQsohO_oKA&d z3xx4OcR}SwZfxFKGAU;d?7N9^7L{Ghv^oYSQRL6tTeYwq9+5}udi$=v$P3CUN~iAc zH5y+W%R7*sHw#w>dIwb5>=n7F6!Z=(x_Ve+4iq>2UUyNxEIe4!9Y=w|DtkG`Zr@e& z?#R9lyX%iCQk1J|69n$^z49%$^-4#Nso3450zIVkbW5f>%_8<%io93>0P ziSU$oli`>O);0?sZ**qn-PIJ?T-MB0pj%;9b=#Gg-HNWhoF*OJ z7^L6+ZeIy0m3xIJ1wrB$xqfx0mT7*+-R;p_r?B2j__7o6u*e+jd3u6JsbO5T(x!7# z72EF*2U<$*nFZb7Q7H{#>ZK|b22)w2$AM^i7|+<+7Li6*ASXOmgNAUG)%J4(>6B)+ z;11QO^`>`NxGYUodcaqu+v(gVXX0jJ_h52LM0jn5hau;DFo7}A5w^{R7qPUUlLW7C`pi-woxEoTD9u^|Ll$_Rge7c z@6337F7J6~eLB3>K6tYz?|DNzPRt^1+-J;rJUf;TT1|m5{FqukO0fl}<7S+V9ya1r z@%5XiKm7=2;0>IEf5FK(ZGtgluo}l1Gid7RjOWG@oR4ks1Kp@U2xA9P13!mT@HFP( z1=N7AAwTA7eE&LX+;=e_Kg1IJ7`1^fa2oTQyotsXa${C(Jx=3#HL_^44>dsoN8?d+ zu@|+#4{;rSg4*%iNyb#+D%3a$)IuIdEqDm|G0*T(!2IS69j)*@YN8+E2E2r%$ow^S z)cv^(6ks{`i%=PB#8tQ#_u^?>hF_tct7Vm1$Of#(Ls*U9!NCXU{Dh7s`V6(wFHkA| z6Otv9&xHmk#06N34Y(W2a0sX33#b%dMNRxZ&coj$LzzjWSv6LU+UW8^@~;WoxKV+d zQK{=i70oGJftPU`-o}~OT9g}TKPu(@sD+$D73oD>j_;r{`wt|EW^{3Gp;J)L&o3tb zb#zv7LlY%YnYe&T(PdQ8{RXwL&tmi0CS6mDWZAUhLfnGPWxj!0*t4hwT|kX{4VB6F zP#gYqkdBICH2I@`%vfBFC74Yy>NOierS2tEvAu)(yD^NefhV9AT7t^ZEL3eQ#lcaW zIclMwFuN9bCw6cYdC&wUsG?~`y&k=&0l$T;(L9H9@g>v%@1s(CBfh?cI?6wz&ivn~ zGoHs_s-e2rrKtPsa@T`qGaU`I7d7EQq+X1Ndaxf=JWrsWdlr=`i>i?qQN?y0b;dW5 zAM<7G7|ubNa!{F?hkA|c(bN0iL`M^x#zXiDYQVANQ9GW8x^749up2dCgqm;wwcsJt z_r>>7J3fah+SlUy|3p1Mj&syPN^v&xn>lo};)iet?!(9MRa}k}nO!^GfQ(^|;9`6d zRU71t)P>CwidQ@iDAdi@KT#DT|*i7df9aZJWsD<1{j?au`R_ew$s54!H zDx!n&{Uqv$o?P)G82 zti=huD?0ndsA61!TF7>E@DNtwNnC^HQ49JUTktE?^K*GfUwF-^4Lw>pn49n^ZfM7+ zaV1_t?cjFoL|%TnW&!G~J5U)rgf%#TI{O!q?7#@)u!}fC+(+n0?rlolQDO^`AeIqoN_i*IMyw%J?Rrzx@(304 z!^B1+*O)(|cZ|po^ND?g+Cw?A|5{ZGYJ4@^ZJdmGkWis=I;NLsB-Hd8H)MOp96+BK zA787$)m9Vrx&7z9)2q3m*JCuHc8FL(gu0+nOLyBMdQ0M~;@CM@NVvpf#7NT{Hqz?o z93(2^8yoaRp#sx;+DGWCRbM))@&ZDwj8KvG=z^wqeychQoW~oVa8h0(WtZOnhRvJ2 z(>_0WpDmg)XHwEjduE*{oZU8>a@IB!mfF_~e^!(Zd%VDLgRX`!a=c#GPufh;!rA?9 z((iK9ei%6E6Mdf9;-=D0hucff4|?pv;wF2kc$Xb2X}5J#Z`xGp)$u#L!(QYC3D0&; zJJWh1%tTI~n@SCYQJ2%rZ_G~rNZ|N^GvKGYorm3o*BORA|9f{Aze{_OeXDFwewgsx zq`g*F)|Bb&_0wiow;S|0j7!gRD$`-A(&>xBJ}*k2aQu`LglVq5lozD!)#*cEF$cd*7yfi!S8JXU?Gu!R2W+rVktJQumt8Gj&^4zWy zwyC_szEM7C-Pxt~)a*Nx0`GX*u#0{_%%toY=iB*>OP4nsFj{ob`VHUQ z-Nq8`8Tg*Zvg1=n)WBi4pHG(TANG%BJa#jZv_3a-<8m5)W%x}mE~oL0mG+m7`mq?9\n" "Language-Team: CakeDC \n" +"Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 1.8.7\n" -"Last-Translator: André Teixeira \n" -"Language: pt_BR\n" -#: Auth/SimpleRbacAuthorize.php:132 +#: Auth/ApiKeyAuthenticate.php:55 +msgid "Type {0} is not valid" +msgstr "Tipo {0} não é válido" + +#: Auth/ApiKeyAuthenticate.php:59 +msgid "Type {0} has no associated callable" +msgstr "Tipo {0} não tem chamada associada" + +#: Auth/ApiKeyAuthenticate.php:68 +msgid "SSL is required for ApiKey Authentication" +msgstr "SSL é requerido para autenticação por chave da API." + +#: Auth/SimpleRbacAuthorize.php:141 msgid "" "Missing configuration file: \"config/{0}.php\". Using default permissions" msgstr "" "Arquivo de configuração ausente: \"config/{0}.php\". Usando permissões padrão" +#: Auth/SocialAuthenticate.php:410 +msgid "Provider cannot be empty" +msgstr "O provedor não pode ser vazio" + +#: Auth/Rules/AbstractRule.php:77 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a " +"default table from the request" +msgstr "" +"O alias da tabela está vazio, por favor, defina um alias de tabela, nós não " +"pudemos extrair uma tabela padrão da requisição" + +#: Auth/Rules/Owner.php:67;70 +msgid "" +"Missing column {0} in table {1} while checking ownership permissions for " +"user {2}" +msgstr "" +"Coluna {0} ausente na tabela {1} ao verificar permissões de propriedade do " +"usuário {2}" + #: Controller/SocialAccountsController.php:52 msgid "Account validated successfully" msgstr "Conta validada com êxito" @@ -33,8 +65,8 @@ msgstr "A conta não pode ser validada" msgid "Invalid token and/or social account" msgstr "Token e/ou conta social inválido(s)" -#: Controller/SocialAccountsController.php:59 -msgid "SocialAccount already active" +#: Controller/SocialAccountsController.php:59;86 +msgid "Social Account already active" msgstr "Conta social já ativa" #: Controller/SocialAccountsController.php:61 @@ -53,218 +85,387 @@ msgstr "O email não pode ser enviado" msgid "Invalid account" msgstr "Conta inválida" -#: Controller/SocialAccountsController.php:86 -msgid "Social Account already active" -msgstr "Conta social já ativa" - #: Controller/SocialAccountsController.php:88 msgid "Email could not be resent" msgstr "O email não pode ser reenviado" -#: Controller/Component/RememberMeComponent.php:70 +#: Controller/Component/RememberMeComponent.php:69 msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" msgstr "" "Salt da aplicação inválido, o salt da aplicação deve ser de pelo menos 256 " "bits (32 bytes)" -#: Controller/Component/UsersAuthComponent.php:156 +#: Controller/Component/UsersAuthComponent.php:157 msgid "You can't enable email validation workflow if use_email is false" msgstr "" "Você não pode habilitar o fluxo de validação por email se use_email for false" -#: Controller/Traits/LoginTrait.php:55 -msgid "" -"The social account is not active. Please check your email for instructions. " -"{0}" -msgstr "" -"A conta social não está ativa. Por favor verifique seu email para " -"instruções. {0}" +#: Controller/Traits/LoginTrait.php:95 +msgid "Issues trying to log in with your social account" +msgstr "Problemas ao tentar autenticar a partir da sua conta social" -#: Controller/Traits/LoginTrait.php:58 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:100 Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "Por favor indique seu email" -#: Controller/Traits/LoginTrait.php:82 +#: Controller/Traits/LoginTrait.php:106 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Seu usuário ainda não foi validado. Por favor, verifique sua caixa de " +"entrada para instruções" + +#: Controller/Traits/LoginTrait.php:108 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Sua conta social ainda não foi validada. Por favor, verifique sua caixa de " +"entrada para instruções" + +#: Controller/Traits/LoginTrait.php:157 Controller/Traits/RegisterTrait.php:73 +msgid "Invalid reCaptcha" +msgstr "ReCaptcha inválido" + +#: Controller/Traits/LoginTrait.php:165 +msgid "You are already logged in" +msgstr "Você já está autenticado" + +#: Controller/Traits/LoginTrait.php:209 msgid "Username or password is incorrect" msgstr "Nome de usuário e/ou senha incorreto(s)" -#: Controller/Traits/LoginTrait.php:93 -msgid "There was an error associating your social network account" -msgstr "Houve um erro associando sua conta social" - -#: Controller/Traits/LoginTrait.php:113 +#: Controller/Traits/LoginTrait.php:230 msgid "You've successfully logged out" msgstr "Você desconectou-se com êxito" -#: Controller/Traits/PasswordManagementTrait.php:53 -msgid "Password has been changed successfully" -msgstr "Senha alterada com êxito" - -#: Controller/Traits/PasswordManagementTrait.php:56;63 +#: Controller/Traits/PasswordManagementTrait.php:53;60;68 msgid "Password could not be changed" msgstr "A senha não pode ser alterada" -#: Controller/Traits/PasswordManagementTrait.php:59 -#: Controller/Traits/ProfileTrait.php:46 +#: Controller/Traits/PasswordManagementTrait.php:57 +msgid "Password has been changed successfully" +msgstr "Senha alterada com êxito" + +#: Controller/Traits/PasswordManagementTrait.php:64 +#: Controller/Traits/ProfileTrait.php:49 msgid "User was not found" msgstr "O usuário não foi encontrado" -#: Controller/Traits/PasswordManagementTrait.php:61 +#: Controller/Traits/PasswordManagementTrait.php:66 msgid "The current password does not match" msgstr "A senha atual não corresponde" -#: Controller/Traits/PasswordManagementTrait.php:93 +#: Controller/Traits/PasswordManagementTrait.php:108 msgid "Please check your email to continue with password reset process" msgstr "" "Por favor, verifique seu email para continuar o processo de redefinição de " "senha" -#: Controller/Traits/PasswordManagementTrait.php:96 +#: Controller/Traits/PasswordManagementTrait.php:111 Shell/UsersShell.php:266 msgid "The password token could not be generated. Please try again" msgstr "O token de senha não pode ser gerado. Por favor, tente novamente" -#: Controller/Traits/PasswordManagementTrait.php:101 -#: Controller/Traits/UserValidationTrait.php:94 +#: Controller/Traits/PasswordManagementTrait.php:116 +#: Controller/Traits/UserValidationTrait.php:98 msgid "User {0} was not found" msgstr "O usuário {0} não foi encontrado" -#: Controller/Traits/PasswordManagementTrait.php:103 -#: Controller/Traits/UserValidationTrait.php:90;98 +#: Controller/Traits/PasswordManagementTrait.php:118 +msgid "The user is not active" +msgstr "O usuário não está ativo" + +#: Controller/Traits/PasswordManagementTrait.php:120 +#: Controller/Traits/UserValidationTrait.php:94;102 msgid "Token could not be reset" msgstr "O token não pode ser redefinido" -#: Controller/Traits/RegisterTrait.php:66 +#: Controller/Traits/ProfileTrait.php:52 +msgid "Not authorized, please login first" +msgstr "Não autorizado, por favor, autentique-se primeiro" + +#: Controller/Traits/RegisterTrait.php:79 msgid "The user could not be saved" msgstr "O usuário não pode ser salvo" -#: Controller/Traits/RegisterTrait.php:82 +#: Controller/Traits/RegisterTrait.php:111 msgid "You have registered successfully, please log in" msgstr "Você registrou-se com sucesso, por favor, autentique-se" -#: Controller/Traits/RegisterTrait.php:84 +#: Controller/Traits/RegisterTrait.php:113 msgid "Please validate your account before log in" msgstr "Por favor, valide sua conta antes de autenticar" -#: Controller/Traits/SimpleCrudTrait.php:75;103 +#: Controller/Traits/SimpleCrudTrait.php:76;105 msgid "The {0} has been saved" msgstr "O {0} foi salvo" -#: Controller/Traits/SimpleCrudTrait.php:78;106 +#: Controller/Traits/SimpleCrudTrait.php:79;108 msgid "The {0} could not be saved" msgstr "O {0} não pode ser salvo" -#: Controller/Traits/SimpleCrudTrait.php:125 +#: Controller/Traits/SimpleCrudTrait.php:128 msgid "The {0} has been deleted" msgstr "O {0} foi deletado" -#: Controller/Traits/SimpleCrudTrait.php:127 +#: Controller/Traits/SimpleCrudTrait.php:130 msgid "The {0} could not be deleted" msgstr "O {0} não pode ser deletado" -#: Controller/Traits/UserValidationTrait.php:43 +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "O reCaptcha não pode ser validado" + +#: Controller/Traits/UserValidationTrait.php:42 msgid "User account validated successfully" msgstr "Conta de usuário validada com êxito" -#: Controller/Traits/UserValidationTrait.php:45 +#: Controller/Traits/UserValidationTrait.php:44 msgid "User account could not be validated" msgstr "A conta de usuário não pode ser validada" -#: Controller/Traits/UserValidationTrait.php:48 +#: Controller/Traits/UserValidationTrait.php:47 msgid "User already active" msgstr "Usuário já ativo" -#: Controller/Traits/UserValidationTrait.php:54 +#: Controller/Traits/UserValidationTrait.php:53 msgid "Reset password token was validated successfully" msgstr "Token de redefinição de senha validado com êxito" -#: Controller/Traits/UserValidationTrait.php:58 +#: Controller/Traits/UserValidationTrait.php:57 msgid "Reset password token could not be validated" msgstr "O token de redefinição de senha não pode ser validado" -#: Controller/Traits/UserValidationTrait.php:65 -msgid "Invalid token and/or email" -msgstr "Token e/ou email inválido(s)" +#: Controller/Traits/UserValidationTrait.php:61 +msgid "Invalid validation type" +msgstr "Tipo de validação inválido" + +#: Controller/Traits/UserValidationTrait.php:64 +msgid "Invalid token or user account already validated" +msgstr "Token inválido ou conta já validada" -#: Controller/Traits/UserValidationTrait.php:67 +#: Controller/Traits/UserValidationTrait.php:66 msgid "Token already expired" msgstr "Token expirado" -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid validation type" -msgstr "Tipo de validação inválido" - -#: Controller/Traits/UserValidationTrait.php:88 +#: Controller/Traits/UserValidationTrait.php:92 msgid "Token has been reset successfully. Please check your email." msgstr "O token foi redefinido com êxito. Por favor, verifique seu email." -#: Controller/Traits/UserValidationTrait.php:96 +#: Controller/Traits/UserValidationTrait.php:100 msgid "User {0} is already active" msgstr "O usuário {0} já está ativo" -#: Model/Table/SocialAccountsTable.php:208 +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Seu link de validação da conta" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0}Seu link de redefinição de senha" + +#: Mailer/UsersMailer.php:78 msgid "{0}Your social account validation link" msgstr "{0}Seu link de validação da conta social" -#: Model/Table/SocialAccountsTable.php:235;263 +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "A referência não pode ser nula" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "A expiração do token não pode ser vazia" + +#: Model/Behavior/PasswordBehavior.php:67;115 +msgid "User not found" +msgstr "Usuário não encontrado" + +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:110 +msgid "User account already validated" +msgstr "Conta de usuário já validada" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "Usuário inativo" + +#: Model/Behavior/PasswordBehavior.php:120 +msgid "The old password does not match" +msgstr "A senha antiga não confere" + +#: Model/Behavior/RegisterBehavior.php:88 +msgid "User not found for the given token and email." +msgstr "Usuário não encontrado com a combinação de token e email" + +#: Model/Behavior/RegisterBehavior.php:91 +msgid "Token has already expired user with no token" +msgstr "Token expirado, usuário sem token" + +#: Model/Behavior/SocialAccountBehavior.php:101;128 msgid "Account already validated" msgstr "Conta já validada" -#: Model/Table/SocialAccountsTable.php:238;266 +#: Model/Behavior/SocialAccountBehavior.php:104;131 msgid "Account not found for the given token and email." msgstr "Conta não encontrada com a combinação de token e email" -#: Model/Table/UsersTable.php:84 +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "Incapaz de autenticar usuário com a referência {0}" + +#: Model/Behavior/SocialBehavior.php:97 +msgid "Email not present" +msgstr "Email ausente" + +#: Model/Table/UsersTable.php:81 msgid "Your password does not match your confirm password. Please try again" msgstr "" "Sua senha não corresponde com a confirmação. Por favor, tente novamente" -#: Model/Table/UsersTable.php:178 +#: Model/Table/UsersTable.php:159 msgid "Username already exists" msgstr "Nome de usuário em uso" -#: Model/Table/UsersTable.php:184 +#: Model/Table/UsersTable.php:165 msgid "Email already exists" msgstr "Email em uso" -#: Model/Table/UsersTable.php:213 -msgid "The \"tos\" property is not present" -msgstr "A propriedade “tos” não está presente" +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Utilitários para CakeDC Users Plugin" -#: Model/Table/UsersTable.php:271 -msgid "Token has already expired user with no token" -msgstr "Token expirado, usuário sem token" +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Ativar um usuário específico" -#: Model/Table/UsersTable.php:274 -msgid "User not found for the given token and email." -msgstr "Usuário não encontrado com a combinação de token e email" +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "Adicionar um novo usuário superadmin para fins de testes" -#: Model/Table/UsersTable.php:341 -msgid "User not found" -msgstr "Usuário não encontrado" +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "Adicionar um novo usuário" -#: Model/Table/UsersTable.php:368 -msgid "+ {0} secs" -msgstr "+ {0} segundos" +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Mudar o role de um usuário específico" -#: Model/Table/UsersTable.php:420 -msgid "Unable to login user with reference {0}" -msgstr "Incapaz de autenticar usuário com a referência {0}" +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "Desativar um usuário específico" -#: Model/Table/UsersTable.php:453 -msgid "Email not present" -msgstr "Email ausente" +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Deletar um usuário específico" -#: Model/Table/UsersTable.php:541 -msgid "Your account validation link" -msgstr "Seu link de validação da conta" +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "Redefinir a senha via email" -#: Model/Table/UsersTable.php:561 -msgid "{0}Your reset password link" -msgstr "{0}Seu link de redefinição de senha" +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "Redefinir a senha de todos usuários" -#: Model/Table/UsersTable.php:585 -msgid "The old password does not match" -msgstr "A senha antiga não confere" +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "Redefinir a senha de um usuário específico" + +#: Shell/UsersShell.php:97 +msgid "User added:" +msgstr "Usuário adicionado:" + +#: Shell/UsersShell.php:98;126 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:99;127 +msgid "Username: {0}" +msgstr "Nome de usuário: {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Email: {0}" +msgstr "Email: {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Password: {0}" +msgstr "Senha: {0}" + +#: Shell/UsersShell.php:125 +msgid "Superuser added:" +msgstr "Superusuário adicionado:" + +#: Shell/UsersShell.php:131 +msgid "Superuser could not be added:" +msgstr "O superusuário não pode ser adicionado:" + +#: Shell/UsersShell.php:134 +msgid "Field: {0} Error: {1}" +msgstr "Campo: {0} Erro: {1}" + +#: Shell/UsersShell.php:152;178 +msgid "Please enter a password." +msgstr "Por favor, indique uma senha." + +#: Shell/UsersShell.php:156 +msgid "Password changed for all users" +msgstr "As senhas de todos usuários foram alteradas" + +#: Shell/UsersShell.php:157;185 +msgid "New password: {0}" +msgstr "Nova senha: {0}" + +#: Shell/UsersShell.php:175;203;281;321 +msgid "Please enter a username." +msgstr "Por favor, indique um nome de usuário." + +#: Shell/UsersShell.php:184 +msgid "Password changed for user: {0}" +msgstr "Senha alterada para usuário: {0}" + +#: Shell/UsersShell.php:206 +msgid "Please enter a role." +msgstr "Por favor, indique um papel." + +#: Shell/UsersShell.php:212 +msgid "Role changed for user: {0}" +msgstr "Papel alterado para usuário: {0}" + +#: Shell/UsersShell.php:213 +msgid "New role: {0}" +msgstr "Novo papel: {0}" + +#: Shell/UsersShell.php:228 +msgid "User was activated: {0}" +msgstr "Usuário ativado: {0}" + +#: Shell/UsersShell.php:243 +msgid "User was de-activated: {0}" +msgstr "Usuário desativado: {0}" + +#: Shell/UsersShell.php:255 +msgid "Please enter a username or email." +msgstr "Por favor, indique um nome de usuário ou senha." + +#: Shell/UsersShell.php:263 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Por favor, peça ao usuário para verificar seu email para continuar o " +"processo de redefinição de senha" + +#: Shell/UsersShell.php:300 +msgid "The user was not found." +msgstr "O usuário não foi encontrado." + +#: Shell/UsersShell.php:329 +msgid "The user {0} was not deleted. Please try again" +msgstr "O usuário {0} não foi deletado. Por favor, tente novamente" + +#: Shell/UsersShell.php:331 +msgid "The user {0} was deleted successfully" +msgstr "O usuário {0} foi deletado com êxito" #: Template/Email/html/reset_password.ctp:21 #: Template/Email/html/social_account_validation.ctp:14 @@ -281,13 +482,12 @@ msgstr "Redefina sua senha aqui" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 msgid "" -"If the link is not correctly displayed, please copy the following address in " +"If the link is not correcly displayed, please copy the following address in " "your web browser {0}" msgstr "" -"Se o link não está exibido corretamente, por favor, copie o seguinte " -"endereço em seu navegador {0}" +"Se o link não estiver sendo exibido corretamente, por favor, copie o " +"endereço a seguir no seu navegador {0}" #: Template/Email/html/reset_password.ctp:30 #: Template/Email/html/social_account_validation.ctp:35 @@ -306,6 +506,14 @@ msgstr "Ative sua autenticação social aqui" msgid "Activate your account here" msgstr "Ative sua conta aqui" +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Se o link não está exibido corretamente, por favor, copie o seguinte " +"endereço em seu navegador {0}" + #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" @@ -334,12 +542,12 @@ msgstr "Listar usuários" msgid "List Accounts" msgstr "Listar contas" -#: Template/Users/add.ctp:22 Template/Users/register.ctp:15 +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 msgid "Add User" msgstr "Adicionar usuário" -#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:13 -#: Template/Users/edit.ctp:42 Template/Users/register.ctp:26 +#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:17 +#: Template/Users/edit.ctp:42 Template/Users/register.ctp:32 #: Template/Users/request_reset_password.ctp:8 #: Template/Users/resend_token_validation.ctp:20 #: Template/Users/social_email.ctp:19 @@ -350,7 +558,7 @@ msgstr "Enviar" msgid "Please enter the new password" msgstr "Por favor, indique a nova senha" -#: Template/Users/change_password.ctp:7 +#: Template/Users/change_password.ctp:10 msgid "Current password" msgstr "Senha atual" @@ -396,47 +604,51 @@ msgstr "próximo" msgid "Please enter your username and password" msgstr "Por favor, indique seu nome de usuário e senha" -#: Template/Users/login.ctp:26 +#: Template/Users/login.ctp:29 msgid "Remember me" msgstr "Lembrar" -#: Template/Users/login.ctp:49 +#: Template/Users/login.ctp:48 msgid "Login" msgstr "Autenticar" -#: Template/Users/profile.ctp:18 +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 msgid "{0} {1}" msgstr "{0} {1}" -#: Template/Users/profile.ctp:23 +#: Template/Users/profile.ctp:24 msgid "Change Password" msgstr "Mudar senha" -#: Template/Users/profile.ctp:26 Template/Users/view.ctp:28;68 +#: Template/Users/profile.ctp:27 Template/Users/view.ctp:28;68 msgid "Username" msgstr "Nome de usuário" -#: Template/Users/profile.ctp:28 Template/Users/view.ctp:30 +#: Template/Users/profile.ctp:29 Template/Users/view.ctp:30 msgid "Email" msgstr "Email" -#: Template/Users/profile.ctp:33 +#: Template/Users/profile.ctp:34 msgid "Social Accounts" msgstr "Contas sociais" -#: Template/Users/profile.ctp:37 Template/Users/view.ctp:70 +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:70 msgid "Avatar" msgstr "Avatar" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:67 +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:67 msgid "Provider" msgstr "Provedor" -#: Template/Users/profile.ctp:39 +#: Template/Users/profile.ctp:40 msgid "Link" msgstr "Link" -#: Template/Users/register.ctp:23 +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Link para {0}" + +#: Template/Users/register.ctp:25 msgid "Accept TOS conditions?" msgstr "Concordar com TOS?" @@ -520,18 +732,51 @@ msgstr "Referência" msgid "Data" msgstr "Dados" -#: View/Helper/UserHelper.php:43 -msgid "Sign in with Facebook" -msgstr "Inscrever-se com Facebook" +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "fa-fa-{0}" -#: View/Helper/UserHelper.php:57 -msgid "Sign in with Twitter" -msgstr "Inscrever-se com Twitter" +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0}" -#: View/Helper/UserHelper.php:71 +#: View/Helper/UserHelper.php:90 msgid "Logout" msgstr "Desconectar" -#: View/Helper/UserHelper.php:109 +#: View/Helper/UserHelper.php:139 msgid "Welcome, {0}" msgstr "Bem-vindo(a), {0}" + +#: View/Helper/UserHelper.php:161 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"O reCaptcha não está configurado! Por favor, configure Users.reCaptcha.key" + +#~ msgid "SocialAccount already active" +#~ msgstr "Conta social já ativa" + +#~ msgid "" +#~ "The social account is not active. Please check your email for " +#~ "instructions. {0}" +#~ msgstr "" +#~ "A conta social não está ativa. Por favor verifique seu email para " +#~ "instruções. {0}" + +#~ msgid "There was an error associating your social network account" +#~ msgstr "Houve um erro associando sua conta social" + +#~ msgid "Invalid token and/or email" +#~ msgstr "Token e/ou email inválido(s)" + +#~ msgid "The \"tos\" property is not present" +#~ msgstr "A propriedade “tos” não está presente" + +#~ msgid "+ {0} secs" +#~ msgstr "+ {0} segundos" + +#~ msgid "Sign in with Facebook" +#~ msgstr "Inscrever-se com Facebook" + +#~ msgid "Sign in with Twitter" +#~ msgstr "Inscrever-se com Twitter" From 3b2183ea9ae8742eabba02eef6c09a90c0d1c91c Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 19 Apr 2016 19:29:57 -0500 Subject: [PATCH 0445/1476] Avoid using the same password as old/new. Improving messages --- src/Controller/Traits/PasswordManagementTrait.php | 2 +- src/Model/Behavior/PasswordBehavior.php | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 5c76767d1..9807df795 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -63,7 +63,7 @@ public function changePassword() } catch (UserNotFoundException $exception) { $this->Flash->error(__d('Users', 'User was not found')); } catch (WrongPasswordException $wpe) { - $this->Flash->error(__d('Users', 'The current password does not match')); + $this->Flash->error(__d('Users', '{0}', $wpe->getMessage())); } catch (Exception $exception) { $this->Flash->error(__d('Users', 'Password could not be changed')); } diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 0169fabdf..726927875 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -117,7 +117,10 @@ public function changePassword(EntityInterface $user) if (!empty($user->current_password)) { if (!$user->checkPassword($user->current_password, $currentUser->password)) { - throw new WrongPasswordException(__d('Users', 'The old password does not match')); + throw new WrongPasswordException(__d('Users', 'The current password does not match')); + } + if ($user->current_password === $user->password_confirm) { + throw new WrongPasswordException(__d('Users', 'You cannot use the current password as the new one')); } } $user = $this->_table->save($user); From f3fada67446ce84f1ff5f200834b007c90d72fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Wed, 20 Apr 2016 09:40:27 -0300 Subject: [PATCH 0446/1476] Fixing tests --- tests/TestCase/Controller/SocialAccountsControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 7b269638a..c85dc2e86 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -123,7 +123,7 @@ public function testValidateAccountAlreadyActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Social Account already active', $this->Controller->request->session()->read('Flash.flash.0.message')); } /** @@ -197,6 +197,6 @@ public function testResendValidationAlreadyActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('SocialAccount already active', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Social Account already active', $this->Controller->request->session()->read('Flash.flash.0.message')); } } From 3277c685cd52725216e71309d7b77327c6f00e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Wed, 20 Apr 2016 09:51:58 -0300 Subject: [PATCH 0447/1476] Preparing es localization file for future translations --- src/Locale/es/Users.mo | Bin 9650 -> 8934 bytes src/Locale/es/Users.po | 482 ++++++++++++++++++++++++++++++----------- 2 files changed, 357 insertions(+), 125 deletions(-) diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo index 421ce4ba1bf00309b9e9566221553c1181222840..b5a47db8fb6c5722299eb21d3248b5ca82af35ad 100644 GIT binary patch delta 2661 zcmYk-du)?c7{~F$IwqHmZ3V|=;9eLPxpXUAfo(9h;RcLxbE_c2z?ZE+S!tmyxFukn zhD43VkOmVY2q9S(k)WY5QNYV$lthd{g=qL=(Wq#Q_XJT4(eJN)XFS={&v{SZp38I2 z`|e!Jji$t)JNu}i>?I}>$6Us!Ve(ykQ1*^ArU>`pM0^tO!BgnP0q6R6)K3aW88Znd zVhQ>%AN`nvoj3x!ke?(>oXSiZ9(8W$L;c{4<3&`*A7KGr#ccc*)!`2~8h>-z?;stU zEEHl9XJFgMqjMx2bLXrnql zjGDl4)I|F+56__bJ&&5$`@e!PW{iq4Oi!*Q# z`7_ycqKu70^;?X}%na07XvW1D#A56#Apbga12pK+459}33w7w+g_%^%Miyzx@oua| z-PeZmFof#(1=Px}p;kPI%3zK=Gm$Zl6*!jm4Q}#JHq34sJlKQ$nSMSrq4TJTTtjvI zBPugDaVqA~i}tu2**)XKdThXQd>r+(oI@@26V#dc8TGr$1V>XHSD|LwfJ#j>YOe$M z(lBG5L9J*mvtex0hU#z!R^bzh2lzINJgBVCvY%wAjML2X&WM@4(ph_i96 zb3->WNt19)I_>?a37kcp;sMlvmylgES5O0dh05&rsQYfAes>2o(E|35g(gfH7479J zJ~X3_%oiqx>gYMt0MDZy!xI?9Q>X!Rd8n7-6tr*)YJfwig}sRCrw=uuGpKPc;0Qhc zm#JumS8)?wM?I%L4uB3_9jc=>I2||QG(3pg@C3HwKUjzDEK8X@j@tW6Sc^AMXKXtA zCR=eN$n&{!+Ol8(ZcmeHqAcN#GXQB2z!;wl`=>=J6&N<}m6<%93cNhG`GZPWmtqcZdh>XhF^o-C79l9|XjoXPb9T!~vy z8SBGZd=<68pHPSRPrMf`i~OsjW-IetZ^mk__c_Y1t{>-V?lHhxCgI%obu3k)!=hRgTJWrTlp4Bl+|hd_w@fo4WnnTgpFC2osLHq8=EWfN?fln=0$wr4n8Q28Dsb}O?)iGc3gse zxC~v);*;t1FHk>y5AVV2xE%k3b8*ouW2$it-f2wHv{1Q=h7Mef+tV9HP(KJ#i>QvD z!5VxHEAbMl!&i_$b2V*$6V>l;unOPB1^7N{0XK0GWO=6Ncb;ftt&Ucz3y zjHJkXmOA6^Bm)_&r+pqOV_EFM{kR{W!_D|9>b@pssfqMr3m(Qb_+u=trScjT4fHW; zrZ-V3{uh!ZQ^kcksKs^Igd6Y?T#To&4$q-dd=)kD@9_eq)40UME;1;}s1NaGk3A^Vd9UVZWd;&F*GpIxQGIrrLRA#?Gl4xemPbOM} zx_|Y2^1q%+4-Fb9kIKX)REn;k4&4W+iG7?}#WJayCM3(I8=J8o8OwYVHL<5r6S{=z z_YG7g-$pI?qaqa@ikak(^JDJ7ZMXo-DMmeJr%|c9h&pW7P`|6DcXd1qHPHpA3@t^S zjZXa54E7v#n6ERs7Ip(Q(c)b4ppF}`6MIm5cLLS%Pm$l6^J)8Q$ehi4s6G4}YH$CE z+DbiJO^`u--;T=Emehf?J%>!7XpT|Q9zB5?@O#L4F+W0ea2A!~i>UjiP&0oWHPPRr zR(unggQ+I(n$U7o`vz1$eW?ETpdRCc=;`@?jEV+)8@J*INMB|#zqYs$HP9exg~w4H zoTfo zQ2rmo`Z-vH1{oyue(xiOi2a0S=@NOu5(9+J#w76|p){@_lxCH05F_PU^5MhdL`+l> zox~hMg{>`*Urtp!4cha^2xVX|F-$0}UnXuZI!woiej-O`%T#s~M~UskR|utg6QNQ` z=tcGbp)-;c#t*3-CkliP(W8XQ)`apSs579#tKn8*=gfVC_M6=?V?>rv*+Xn7*Npi( zdW5!FMK3RvZA445{^Xs$hK5IonS{z=LeFWS3(Crb^5;fAJJRd@lcdx1j-<~PyDRTHk!y1!Zm!&EXv=fAj|U;sj^ePu;DH~tXoaPVHQ(Pn z;)brBbRz5c)(u1MbE5JXvF8tKUZG8g^xb$e2uG)fo@%T;SJBbdob9k1vt4bQ)@3P~ zT?5T~+zBsYkmmcH*zMxW*87^X?ai&5Y->kXd&jzLYc^YIty^Cjt2@7<--+Vpy`ker zc_$9SE}Q9h{NaK#%rD*O@Q%UKtc5mn+lH)N*jX|E9Ec>kDzev)$^#A|> diff --git a/src/Locale/es/Users.po b/src/Locale/es/Users.po index 70e84f892..e6a31e11b 100644 --- a/src/Locale/es/Users.po +++ b/src/Locale/es/Users.po @@ -4,25 +4,53 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2016-03-07 20:35+0000\n" -"PO-Revision-Date: 2016-04-15 17:47+0100\n" +"POT-Creation-Date: 2016-04-20 09:48-0300\n" +"PO-Revision-Date: 2016-04-20 09:49-0300\n" +"Last-Translator: André Teixeira \n" "Language-Team: CakeDC \n" +"Language: es_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.8.7\n" -"Last-Translator: \n" -"Language: es_ES\n" "X-Poedit-SourceCharset: UTF-8\n" -#: Auth/SimpleRbacAuthorize.php:132 +#: Auth/ApiKeyAuthenticate.php:55 +msgid "Type {0} is not valid" +msgstr "" + +#: Auth/ApiKeyAuthenticate.php:59 +msgid "Type {0} has no associated callable" +msgstr "" + +#: Auth/ApiKeyAuthenticate.php:68 +msgid "SSL is required for ApiKey Authentication" +msgstr "" + +#: Auth/SimpleRbacAuthorize.php:141 msgid "" "Missing configuration file: \"config/{0}.php\". Using default permissions" msgstr "" "Falta el archivo de configuración: \"config/{0}.php\". Utilizando permisos " "predeterminados" +#: Auth/SocialAuthenticate.php:410 +msgid "Provider cannot be empty" +msgstr "" + +#: Auth/Rules/AbstractRule.php:77 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a " +"default table from the request" +msgstr "" + +#: Auth/Rules/Owner.php:67;70 +msgid "" +"Missing column {0} in table {1} while checking ownership permissions for " +"user {2}" +msgstr "" + #: Controller/SocialAccountsController.php:52 msgid "Account validated successfully" msgstr "Cuenta validada correctamente" @@ -35,8 +63,8 @@ msgstr "No se pudo validar la cuenta" msgid "Invalid token and/or social account" msgstr "Token o cuenta social incorrecta" -#: Controller/SocialAccountsController.php:59 -msgid "SocialAccount already active" +#: Controller/SocialAccountsController.php:59;86 +msgid "Social Account already active" msgstr "Cuenta social ya activa" #: Controller/SocialAccountsController.php:61 @@ -55,219 +83,382 @@ msgstr "No se puede enviar el email" msgid "Invalid account" msgstr "Cuenta inválida" -#: Controller/SocialAccountsController.php:86 -msgid "Social Account already active" -msgstr "Cuenta social ya activa" - #: Controller/SocialAccountsController.php:88 msgid "Email could not be resent" msgstr "No se puede reenviar el Email" -#: Controller/Component/RememberMeComponent.php:70 +#: Controller/Component/RememberMeComponent.php:69 msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" msgstr "App salt inválido, debe contener al menos 256 bits (32 bytes)" -#: Controller/Component/UsersAuthComponent.php:156 +#: Controller/Component/UsersAuthComponent.php:157 msgid "You can't enable email validation workflow if use_email is false" msgstr "" "No es posible activar el flujo de trabajo para la validación de email si " "use_mail es falso" -#: Controller/Traits/LoginTrait.php:55 -msgid "" -"The social account is not active. Please check your email for instructions. " -"{0}" +#: Controller/Traits/LoginTrait.php:95 +msgid "Issues trying to log in with your social account" msgstr "" -"La cuenta social está inactiva. Por favor, compruebe las instrucciones en su " -"correo. {0}" -#: Controller/Traits/LoginTrait.php:58 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:100 Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "Por favor, introduzca su email" -#: Controller/Traits/LoginTrait.php:82 +#: Controller/Traits/LoginTrait.php:106 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" + +#: Controller/Traits/LoginTrait.php:108 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" + +#: Controller/Traits/LoginTrait.php:157 Controller/Traits/RegisterTrait.php:73 +msgid "Invalid reCaptcha" +msgstr "" + +#: Controller/Traits/LoginTrait.php:165 +msgid "You are already logged in" +msgstr "" + +#: Controller/Traits/LoginTrait.php:209 msgid "Username or password is incorrect" msgstr "Usuario o contraseña incorrecta" -#: Controller/Traits/LoginTrait.php:93 -msgid "There was an error associating your social network account" -msgstr "Hubo un error al asociar su cuenta de la red social" - -#: Controller/Traits/LoginTrait.php:113 +#: Controller/Traits/LoginTrait.php:230 msgid "You've successfully logged out" msgstr "Ha cerrado sesión correctamente" -#: Controller/Traits/PasswordManagementTrait.php:53 -msgid "Password has been changed successfully" -msgstr "Contraseña cambiada correctamente" - -#: Controller/Traits/PasswordManagementTrait.php:56;63 +#: Controller/Traits/PasswordManagementTrait.php:53;60;68 msgid "Password could not be changed" msgstr "No es posible cambiar la contraseña" -#: Controller/Traits/PasswordManagementTrait.php:59 -#: Controller/Traits/ProfileTrait.php:46 +#: Controller/Traits/PasswordManagementTrait.php:57 +msgid "Password has been changed successfully" +msgstr "Contraseña cambiada correctamente" + +#: Controller/Traits/PasswordManagementTrait.php:64 +#: Controller/Traits/ProfileTrait.php:49 msgid "User was not found" msgstr "Usuario no encontrado" -#: Controller/Traits/PasswordManagementTrait.php:61 +#: Controller/Traits/PasswordManagementTrait.php:66 msgid "The current password does not match" msgstr "La contraseña actual no coincide" -#: Controller/Traits/PasswordManagementTrait.php:93 +#: Controller/Traits/PasswordManagementTrait.php:108 msgid "Please check your email to continue with password reset process" msgstr "" "Por favor, compruebe su correo para continuar con el proceso de " "restablecimiento de contraseña" -#: Controller/Traits/PasswordManagementTrait.php:96 +#: Controller/Traits/PasswordManagementTrait.php:111 Shell/UsersShell.php:266 msgid "The password token could not be generated. Please try again" msgstr "" "No se pudo generar el token de contraseña. Por favor, inténtelo de nuevo" -#: Controller/Traits/PasswordManagementTrait.php:101 -#: Controller/Traits/UserValidationTrait.php:94 +#: Controller/Traits/PasswordManagementTrait.php:116 +#: Controller/Traits/UserValidationTrait.php:98 msgid "User {0} was not found" msgstr "Usuario {0} no encontrado" -#: Controller/Traits/PasswordManagementTrait.php:103 -#: Controller/Traits/UserValidationTrait.php:90;98 +#: Controller/Traits/PasswordManagementTrait.php:118 +msgid "The user is not active" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:120 +#: Controller/Traits/UserValidationTrait.php:94;102 msgid "Token could not be reset" msgstr "No se puede restablecer el token" -#: Controller/Traits/RegisterTrait.php:66 +#: Controller/Traits/ProfileTrait.php:52 +msgid "Not authorized, please login first" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:79 msgid "The user could not be saved" msgstr "No se ha podido guardar el usuario" -#: Controller/Traits/RegisterTrait.php:82 +#: Controller/Traits/RegisterTrait.php:111 msgid "You have registered successfully, please log in" msgstr "Se ha registrado correctamente, por favor ingrese" -#: Controller/Traits/RegisterTrait.php:84 +#: Controller/Traits/RegisterTrait.php:113 msgid "Please validate your account before log in" msgstr "Por favor, valide su cuenta antes de ingresar" -#: Controller/Traits/SimpleCrudTrait.php:75;103 +#: Controller/Traits/SimpleCrudTrait.php:76;105 msgid "The {0} has been saved" msgstr "El {0} ha sido guardado" -#: Controller/Traits/SimpleCrudTrait.php:78;106 +#: Controller/Traits/SimpleCrudTrait.php:79;108 msgid "The {0} could not be saved" msgstr "El {0} no ha podido guardarse" -#: Controller/Traits/SimpleCrudTrait.php:125 +#: Controller/Traits/SimpleCrudTrait.php:128 msgid "The {0} has been deleted" msgstr "El {0} ha sido eliminado" -#: Controller/Traits/SimpleCrudTrait.php:127 +#: Controller/Traits/SimpleCrudTrait.php:130 msgid "The {0} could not be deleted" msgstr "El {0} no ha podido eliminarse" -#: Controller/Traits/UserValidationTrait.php:43 +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:42 msgid "User account validated successfully" msgstr "Cuenta de usuario validada correctamente" -#: Controller/Traits/UserValidationTrait.php:45 +#: Controller/Traits/UserValidationTrait.php:44 msgid "User account could not be validated" msgstr "No se pudo validar la cuenta de usuario" -#: Controller/Traits/UserValidationTrait.php:48 +#: Controller/Traits/UserValidationTrait.php:47 msgid "User already active" msgstr "Usuario ya activo" -#: Controller/Traits/UserValidationTrait.php:54 +#: Controller/Traits/UserValidationTrait.php:53 msgid "Reset password token was validated successfully" msgstr "Restablecimiento del token de contraseña validado correctamente" -#: Controller/Traits/UserValidationTrait.php:58 +#: Controller/Traits/UserValidationTrait.php:57 msgid "Reset password token could not be validated" msgstr "Restablecimiento del token de contraseña no pudo validarse" -#: Controller/Traits/UserValidationTrait.php:65 -msgid "Invalid token and/or email" -msgstr "Token y/o email inválido" +#: Controller/Traits/UserValidationTrait.php:61 +msgid "Invalid validation type" +msgstr "Tipo de validación inválido" -#: Controller/Traits/UserValidationTrait.php:67 +#: Controller/Traits/UserValidationTrait.php:64 +msgid "Invalid token or user account already validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:66 msgid "Token already expired" msgstr "Token ya expirado" -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid validation type" -msgstr "Tipo de validación inválido" - -#: Controller/Traits/UserValidationTrait.php:88 +#: Controller/Traits/UserValidationTrait.php:92 msgid "Token has been reset successfully. Please check your email." msgstr "" "Se ha restablecido el token correctamente. Por favor compruebe su email." -#: Controller/Traits/UserValidationTrait.php:96 +#: Controller/Traits/UserValidationTrait.php:100 msgid "User {0} is already active" msgstr "El usuario {0} ya está activo" -#: Model/Table/SocialAccountsTable.php:208 +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Enlace para validar su cuenta" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0} Enlace para restablecer su contraseña" + +#: Mailer/UsersMailer.php:78 msgid "{0}Your social account validation link" msgstr "{0} Enlace de validación de su cuenta social" -#: Model/Table/SocialAccountsTable.php:235;263 +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:67;115 +msgid "User not found" +msgstr "Usuario no encontrado" + +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:110 +msgid "User account already validated" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:120 +msgid "The old password does not match" +msgstr "La antigua contraseña no coincide" + +#: Model/Behavior/RegisterBehavior.php:88 +msgid "User not found for the given token and email." +msgstr "Usuario no encontrado para el token y email proporcionado" + +#: Model/Behavior/RegisterBehavior.php:91 +msgid "Token has already expired user with no token" +msgstr "El token ha expirado usuario sin token" + +#: Model/Behavior/SocialAccountBehavior.php:101;128 msgid "Account already validated" msgstr "Cuenta ya activada" -#: Model/Table/SocialAccountsTable.php:238;266 +#: Model/Behavior/SocialAccountBehavior.php:104;131 msgid "Account not found for the given token and email." msgstr "Cuenta no encontrada para el token y email proporcionado" -#: Model/Table/UsersTable.php:84 +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "No se puede iniciar sesión con el usuario con referencia {0}" + +#: Model/Behavior/SocialBehavior.php:97 +msgid "Email not present" +msgstr "No se encuentra el email" + +#: Model/Table/UsersTable.php:81 msgid "Your password does not match your confirm password. Please try again" msgstr "" "Su contraseña y la comprobación no concuerdan. Por favor inténtelo de nuevo" -#: Model/Table/UsersTable.php:178 +#: Model/Table/UsersTable.php:159 msgid "Username already exists" msgstr "Nombre de usuario ya existente" -#: Model/Table/UsersTable.php:184 +#: Model/Table/UsersTable.php:165 msgid "Email already exists" msgstr "Email ya existente" -#: Model/Table/UsersTable.php:213 -msgid "The \"tos\" property is not present" -msgstr "La propiedad \"tos\" no está presente" +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "" -#: Model/Table/UsersTable.php:271 -msgid "Token has already expired user with no token" -msgstr "El token ha expirado usuario sin token" +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "" -#: Model/Table/UsersTable.php:274 -msgid "User not found for the given token and email." -msgstr "Usuario no encontrado para el token y email proporcionado" +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "" -#: Model/Table/UsersTable.php:341 -msgid "User not found" -msgstr "Usuario no encontrado" +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "" -#: Model/Table/UsersTable.php:368 -msgid "+ {0} secs" -msgstr "+ {0} secs" +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "" -#: Model/Table/UsersTable.php:420 -msgid "Unable to login user with reference {0}" -msgstr "No se puede iniciar sesión con el usuario con referencia {0}" +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "" -#: Model/Table/UsersTable.php:453 -msgid "Email not present" -msgstr "No se encuentra el email" +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "" -#: Model/Table/UsersTable.php:541 -msgid "Your account validation link" -msgstr "Enlace para validar su cuenta" +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "" -#: Model/Table/UsersTable.php:561 -msgid "{0}Your reset password link" -msgstr "{0} Enlace para restablecer su contraseña" +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "" -#: Model/Table/UsersTable.php:585 -msgid "The old password does not match" -msgstr "La antigua contraseña no coincide" +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "" + +#: Shell/UsersShell.php:97 +msgid "User added:" +msgstr "" + +#: Shell/UsersShell.php:98;126 +msgid "Id: {0}" +msgstr "" + +#: Shell/UsersShell.php:99;127 +msgid "Username: {0}" +msgstr "" + +#: Shell/UsersShell.php:100;128 +msgid "Email: {0}" +msgstr "" + +#: Shell/UsersShell.php:101;129 +msgid "Password: {0}" +msgstr "" + +#: Shell/UsersShell.php:125 +msgid "Superuser added:" +msgstr "" + +#: Shell/UsersShell.php:131 +msgid "Superuser could not be added:" +msgstr "" + +#: Shell/UsersShell.php:134 +msgid "Field: {0} Error: {1}" +msgstr "" + +#: Shell/UsersShell.php:152;178 +msgid "Please enter a password." +msgstr "" + +#: Shell/UsersShell.php:156 +msgid "Password changed for all users" +msgstr "" + +#: Shell/UsersShell.php:157;185 +msgid "New password: {0}" +msgstr "" + +#: Shell/UsersShell.php:175;203;281;321 +msgid "Please enter a username." +msgstr "" + +#: Shell/UsersShell.php:184 +msgid "Password changed for user: {0}" +msgstr "" + +#: Shell/UsersShell.php:206 +msgid "Please enter a role." +msgstr "" + +#: Shell/UsersShell.php:212 +msgid "Role changed for user: {0}" +msgstr "" + +#: Shell/UsersShell.php:213 +msgid "New role: {0}" +msgstr "" + +#: Shell/UsersShell.php:228 +msgid "User was activated: {0}" +msgstr "" + +#: Shell/UsersShell.php:243 +msgid "User was de-activated: {0}" +msgstr "" + +#: Shell/UsersShell.php:255 +msgid "Please enter a username or email." +msgstr "" + +#: Shell/UsersShell.php:263 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" + +#: Shell/UsersShell.php:300 +msgid "The user was not found." +msgstr "" + +#: Shell/UsersShell.php:329 +msgid "The user {0} was not deleted. Please try again" +msgstr "" + +#: Shell/UsersShell.php:331 +msgid "The user {0} was deleted successfully" +msgstr "" #: Template/Email/html/reset_password.ctp:21 #: Template/Email/html/social_account_validation.ctp:14 @@ -284,13 +475,10 @@ msgstr "Restablezca su contraseña aquí" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 msgid "" -"If the link is not correctly displayed, please copy the following address in " +"If the link is not correcly displayed, please copy the following address in " "your web browser {0}" msgstr "" -"Si el enlace no se muestra correctamente, por favor copie la siguiente " -"dirección en su navegador web {0}" #: Template/Email/html/reset_password.ctp:30 #: Template/Email/html/social_account_validation.ctp:35 @@ -309,6 +497,14 @@ msgstr "Active su acceso social aquí" msgid "Activate your account here" msgstr "Active su cuenta aquí" +#: 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 "" +"Si el enlace no se muestra correctamente, por favor copie la siguiente " +"dirección en su navegador web {0}" + #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" @@ -337,12 +533,12 @@ msgstr "Listar Usuarios" msgid "List Accounts" msgstr "Listar Cuentas" -#: Template/Users/add.ctp:22 Template/Users/register.ctp:15 +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 msgid "Add User" msgstr "Añadir Usuario" -#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:13 -#: Template/Users/edit.ctp:42 Template/Users/register.ctp:26 +#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:17 +#: Template/Users/edit.ctp:42 Template/Users/register.ctp:32 #: Template/Users/request_reset_password.ctp:8 #: Template/Users/resend_token_validation.ctp:20 #: Template/Users/social_email.ctp:19 @@ -353,7 +549,7 @@ msgstr "Enviar" msgid "Please enter the new password" msgstr "Por favor introduzca la nueva contraseña" -#: Template/Users/change_password.ctp:7 +#: Template/Users/change_password.ctp:10 msgid "Current password" msgstr "Contraseña actual" @@ -399,47 +595,51 @@ msgstr "siguiente" msgid "Please enter your username and password" msgstr "Por favor introduzca su usuario y contraseña" -#: Template/Users/login.ctp:26 +#: Template/Users/login.ctp:29 msgid "Remember me" msgstr "Recordarme" -#: Template/Users/login.ctp:49 +#: Template/Users/login.ctp:48 msgid "Login" msgstr "Ingresar" -#: Template/Users/profile.ctp:18 +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 msgid "{0} {1}" msgstr "{0} {1}" -#: Template/Users/profile.ctp:23 +#: Template/Users/profile.ctp:24 msgid "Change Password" msgstr "Cambiar contraseña" -#: Template/Users/profile.ctp:26 Template/Users/view.ctp:28;68 +#: Template/Users/profile.ctp:27 Template/Users/view.ctp:28;68 msgid "Username" msgstr "Usuario" -#: Template/Users/profile.ctp:28 Template/Users/view.ctp:30 +#: Template/Users/profile.ctp:29 Template/Users/view.ctp:30 msgid "Email" msgstr "Email" -#: Template/Users/profile.ctp:33 +#: Template/Users/profile.ctp:34 msgid "Social Accounts" msgstr "Cuentas sociales" -#: Template/Users/profile.ctp:37 Template/Users/view.ctp:70 +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:70 msgid "Avatar" msgstr "Avatar" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:67 +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:67 msgid "Provider" msgstr "Proveedor" -#: Template/Users/profile.ctp:39 +#: Template/Users/profile.ctp:40 msgid "Link" msgstr "Enlace" -#: Template/Users/register.ctp:23 +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "" + +#: Template/Users/register.ctp:25 msgid "Accept TOS conditions?" msgstr "¿Acepta las condiciones del servicios?" @@ -523,18 +723,50 @@ msgstr "Referencia" msgid "Data" msgstr "Datos" -#: View/Helper/UserHelper.php:43 -msgid "Sign in with Facebook" -msgstr "Ingresar con Facebook" +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "" -#: View/Helper/UserHelper.php:57 -msgid "Sign in with Twitter" -msgstr "Ingresar con Twitter" +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "" -#: View/Helper/UserHelper.php:71 +#: View/Helper/UserHelper.php:90 msgid "Logout" msgstr "Salir" -#: View/Helper/UserHelper.php:109 +#: View/Helper/UserHelper.php:139 msgid "Welcome, {0}" msgstr "Bienvenido, {0}" + +#: View/Helper/UserHelper.php:161 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" + +#~ msgid "SocialAccount already active" +#~ msgstr "Cuenta social ya activa" + +#~ msgid "" +#~ "The social account is not active. Please check your email for " +#~ "instructions. {0}" +#~ msgstr "" +#~ "La cuenta social está inactiva. Por favor, compruebe las instrucciones en " +#~ "su correo. {0}" + +#~ msgid "There was an error associating your social network account" +#~ msgstr "Hubo un error al asociar su cuenta de la red social" + +#~ msgid "Invalid token and/or email" +#~ msgstr "Token y/o email inválido" + +#~ msgid "The \"tos\" property is not present" +#~ msgstr "La propiedad \"tos\" no está presente" + +#~ msgid "+ {0} secs" +#~ msgstr "+ {0} secs" + +#~ msgid "Sign in with Facebook" +#~ msgstr "Ingresar con Facebook" + +#~ msgid "Sign in with Twitter" +#~ msgstr "Ingresar con Twitter" From 005da158c6dcdf94e8e4ce18824987eb0bf3fb02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Teixeira?= Date: Wed, 20 Apr 2016 09:52:15 -0300 Subject: [PATCH 0448/1476] Preparing sv localization file for future translations --- src/Locale/sv/Users.mo | Bin 12917 -> 12834 bytes src/Locale/sv/Users.po | 198 +++++++++++++++++++++++++---------------- 2 files changed, 121 insertions(+), 77 deletions(-) diff --git a/src/Locale/sv/Users.mo b/src/Locale/sv/Users.mo index 07925b46d0f1ae067550b7a334e34f0b255ca2b6..aafbf4428eee29c8ffcbcaf0581cf4738ff1e766 100644 GIT binary patch delta 3287 zcmY+^dr(wm7{~D!L@v9Fih`g>ZsLt(X%Ub>M7*Gxf}>(crML+yfuM*NAY02zUQ*Me zW{R4QF_Y7z4o+Ss`==(gQYX_XE2SA79V^Z0W*2Mv{&r7)bY`FZyyxtm_kG^yeb4!| zVt6^d5tKY%@{U$DoQe1LLsD zKKG*rUWcK$8I|Z(oQW;yV|?>B4aP9#^gbHvFd2{HqxdCipvbPllDkm}PeRS~Y1GVS zBCBC)Pzg1mCbSBb$a)-$TaeP5uh6f?bsCIeen55b4=PhvH)e~ms5Q^FeG-#6UxfY9 zLfv-~i}4H&$9T$Eilvx?hcE$eBOenQNBtkB5l`LpLk_Cr$*396$244n1MnC=g6*ip z9qdfq*9}#XRQr4gQdBb$1C>GbSA&CaC91NAyHkHRjc>W20Ydnfo`Muq$74{txEz&O z6ZXR$s3m(JRoe5Y0WYKecN3LR7@cS-J7I4ej6-oUYV&UN)6gz$L+&vbPy^gT%{-bN zsD$!RiIgEfnFb_hvjMfn2T)6J5Gjs1j{4tubmJ{d#Yj3)0$HdE`WMj9%$rbaz8|&L z2T_@ywY`HXWenM}ye0{GGEF*qumClITI8>0HL{J&KKuMAD&Y&Lfo~%J_nRMSXb(g% zP0b($b)Jpd-DT*)8CZbTsI_|=mFPFf$Na^Yo}L8iKMkj&Hsiaf#5(e4ElCop-vJn@ z=RcK(W}b!QVuqo1br~)WF=jccl=oRc{ochLoM9@ab3PVT@s7!sRrKv_e&lakKJ*fX3!W2A(>hKn7Y3`zC7|OFt z(?pKHDI)-A7eV&JPB}~PuI1nBEgJz&g_zd!7 znPyZ1+pq)=U?Kj2n&5EOF%5U3#yN``_o|9_hqY}A|kr>H_(9;ludZnkK1}dg5E@g)q$>!>CA4(Y;l;5{3L9%Qx5U}SYoDL#hH$dl5jDU))WA;a zu7n1mDpHPm%$A@^xB>MF-iICW2x`rbp(=LZTFls_V>C|0UW{+1 z(_qr33H5xoqHZ{WD&ZCEjMwl9yo=;ya+rqJcn)ew8Zir7(1#bX3^RF4DdCM6g{`P1 zJB)>z@i7_^_#vv}Pm%p-{=^Vek}BP1LPtU1o5WEaZL>x=x>YsM8cjS-=uoXj5etZM z#3Vwa>?U+*x2y@Yf(tj9_IUfe8E4t;*D%L!i919d0KyYaJ7aCZZFu&>H8QlC+YRjyj@|(B3a5GKe|W31@P@4YY<5 zI$jDASbsHNu+Lkp5LaUQ3eLvZSBh*G;S#$&0_WRpvC}GY#mDWXHJfk~T0R|%twvX3 z&K6oz0_VZ6ji7~JM!ZT?652@r9WT<@LF}^5xe~KB(b9h0N@#yCCuR`!gkC-Ds=%?H z?{$Q>(p)PkI==9^!1drJtf4)P=u3~(u{aF;xd`06;9D@I%Zb;{Db&zE_3I}suff{%T-j6FV0^2be zH=*v|hcS2%?f5B1FuplWLj(SVOx|3=zIYWi6ZNValCTfvT8^`>SE7p5fQh)mI^TpE zcsq8--Ka$0!g=^1x*6ZZ(JNz_MjVF$Ov5j6I9^62&_6z0awjTbH)^JJsF^KBR>QQQ z5^6_HXbUQl9XJv9Af-2dVnB_*X)uPli|U|PLO9cb_#o$lQENWYvIbK)Z^a?F7j@rp zoQgl-7|fuIGqDy6@H6a>w~>#DPo(~XXk<_~{ZNkTcs^>zYcK~pFawWaCSF4&p2W`7 zeQBtQjIz!rAk{T)|%(74V84bX>w=_x2cbzF(s#f_-M+A$s9 zLoHbs>i_3aCBB0ixH~uN{|TtXT&N{2!c?4#MHmRs&@MiL+N~FmKFnRzKz-SPsz4!X zATKJRHsmj6Hxf4}^cQFc2qSpKj zD)WCVlgLsfEk>5vOh%qiGY7MA5o!WEkXuYAvaL*)b$$_*@LgowfJtClx?vz{FXW+S zP-&feP`kVhV{rqPU5JkG*))TaCuHBK&n){;!d(DOf?hAQwR zYUcBiEx|@C#!gfMe_=Mp@QA2F1*n9}Q1_Rk5}bvq zR5fbm&8UP{q4q>uI`vm(-*Z8wJcr8sDyoD3P&dSqMHVLFP#kMnhpOOan zbUcgW(Z%{{g3B-mzeSDHEkJJ?I1#m3(ol~_8EUuAMwQry+8gVUoXqE_jxM7rU}pm; zkwMrKOHfZkIqKD3gBoYKb-fMMUtli{k~HU0uhvMu9!4iR(1S{>6&cICjY-&rYy)!z zHRD*`tGb?yJ#YkSsYWARn@WtpHOT6jR%EpU<^vidxzL3?q9%$u%XCzSWvB$^pb}e+ zs?0&u<8~ZX$_uDh@=c7y2sVh;-iE4RGO9vO)Px_!JjOT8G@M-6htYTzN8s-miz(Du z?}JQK<`YmI)u9G%MN&lQx*?Vn%$Qh zp0N$}RM=4+ry?8HOu=rrhR7pcC3KX8zKwYr)z8+T%a-6>N^2Z3iO`{1l@UIooOqnj zC_4!q+AS}HTH%Fzg7zcUc?(uq?G7xk+T!`(ew%&3W?GHJ3PRgSTWB<~J$TNRk^dsC zxrB~*qJfw}=(YG7p>@_#L98Tt5&mF7%(RqNS~?aJ&k%YBrV`qU3xe;*q@}+^tBBC? zT$s@MtEuJH@ka1QOtNbotqGy?@as*@W@5Q@trVA7ZLuRbI@X@Ji&ib+AhdismIb}B z$pt}L(?aLruT7wZUroG1)DYT8_l{?2Y$IL|eiECU|1vG@$1Q~R_gZ2O(M0GK#I6e+ z8~NTqXe)VxadGzXb)oCwO}L2mEMhP*mUxqBC-exeC#s2wgpO52J+Y8z>-5Ie*diON zyzctoT6_P_llI?w#N}qYMmk)1g)ZkXrz?2$f#fOouH@!%#p$$FxSRah(|zuSrh2!( z(O2l0QSbBCIi`Ja$W!gB^;I`GMlIEq5|6jm>vz}JH2NEBeeRm-hMcDA&Xm++F#|$l dmR40YE^Y8TeAOOzgTr0t_cr@Gf5|L~`X9UlUhDt> diff --git a/src/Locale/sv/Users.po b/src/Locale/sv/Users.po index b13668079..4f5da4c53 100644 --- a/src/Locale/sv/Users.po +++ b/src/Locale/sv/Users.po @@ -4,9 +4,9 @@ msgid "" msgstr "" "Project-Id-Version: Users\n" -"POT-Creation-Date: 2016-02-18 14:10+0100\n" -"PO-Revision-Date: 2016-02-18 14:24+0100\n" -"Last-Translator: Ulrik Södergren \n" +"POT-Creation-Date: 2016-04-20 09:50-0300\n" +"PO-Revision-Date: 2016-04-20 09:50-0300\n" +"Last-Translator: André Teixeira \n" "Language-Team: CakeDC \n" "Language: sv\n" "MIME-Version: 1.0\n" @@ -15,17 +15,41 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.8.7\n" -#: Auth/SimpleRbacAuthorize.php:133 +#: Auth/ApiKeyAuthenticate.php:55 +msgid "Type {0} is not valid" +msgstr "" + +#: Auth/ApiKeyAuthenticate.php:59 +msgid "Type {0} has no associated callable" +msgstr "" + +#: Auth/ApiKeyAuthenticate.php:68 +msgid "SSL is required for ApiKey Authentication" +msgstr "" + +#: Auth/SimpleRbacAuthorize.php:141 msgid "" "Missing configuration file: \"config/{0}.php\". Using default permissions" msgstr "" "Saknad konfigurationsfil: \"config / {0} .php\". Använder " "standardbehörigheter" -#: Auth/SocialAuthenticate.php:153 +#: Auth/SocialAuthenticate.php:410 msgid "Provider cannot be empty" msgstr "Leverantör kan inte vara tomt" +#: Auth/Rules/AbstractRule.php:77 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a " +"default table from the request" +msgstr "" + +#: Auth/Rules/Owner.php:67;70 +msgid "" +"Missing column {0} in table {1} while checking ownership permissions for " +"user {2}" +msgstr "" + #: Controller/SocialAccountsController.php:52 msgid "Account validated successfully" msgstr "Kontot har validerats" @@ -38,8 +62,8 @@ msgstr "Konto kunde inte valideras" msgid "Invalid token and/or social account" msgstr "Ogiltig token och / eller social konto" -#: Controller/SocialAccountsController.php:59 -msgid "SocialAccount already active" +#: Controller/SocialAccountsController.php:59;86 +msgid "Social Account already active" msgstr "SocialAccount redan aktivt" #: Controller/SocialAccountsController.php:61 @@ -58,10 +82,6 @@ msgstr "Epsot kunde inte skickas" msgid "Invalid account" msgstr "Ogiltigt konto" -#: Controller/SocialAccountsController.php:86 -msgid "Social Account already active" -msgstr "SocialAccount redan aktivt" - #: Controller/SocialAccountsController.php:88 msgid "Email could not be resent" msgstr "E-post kan inte skickas om" @@ -76,15 +96,15 @@ msgid "You can't enable email validation workflow if use_email is false" msgstr "" "Du kan inte aktivera epost-validering arbetsflöde om use_email är falskt" -#: Controller/Traits/LoginTrait.php:92 +#: Controller/Traits/LoginTrait.php:95 msgid "Issues trying to log in with your social account" msgstr "Problem vid inloggning med ditt sociala konto" -#: Controller/Traits/LoginTrait.php:96 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:100 Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "Lägg till din epost" -#: Controller/Traits/LoginTrait.php:102 +#: Controller/Traits/LoginTrait.php:106 msgid "" "Your user has not been validated yet. Please check your inbox for " "instructions" @@ -92,7 +112,7 @@ msgstr "" "Ditt konto har inte verifierats ännu. Vänligen kontrollera din inbox för " "instruktioner" -#: Controller/Traits/LoginTrait.php:104 +#: Controller/Traits/LoginTrait.php:108 msgid "" "Your social account has not been validated yet. Please check your inbox for " "instructions" @@ -100,45 +120,57 @@ msgstr "" "Din sociala hänsyn har inte validerats ännu. Vänligen kontrollera din inbox " "för instruktioner" -#: Controller/Traits/LoginTrait.php:177 +#: Controller/Traits/LoginTrait.php:157 Controller/Traits/RegisterTrait.php:73 +msgid "Invalid reCaptcha" +msgstr "" + +#: Controller/Traits/LoginTrait.php:165 +msgid "You are already logged in" +msgstr "" + +#: Controller/Traits/LoginTrait.php:209 msgid "Username or password is incorrect" msgstr "Användarnamn eller lösenord är felaktigt" -#: Controller/Traits/LoginTrait.php:198 +#: Controller/Traits/LoginTrait.php:230 msgid "You've successfully logged out" msgstr "Du har loggats ut" -#: Controller/Traits/PasswordManagementTrait.php:53 -msgid "Password has been changed successfully" -msgstr "Lösenordsbytet lyckades!" - -#: Controller/Traits/PasswordManagementTrait.php:56;63 +#: Controller/Traits/PasswordManagementTrait.php:53;60;68 msgid "Password could not be changed" msgstr "Lösenordet kunde inte ändras" -#: Controller/Traits/PasswordManagementTrait.php:59 +#: Controller/Traits/PasswordManagementTrait.php:57 +msgid "Password has been changed successfully" +msgstr "Lösenordsbytet lyckades!" + +#: Controller/Traits/PasswordManagementTrait.php:64 #: Controller/Traits/ProfileTrait.php:49 msgid "User was not found" msgstr "Användaren hittades inte." -#: Controller/Traits/PasswordManagementTrait.php:61 +#: Controller/Traits/PasswordManagementTrait.php:66 msgid "The current password does not match" msgstr "Den nuvarande lösenord matchar inte" -#: Controller/Traits/PasswordManagementTrait.php:102 +#: Controller/Traits/PasswordManagementTrait.php:108 msgid "Please check your email to continue with password reset process" msgstr "Kontrollera din epost för att fortsätta lösenordsåterställningen" -#: Controller/Traits/PasswordManagementTrait.php:105 Shell/UsersShell.php:266 +#: Controller/Traits/PasswordManagementTrait.php:111 Shell/UsersShell.php:266 msgid "The password token could not be generated. Please try again" msgstr "Lösenordstoken kunde inte skapas. Var god försök igen" -#: Controller/Traits/PasswordManagementTrait.php:110 +#: Controller/Traits/PasswordManagementTrait.php:116 #: Controller/Traits/UserValidationTrait.php:98 msgid "User {0} was not found" msgstr "Användaren {0} hittades inte" -#: Controller/Traits/PasswordManagementTrait.php:112 +#: Controller/Traits/PasswordManagementTrait.php:118 +msgid "The user is not active" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:120 #: Controller/Traits/UserValidationTrait.php:94;102 msgid "Token could not be reset" msgstr "Token kunde inte återställas" @@ -147,19 +179,15 @@ msgstr "Token kunde inte återställas" msgid "Not authorized, please login first" msgstr "Inte auktoriserad, vänligen logga in först" -#: Controller/Traits/RegisterTrait.php:74 Controller/Traits/SocialTrait.php:38 -msgid "The reCaptcha could not be validated" -msgstr "reCAPTCHA angavs inte korrekt" - -#: Controller/Traits/RegisterTrait.php:80 +#: Controller/Traits/RegisterTrait.php:79 msgid "The user could not be saved" msgstr "Användaren kunde inte sparas" -#: Controller/Traits/RegisterTrait.php:113 +#: Controller/Traits/RegisterTrait.php:111 msgid "You have registered successfully, please log in" msgstr "Din registrering är klar, vänligen logga in" -#: Controller/Traits/RegisterTrait.php:115 +#: Controller/Traits/RegisterTrait.php:113 msgid "Please validate your account before log in" msgstr "Vänligen validera ditt konto innan inloggning" @@ -179,6 +207,10 @@ msgstr "{0} har tagits bort" msgid "The {0} could not be deleted" msgstr "{0} kunde inte tas bort" +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "reCAPTCHA angavs inte korrekt" + #: Controller/Traits/UserValidationTrait.php:42 msgid "User account validated successfully" msgstr "Användarkontot har validerats" @@ -219,51 +251,56 @@ msgstr "Token har återställts. Kontrollera din e-post." msgid "User {0} is already active" msgstr "Användaren {0} är redan aktiv" -#: Model/Behavior/PasswordBehavior.php:42 +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Din länk för att validera kontot" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0} Din länk för att återställa lösenord" + +#: Mailer/UsersMailer.php:78 +msgid "{0}Your social account validation link" +msgstr "{0} Din sociala konto svalideringslänk" + +#: Model/Behavior/PasswordBehavior.php:56 msgid "Reference cannot be null" msgstr "Referens får inte vara null" -#: Model/Behavior/PasswordBehavior.php:47 +#: Model/Behavior/PasswordBehavior.php:61 msgid "Token expiration cannot be empty" msgstr "Giltighet för token kan inte vara tom" -#: Model/Behavior/PasswordBehavior.php:53 +#: Model/Behavior/PasswordBehavior.php:67;115 msgid "User not found" msgstr "Användaren hittades inte" -#: Model/Behavior/PasswordBehavior.php:95 -msgid "{0}Your reset password link" -msgstr "{0} Din länk för att återställa lösenord" +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:110 +msgid "User account already validated" +msgstr "Kontot är redan aktiverat!" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "" -#: Model/Behavior/PasswordBehavior.php:119 +#: Model/Behavior/PasswordBehavior.php:120 msgid "The old password does not match" msgstr "Det gamla lösenordet stämmer inte" -#: Model/Behavior/RegisterBehavior.php:65 -msgid "Your account validation link" -msgstr "Din länk för att validera kontot" - -#: Model/Behavior/RegisterBehavior.php:86 +#: Model/Behavior/RegisterBehavior.php:88 msgid "User not found for the given token and email." msgstr "Hittade ingen användare som matchar angivet token eller epost" -#: Model/Behavior/RegisterBehavior.php:89 +#: Model/Behavior/RegisterBehavior.php:91 msgid "Token has already expired user with no token" msgstr "Token har redan gått ut eller användare utan token" -#: Model/Behavior/RegisterBehavior.php:108 -msgid "User account already validated" -msgstr "Kontot är redan aktiverat!" - -#: Model/Behavior/SocialAccountBehavior.php:82 -msgid "{0}Your social account validation link" -msgstr "{0} Din sociala konto svalideringslänk" - -#: Model/Behavior/SocialAccountBehavior.php:109;136 +#: Model/Behavior/SocialAccountBehavior.php:101;128 msgid "Account already validated" msgstr "Kontot är redan aktiverat!" -#: Model/Behavior/SocialAccountBehavior.php:112;139 +#: Model/Behavior/SocialAccountBehavior.php:104;131 msgid "Account not found for the given token and email." msgstr "Kontot hittades inte för givet token och e-post." @@ -271,19 +308,19 @@ msgstr "Kontot hittades inte för givet token och e-post." msgid "Unable to login user with reference {0}" msgstr "Det går inte att logga in användaren med refrens {0}" -#: Model/Behavior/SocialBehavior.php:98 +#: Model/Behavior/SocialBehavior.php:97 msgid "Email not present" msgstr "Epost saknas" -#: Model/Table/UsersTable.php:80 +#: Model/Table/UsersTable.php:81 msgid "Your password does not match your confirm password. Please try again" msgstr "Dina lösenord matchar inte. Vänligen försök igen." -#: Model/Table/UsersTable.php:158 +#: Model/Table/UsersTable.php:159 msgid "Username already exists" msgstr "Användarnamnet är upptaget" -#: Model/Table/UsersTable.php:164 +#: Model/Table/UsersTable.php:165 msgid "Email already exists" msgstr "E-postadressen finns redan" @@ -415,14 +452,14 @@ msgstr "" msgid "The user was not found." msgstr "Användaren hittades inte." -#: Shell/UsersShell.php:327 -msgid "The user {0} was deleted successfully" -msgstr "Användaren {0} har tagits bort" - #: Shell/UsersShell.php:329 msgid "The user {0} was not deleted. Please try again" msgstr "Användaren {0} raderades ej. Var god försök igen" +#: Shell/UsersShell.php:331 +msgid "The user {0} was deleted successfully" +msgstr "Användaren {0} har tagits bort" + #: Template/Email/html/reset_password.ctp:21 #: Template/Email/html/social_account_validation.ctp:14 #: Template/Email/html/validation.ctp:21 @@ -498,15 +535,15 @@ msgstr "Lista användare" msgid "List Accounts" msgstr "Lista konton" -#: Template/Users/add.ctp:22 Template/Users/register.ctp:15 +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 msgid "Add User" msgstr "Ny användare" #: Template/Users/add.ctp:32 Template/Users/change_password.ctp:17 -#: Template/Users/edit.ctp:42 Template/Users/register.ctp:27 +#: Template/Users/edit.ctp:42 Template/Users/register.ctp:32 #: Template/Users/request_reset_password.ctp:8 #: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:20 +#: Template/Users/social_email.ctp:19 msgid "Submit" msgstr "Skicka" @@ -560,15 +597,15 @@ msgstr "nästa" msgid "Please enter your username and password" msgstr "Ange ditt användarnamn och lösenord" -#: Template/Users/login.ctp:26 +#: Template/Users/login.ctp:29 msgid "Remember me" msgstr "Kom ihåg mig" -#: Template/Users/login.ctp:55 +#: Template/Users/login.ctp:48 msgid "Login" msgstr "Loggin" -#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:63 +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 msgid "{0} {1}" msgstr "{0} {1}" @@ -604,7 +641,7 @@ msgstr "Länk" msgid "Link to {0}" msgstr "Länk till {0}" -#: Template/Users/register.ctp:23 +#: Template/Users/register.ctp:25 msgid "Accept TOS conditions?" msgstr "Jag accepterar villkoren" @@ -688,22 +725,29 @@ msgstr "Referens" msgid "Data" msgstr "Data" -#: View/Helper/UserHelper.php:62 +#: View/Helper/UserHelper.php:49 msgid "fa fa-{0}" msgstr "fa fa-{0}" -#: View/Helper/UserHelper.php:64 +#: View/Helper/UserHelper.php:52 msgid "btn btn-social btn-{0} " msgstr "btn btn-social btn-{0} " -#: View/Helper/UserHelper.php:77 +#: View/Helper/UserHelper.php:90 msgid "Logout" msgstr "Logga ut" -#: View/Helper/UserHelper.php:115 +#: View/Helper/UserHelper.php:139 msgid "Welcome, {0}" msgstr "Välkommen, {0}" +#: View/Helper/UserHelper.php:161 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" + +#~ msgid "SocialAccount already active" +#~ msgstr "SocialAccount redan aktivt" + #~ msgid "There was an error associating your social network account" #~ msgstr "Det gick inte att associera ditt sociala nätverkskonto" From 95744169529c26670324451afcc450f6e677fd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 20 Apr 2016 14:50:04 +0100 Subject: [PATCH 0449/1476] Update Home.md --- Docs/Home.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Home.md b/Docs/Home.md index 4250dea39..fc5bc4658 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -28,3 +28,4 @@ Documentation * [UserHelper](Documentation/UserHelper.md) * [Events](Documentation/Events.md) * [Extending the Plugin](Documentation/Extending-the-Plugin.md) +* [Translations](Documentation/Translations.md) From 5d7ec8e337cede1ee0daab62b5c2713f423fb74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 20 Apr 2016 14:59:42 +0100 Subject: [PATCH 0450/1476] Create Translations.md --- Docs/Documentation/Translations.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Docs/Documentation/Translations.md diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md new file mode 100644 index 000000000..aad67deb0 --- /dev/null +++ b/Docs/Documentation/Translations.md @@ -0,0 +1,9 @@ +Translations +============ + +The Plugin is translated into several languages: + +* Swedish (sv) by @digitalfotografen +* Spanish (es) by @florenciohernandez +* Brazillian Portuguese (pt_BR) by @andtxr + From 5e3107d4fe1097b4d13f354f589ea163f1daee1c Mon Sep 17 00:00:00 2001 From: Maicon Amarante Date: Mon, 25 Apr 2016 09:23:58 -0300 Subject: [PATCH 0451/1476] Enable Stateless Authentication following http://book.cakephp.org/3.0/en/controllers/components/authentication.html#creating-stateless-authentication-systems --- src/Auth/ApiKeyAuthenticate.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index e667d29bb..51d279ac8 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -49,6 +49,24 @@ class ApiKeyAuthenticate extends BaseAuthenticate * @return mixed */ public function authenticate(Request $request, Response $response) + { + return $this->getUser($request); + } + + /** + * Stateless Authentication System + * http://book.cakephp.org/3.0/en/controllers/components/authentication.html#creating-stateless-authentication-systems + * + * Config: + * $this->Auth->config('storage', 'Memory'); + * $this->Auth->config('unauthorizedRedirect', 'false'); + * $this->Auth->config('checkAuthIn', 'Controller.initialize'); + * $this->Auth->config('loginAction', false); + * + * @param Request $request Cake request object. + * @return mixed + */ + public function getUser(Request $request) { $type = $this->config('type'); if (!in_array($type, $this->types)) { From 636a7658398d10f53c06537083f1151d3148e3c2 Mon Sep 17 00:00:00 2001 From: Maicon Amarante Date: Mon, 25 Apr 2016 09:24:20 -0300 Subject: [PATCH 0452/1476] How to enable Stateless Authentication --- Docs/Documentation/ApiKeyAuthenticate.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Docs/Documentation/ApiKeyAuthenticate.md b/Docs/Documentation/ApiKeyAuthenticate.md index 9befe32b2..80f331c4c 100644 --- a/Docs/Documentation/ApiKeyAuthenticate.md +++ b/Docs/Documentation/ApiKeyAuthenticate.md @@ -27,3 +27,11 @@ $config['Auth']['authenticate']['CakeDC/Users.ApiKey'] = [ ]; ``` +In order to allow stateless authentication, enable these configuration: + +```php + $this->Auth->config('storage', 'Memory'); + $this->Auth->config('unauthorizedRedirect', 'false'); + $this->Auth->config('checkAuthIn', 'Controller.initialize'); + $this->Auth->config('loginAction', false); +``` \ No newline at end of file From 88dafece53f85e905f69c1c5978c44c609818902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Mon, 25 Apr 2016 16:34:30 +0100 Subject: [PATCH 0453/1476] Fix validation string to be able to have translations --- src/Locale/Users.pot | 3 +++ src/Locale/es/Users.mo | Bin 9650 -> 9713 bytes src/Locale/es/Users.po | 6 +++++- src/Model/Behavior/RegisterBehavior.php | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 3efabc9f5..8c48fb11f 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -532,3 +532,6 @@ msgstr "" msgid "Welcome, {0}" msgstr "" +#: Model/Behavior/RegisterBehavior.php:147 +msgid "This field is required" +msgstr "" diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo index 421ce4ba1bf00309b9e9566221553c1181222840..a6b1929d8213292857f5d16805d83bd9bb6b945a 100644 GIT binary patch delta 2391 zcmX}te@s;#^1x<)@f}6tHEP5Fv#zB_osz+)`1l7&zG7TIE)2 zWjC6-mZRFJ=3IHJ85>(pa&EM#fAn)J`$0dp+Q{`siZy$GxTnte-q&-Ud(QKGpYM6j z z@0f>)H<;asg}4ycqSq{JwKRNmY{2E%;$AR_x*_cP0&3u6n1`KXH3V;%Nj z8;)Z&UPoP5O_oZe4NI{P3-L7!ub^?3h9@Z(CX#xe}xO*o2~ zcmh@8Db&PY;WGRS8Pakov-VgCYM~A3)L#>}(Ba2+ROv=gn`R7a@H95#KbV6}8L@$a zsFFW}N@NVRNhfd}UUbis7sV=EfE3k=PzkSHME!MR6CK6ajhZlms>pd%slG&&UdvO0 zUe{veE8B!r+q$p>L&)4VhDz{#RAT2*MqnC>A>MQDuvqA9#*Y|g;QxL(>17pH)0ibqn_b0 z)WDO-y>`~^{|3q3uA!b~8t;^zaTe;47Ge=rpuTTMRcgEI{#bw5o~5A#4x!$HH&GM5 zgX|lNq6U~km3SI;-Pfr5zC$JYCu+s%)SH~F1eMS|sQ!mgpyOPGY!* z#swPnn4A||X%n)qY&Yu0r%=1~2rAL{P?h@J?f(T;iR-A%x6p}Qmx|ilm8gYn#s(Zj zRpg9A{q;pISCNC&qcZD2J;M>y#IIl_o^a29K$Uh5^|ojbei|$V9n8b!SdaH&52_;X zqAE6ls?3%AaO^ek@KWDK$4b;dt*8ogV>J%D=O3aH{S>qDH`Iy~D2w`2(7|H#U=wOj zv|u}SVg*j3gR@mMwBod7X7^($&ObZUCOU|k;6+@4hf&Y?Oyo#nPTWxBgT#XHR?f8n zbvzMc{{M%X`v_hCAfcb`Mj}A85t^@?*hM%*Goi;lNNglj5I>=c>DWdD=UcIlKIq|> z!v<(15LHA9p+k>L&-h_tHKE7YL1;0pL~rDIZ%+2(wC*Fi2-R6f3$Y_|+FRxe(dsAm zN3MG7a(B}zCv-eOl+Cwdb$u+d*;na%lpgKpJ&{AcGXHj3oy30!Z_)pUe(N8JeDBMO z+Z(y+%Zu9?%}$!}X7&a{PIoY{v&*5;AJ{t(><@HBuVtL`cvs!-RIFK7SstBU@<&qE c-JyK}XGiC*J$+6fc4eSH*wq)E@L%!#3(W2B=>Px# delta 2329 zcmX}te@xVM9LMqZ@$>E!m0uzOar_WCQx1XxVdvr2hIK9mmPCeVL@7$7rn0EMtz>PM zHFhieLuyX{09Ok;b91#NTRPjC&P})6Sn5_|v7FjkHrF3LUw7a7?%wzKe82boem?Kd z`}6t2-RM_Q=jWWXkBno4C?;l8&5q%bOujg3{APSC$k$SA#6pbXgE)Y7c)&gX8ujQE zd;n*$6z}0;ELdQcfz{|WbF7wzj|)v$g=^g#wxJ#vc6Cr4e~3%)Fs9)os>3gkkDYR_ zpGEb14%6`x=HXS;1m>}T@hxqkSvD7nU2Cy`^EM=Ddj>T?Kc?UyZp9%~f|u|yypEc2 zWtLe5Mo|6qqY@cKB|L_F>>yu$#r;!rb->#lT$qM+fgzGt|iq&BR zyRjP&<7&K(x-UqUN~9fYu@9^919VoNR=#|6LpY{4`C2P_%trV zG0ewLQ6)Zw8u$lXj&n#?mPMJh$4XEWZONwo8gMNa$}oy5-4JTijAJXF#16cLMHtRW zcGQC^`94%4S%P|4JGWE@+^gs7g$tN^}yn>8_y? zyXl(FG-+B8sj`J}6|P6dve!_F9YQ5EiR$+|R3$HJTDDpZWx8_oE-hc!oS=2=G9#O6?mI*X};Ixfd%jG)$T z1l94!$g}pDd;K($vt2>0;cuw5y@Ogxy<0)>qkeBhRjSps!@b^*B;eQ}4Xx1|r~%(W z_KUrb>RQB-1YqXryD4R92d=n3q>X;kU`lv$fFAJtCrmDYFv$B_k2Gp!9%D$@i}Uy=iTcUF~IpPOvOb^Uwa`3 zH(@!}YXK{OMz}MjGqos{J96Ra@m2IW9h4}B_?fL&$Nvk(@*H_?qCFb*& kdUnKv{$ITD%G~p*-ug!Z^-V2}P4PdL-toupm)%SK7w\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -538,3 +538,7 @@ msgstr "Salir" #: View/Helper/UserHelper.php:109 msgid "Welcome, {0}" msgstr "Bienvenido, {0}" + +#: Model/Behavior/RegisterBehavior.php:147 +msgid "This field is required" +msgstr "Este campo es requerido" diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 36bc66688..f42f43aad 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -144,7 +144,7 @@ protected function _emailValidator(Validator $validator, $validateEmail) $this->validateEmail = $validateEmail; $validator ->add('email', 'valid', ['rule' => 'email']) - ->notEmpty('email', 'This field is required', function ($context) { + ->notEmpty('email', __d('Users', 'This field is required'), function ($context) { return $this->validateEmail; }); return $validator; From 19508350e0df72f7307d24eeadaeb38645bad541 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 29 Apr 2016 09:28:57 -0500 Subject: [PATCH 0454/1476] Improve coverage --- tests/Fixture/UsersFixture.php | 16 +++--- .../Traits/PasswordManagementTraitTest.php | 50 +++++++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 4521f5270..1577a0783 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -151,19 +151,19 @@ class UsersFixture extends TestFixture ], [ 'id' => '00000000-0000-0000-0000-000000000006', - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', + 'username' => 'user-6', + 'email' => '6@example.com', + 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + 'first_name' => 'first-user-6', + 'last_name' => 'firts name 6', + 'token' => 'token-6', 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', + 'api_token' => '', 'activation_date' => '2015-06-24 17:33:54', 'tos_date' => '2015-06-24 17:33:54', 'active' => true, 'is_superuser' => false, - 'role' => 'Lorem ipsum dolor sit amet', + 'role' => 'user', 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54' ], diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index bbd83d76c..b7c97c036 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -92,6 +92,56 @@ public function testChangePasswordWithError() $this->Trait->changePassword(); } + /** + * test + * + * @return void + */ + public function testChangePasswordWithSamePassword() + { + $this->assertEquals('$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + $this->table->get('00000000-0000-0000-0000-000000000006')->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->will($this->returnValue([ + 'current_password' => '12345', + 'password' => '12345', + 'password_confirm' => '12345', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('You cannot use the current password as the new one'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithWrongCurrentPassword() + { + $this->assertEquals('$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + $this->table->get('00000000-0000-0000-0000-000000000006')->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->will($this->returnValue([ + 'current_password' => 'wrong-password', + 'password' => '12345', + 'password_confirm' => '12345', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The current password does not match'); + $this->Trait->changePassword(); + } + /** * test * From 17be3984a296103a0a51596424393a9a0d2c9afa Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 29 Apr 2016 09:55:46 -0500 Subject: [PATCH 0455/1476] Fix PHP Cs --- .../Traits/PasswordManagementTraitTest.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index b7c97c036..523eb2820 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -99,8 +99,10 @@ public function testChangePasswordWithError() */ public function testChangePasswordWithSamePassword() { - $this->assertEquals('$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', - $this->table->get('00000000-0000-0000-0000-000000000006')->password); + $this->assertEquals( + '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + $this->table->get('00000000-0000-0000-0000-000000000006')->password + ); $this->_mockRequestPost(); $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); @@ -124,8 +126,10 @@ public function testChangePasswordWithSamePassword() */ public function testChangePasswordWithWrongCurrentPassword() { - $this->assertEquals('$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', - $this->table->get('00000000-0000-0000-0000-000000000006')->password); + $this->assertEquals( + '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + $this->table->get('00000000-0000-0000-0000-000000000006')->password + ); $this->_mockRequestPost(); $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); From 5d6ca8a372c49b1bdc592b82cf10f7d0fe8b813a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 4 May 2016 23:10:28 +0100 Subject: [PATCH 0456/1476] remove deprecated findAllBy --- src/Model/Behavior/PasswordBehavior.php | 2 +- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 726927875..b5a17ab78 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -95,7 +95,7 @@ public function resetToken($reference, array $options = []) */ protected function _getUser($reference) { - return $this->_table->findAllByUsernameOrEmail($reference, $reference)->first(); + return $this->_table->findByUsernameOrEmail($reference, $reference)->first(); } /** diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 18b4c3290..c864aa211 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -69,7 +69,7 @@ public function tearDown() */ public function testResetToken() { - $user = $this->table->findAllByUsername('user-1')->first(); + $user = $this->table->findByUsername('user-1')->first(); $token = $user->token; $this->Behavior->Email->expects($this->never()) ->method('sendResetPasswordEmail') @@ -89,7 +89,7 @@ public function testResetToken() */ public function testResetTokenSendEmail() { - $user = $this->table->findAllByUsername('user-1')->first(); + $user = $this->table->findByUsername('user-1')->first(); $token = $user->token; $tokenExpires = $user->token_expires; $this->Behavior->Email->expects($this->once()) @@ -134,7 +134,7 @@ public function testResetTokenNotExistingUser() */ public function testResetTokenUserAlreadyActive() { - $activeUser = TableRegistry::get('CakeDC/Users.Users')->findAllByUsername('user-4')->first(); + $activeUser = TableRegistry::get('CakeDC/Users.Users')->findByUsername('user-4')->first(); $this->assertTrue($activeUser->active); $this->table = $this->getMockForModel('CakeDC/Users.Users', ['save']); $this->table->expects($this->never()) @@ -154,7 +154,7 @@ public function testResetTokenUserAlreadyActive() */ public function testResetTokenUserNotActive() { - $user = TableRegistry::get('CakeDC/Users.Users')->findAllByUsername('user-1')->first(); + $user = TableRegistry::get('CakeDC/Users.Users')->findByUsername('user-1')->first(); $this->Behavior->resetToken('user-1', [ 'ensureActive' => true, 'expiration' => 3600 From 1413cfc85d2f997a8ba762364239f07842dc3cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 4 May 2016 23:28:57 +0100 Subject: [PATCH 0457/1476] improving coverage --- .../TestCase/Model/Behavior/PasswordBehaviorTest.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index c864aa211..46de31714 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -115,6 +115,17 @@ public function testResetTokenWithNullParams() $this->Behavior->resetToken(null); } + /** + * Test resetTokenNoExpiration + * + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Token expiration cannot be empty + */ + public function testResetTokenNoExpiration() + { + $this->Behavior->resetToken('ref'); + } + /** * Test resetToken * From 566339c9563337baf3f372b2348dd3ccea832ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Fri, 3 Jun 2016 17:46:26 +0100 Subject: [PATCH 0458/1476] refs #303 add custom finder to log in using either username or email --- README.md | 2 +- composer.json | 2 +- config/users.php | 4 ++-- src/Model/Table/UsersTable.php | 24 +++++++++++++++++++++++- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 54bd0a84a..1940faa42 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.2+ +* CakePHP 3.2.9+ * PHP 5.5.9+ Documentation diff --git a/composer.json b/composer.json index 0102ca750..756639eb0 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "~3.2" + "cakephp/cakephp": ">=3.2.9 <4.0.0" }, "require-dev": { "phpunit/phpunit": "*", diff --git a/config/users.php b/config/users.php index 52fa057ee..172c13d41 100644 --- a/config/users.php +++ b/config/users.php @@ -91,7 +91,7 @@ ] ], ], -//default configuration used to auto-load the Auth Component, override to change the way Auth works + //default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ 'loginAction' => [ 'plugin' => 'CakeDC/Users', @@ -101,7 +101,7 @@ ], 'authenticate' => [ 'all' => [ - 'finder' => 'active', + 'finder' => 'auth', ], 'CakeDC/Users.ApiKey', 'CakeDC/Users.RememberMe', diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 7eac44ee3..da54831f5 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -178,7 +178,29 @@ public function buildRules(RulesChecker $rules) */ public function findActive(Query $query, array $options = []) { - $query->where(["{$this->_alias}.active" => 1]); + $query->where([$this->aliasField('active') => 1]); + return $query; + } + + /** + * Custom finder to log in users + * + * @param Query $query Query object to modify + * @param array $options Query options + * @return Query + * @throws \BadMethodCallException + */ + public function findAuth(Query $query, array $options = []) + { + $identifier = Hash::get($options, 'username'); + if (empty($identifier)) { + throw new \BadMethodCallException(__d('Users', 'Missing \'username\' in options data')); + } + + $query + ->orWhere([$this->aliasField('email') => $identifier]) + ->find('active', $options); + return $query; } } From f0f5dda9d5bcb02bb7627fbc1b98defafad35e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Mon, 6 Jun 2016 09:52:34 +0100 Subject: [PATCH 0459/1476] refs #303 added unit tests for finder auth --- src/Locale/Users.pot | 6 +++- src/Locale/es/Users.mo | Bin 8934 -> 9035 bytes src/Locale/es/Users.po | 6 +++- tests/TestCase/Model/Table/UsersTableTest.php | 32 ++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 2efe2c07e..61e6c7acc 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -309,6 +309,10 @@ msgstr "" msgid "Email already exists" msgstr "" +#: Model/Table/UsersTable.php:197 +msgid "Missing \'username\' in options data" +msgstr "" + #: Shell/UsersShell.php:54 msgid "Utilities for CakeDC Users Plugin" msgstr "" @@ -729,4 +733,4 @@ msgstr "" #: View/Helper/UserHelper.php:161 msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" +msgstr "" \ No newline at end of file diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo index b5a47db8fb6c5722299eb21d3248b5ca82af35ad..ffe80c6b57938b0790c026bbef1c06b602649ec1 100644 GIT binary patch delta 2558 zcmYk;drXye9LMpWh$Oc_F3};;Cqa(f4%a*qF{yfjmt>4b~dHtT>d7j_> zci>*j7pvTFbCQo5(jYOL7@uy;F|2%y3+Yg*F;Cza2JjTl!HXEeoAy2}%^1B>hJ{#z zbFl-nZ~#+q1ZU#w$g8e7Os15Ax9kI#Q7>Gx-au9SJ!a$2n2i6TDojc@hL1_*qVjyC zVpE7Sumtn495sM27T`9VMf+yZ%g`hH#Zjbg^FFG93z&pgFoIW69W2Q(W+m2QG44lI z{5Gls=TRNHf|+;?Rqt1*j@`l(+Be^knTPkW6*GBSQ`BkQftrC{EW!k8#@@g%p2IEp z2R35Is0^tiVyM#fMZ*p`EBbaR8U%csBF@6q(x;X!AWpZJxj^zkyoR=39%JvL0lR zrXTZhAF3lquo6$BD!zdlSayy-;s9y}SD-r5W{u@A|G5;rNddEB-o+|BhkVQw7j@`Q zR7bLTSQQ6RGZVt6aW!hK`;k>N32ep@tj5czQ}YXIpc(8)?VU20j9!eRDjq`hbObds z2T*H$3QtZm<}=h9zD#e_!6T>&-@yj_2(=`Cqw342mt@TxRCygzh1rN&B6klNtyu!K zRxXy|n0;UZ>9o0M{nD0Cp*rv*YH1##8cbq6SVfbLYG5{MW{XkJEkeE5fON<;?PN64 zKICH#a#4p)+VV4~iatj*a2<6VzrjAdg=(;s!`*~i(ZOS=5nn(JY!X$^ZB&PTz$~5r zzsRWK6c$=N%tFmTK5oM>>f9bjZN70-g=et@FQJa_9qh(rM$?5o7{;rp`jS{D?SV>M zj_p`Q`({iT`~X$)T~vd=q1Ngjd!NN{G@?Q-OR)i)aTpyukF0{3M0M;})Xe14szzRd z+FKQiCI4)d?w+(p3xJcz334C;J;jEy*H@3ZN)I#!CTnrT6esN0tJB9EF; zyNOXg6AnXgzD+ns6BB9)xdo$$KO#)Rm88zG}J~? zdWq18H|d7dPwet?998TgRDUheODJt83TWS3i*}We77;tVoIiESzGCm2a0AgoX!?~l z`gm83RQn=9XxWt35zi6YfNUdgR=`WGTwR^TB>&#DA)D3gA=VNsn>St0qNbg}dp{;y zaDZ4sJW9*S=qFgSr@s~R3H@&9#Bf5rq%~hp^!c}1V%J-5-D{d-_KQ`h9sDSDlL^}! zErXV3F~N!Rc6JADCUz4_5g+d#6dmC;_Pz^~iB6)9SfKO2lT4J@ODM&OW@T(zi1kE} z&}L-my|lvm3=R_M_FfxJdt@uoV9Tme8&=0rNymDbGMbu|%8+!F9A!u^OvF-S(+h*I z4Mks#M`F>S(-(IVdx!fH@gb)tG8~z>o>4S2v%V@+?}Qqc)P*WSH4_i=?j{%i@0DoW W8Ay1K>l)?#-Mk+inz$LrO#Kf#jN+RB delta 2470 zcmYk-eN5F=9LMpm7ra8{{=sUcYpv(aRc@}{pZhy^>x}Pxo!_~?dmg^$ z{C@D4N0tr9azj1`gmXd>!w_(-_Awcl{^oC%Jc-72qr^ z#sp5o4H(3&n1wr$pLq5nmH9Nh;%*p5{b0m-8P)Npn1fd_6K|k8{0Z;IKV17Aq+<)v zI2l8jhY{2Q%J3d+z+A?+u2h8?xi9u1eb^9cfKwR2B=+JN)C5Bzvqmh!66{5FJcydW zanwYU7{(D)zn4%G`xt|aZ{t)};+Lq@6mYjJL9Kid&c*~PQ*Bs>d$1GV!y3$;>fhIj znn)j3;(jc{bGQJ%LG_=(Dm=|JL`A8cfh^9-P#sj`LTtqtzJxO|iJH(ySc((KpJmdC zGM0zxw-A+?Qq);!!R6S8g*co;{&ncaXwadVKn?H@>d-}U{Zy4Bi?kT#V=d~wc3gzJ zP#qsZt?U|V#S^Fu1|$ANraG%|I_(`1@=rEw2Mrat2l=xkADYl5)I_eKI{q1znOisq z!}Ov(jv>2e39QEkjNxmjr{z3qphC)8XWzT_+ejBSli6#FDo|VIC8%hx8nGPLxf@yn^hSeU2L7J5*+WMBVon>UVcg6U|}&Sg2=}RJ50?`Ou8E_+Quy zsE*!34R9Fs7@ovFJdGMK#6$fM&c-NqqXyWATG&xkKf|aAjiAPPAG7rQk5kbMuVNQo zM?I$r4uB3_9jc?XI1f8M?>!V3~D78a5;X3^*D{jD6U7cX#=Q1z1)Wm_%m57;Eue)B=A& z9pb<7K8!}mzdCA(`p@-7tl@gVUB82jWn;*$*te(^-A1(sSQb^AgZ$sJ6{x*!#*Ns4 z_v3kt;t!|=PG;5Xuw<_1&-8g3bjbFi1{lNz_$F$vF5)C?CAJfFL<{iyL32r z5SxfF(MG8B_}Et5>FVuHZL5m5)vez@)w+C8ACx784p6#OQqdEkH{$\n" "Language-Team: CakeDC \n" "Language: es_ES\n" @@ -326,6 +326,10 @@ msgstr "Nombre de usuario ya existente" msgid "Email already exists" msgstr "Email ya existente" +#: Model/Table/UsersTable.php:197 +msgid "Missing 'username' in options data" +msgstr "Falta 'username' en los datos de opciones" + #: Shell/UsersShell.php:54 msgid "Utilities for CakeDC Users Plugin" msgstr "" diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index e316eebe5..b7f4459f3 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -324,4 +324,36 @@ public function testFindActive() $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); } + + /** + * Test findAuth method. + * + * @expectedException \BadMethodCallException + * @expectedExceptionMessage Missing 'username' in options data + */ + public function testFindAuthBadMethodCallException() + { + $user = $this->Users->find('auth'); + } + + /** + * Test findAuth method. + * + * @expected + */ + public function testFindAuth() + { + $user = $this->Users + ->find('auth', ['username' => 'not-exist@email.com']) + ->toArray(); + $this->assertEmpty($user); + + $user = $this->Users + ->find('auth', ['username' => 'user-2@test.com']) + ->first() + ->toArray(); + + $this->assertSame('00000000-0000-0000-0000-000000000002', Hash::get($user, 'id')); + $this->assertSame('user-2', Hash::get($user, 'username')); + } } From 05298923f1592cb4375e01b48868eebb9bae918c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Thu, 16 Jun 2016 13:07:46 +0100 Subject: [PATCH 0460/1476] refs #374 added not empty validation for current_password --- .../Traits/PasswordManagementTrait.php | 7 +++++- src/Model/Table/UsersTable.php | 14 +++++++++++ .../Traits/PasswordManagementTraitTest.php | 23 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 9807df795..6f7bcd62a 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -15,6 +15,7 @@ use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; use Cake\Core\Configure; +use Cake\Validation\Validator; use Exception; /** @@ -48,7 +49,11 @@ public function changePassword() $this->set('validatePassword', $validatePassword); if ($this->request->is('post')) { try { - $user = $this->getUsersTable()->patchEntity($user, $this->request->data(), ['validate' => 'passwordConfirm']); + $validator = $this->getUsersTable()->validationPasswordConfirm(new Validator()); + if (!empty($id)) { + $validator = $this->getUsersTable()->validationCurrentPassword($validator); + } + $user = $this->getUsersTable()->patchEntity($user, $this->request->data(), ['validate' => $validator]); if ($user->errors()) { $this->Flash->error(__d('Users', 'Password could not be changed')); } else { diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index da54831f5..ad045cf83 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -86,6 +86,20 @@ public function validationPasswordConfirm(Validator $validator) return $validator; } + /** + * Adds rules for current password + * + * @param Validator $validator Cake validator object. + * @return Validator + */ + public function validationCurrentPassword(Validator $validator) + { + $validator + ->notEmpty('current_password'); + + return $validator; + } + /** * Default validation rules. * diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 523eb2820..f49051f31 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -119,6 +119,29 @@ public function testChangePasswordWithSamePassword() $this->Trait->changePassword(); } + /** + * test + * + * @return void + */ + public function testChangePasswordWithEmptyCurrentPassword() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('data') + ->will($this->returnValue([ + 'current_password' => '', + 'password' => '54321', + 'password_confirm' => '54321', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Password could not be changed'); + $this->Trait->changePassword(); + } + /** * test * From 4fd1ca9f3ed3f339d6deb05b246f867619e92a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Thu, 16 Jun 2016 14:38:08 +0100 Subject: [PATCH 0461/1476] refs #381 updated deprecated methods from phpunit --- .../TestCase/Auth/ApiKeyAuthenticateTest.php | 9 ++--- .../Auth/RememberMeAuthenticateTest.php | 9 ++--- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 18 ++++----- .../TestCase/Auth/SocialAuthenticateTest.php | 17 ++++---- .../TestCase/Auth/SuperuserAuthorizeTest.php | 9 ++--- .../Component/UsersAuthComponentTest.php | 8 +++- .../Traits/CustomUsersTableTraitTest.php | 7 ++-- .../Controller/Traits/RecaptchaTraitTest.php | 20 ++++++++-- .../Controller/Traits/SocialTraitTest.php | 40 +++++++++++++------ tests/TestCase/Shell/UsersShellTest.php | 11 +++-- tests/TestCase/View/Helper/UserHelperTest.php | 22 +++++++--- 11 files changed, 104 insertions(+), 66 deletions(-) diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php index 3008c98ce..90a95c28e 100644 --- a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -38,11 +38,10 @@ public function setUp() $request = new Request(); $response = new Response(); - $controller = $this->getMock( - 'Cake\Controller\Controller', - null, - [$request, $response] - ); + $controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); $registry = new ComponentRegistry($controller); $this->apiKey = new ApiKeyAuthenticate($registry, ['require_ssl' => false]); } diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php index 150e00f37..4a5eb09b7 100644 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -41,11 +41,10 @@ public function setUp() $request = new Request(); $response = new Response(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - null, - [$request, $response] - ); + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); $registry = new ComponentRegistry($this->controller); $this->rememberMe = new RememberMeAuthenticate($registry); } diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index 7f84f7878..e654e59cf 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -63,11 +63,10 @@ public function setUp() $request = new Request(); $response = new Response(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - null, - [$request, $response] - ); + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); $this->registry = new ComponentRegistry($this->controller); } @@ -112,11 +111,10 @@ public function testLoadPermissions() */ public function testConstructMissingPermissionsFile() { - $this->simpleRbacAuthorize = $this->getMock( - 'CakeDC\Users\Auth\SimpleRbacAuthorize', - null, - [$this->registry, ['autoload_config' => 'does-not-exist']] - ); + $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') + ->setMethods(null) + ->setConstructorArgs([$this->registry, ['autoload_config' => 'does-not-exist']]) + ->getMock(); //we should have the default permissions $this->assertEquals($this->defaultPermissions, $this->simpleRbacAuthorize->config('permissions')); } diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index 80e40ab20..95df2ed87 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -50,11 +50,10 @@ public function setUp() ->disableOriginalConstructor() ->getMock(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - ['failedSocialLogin'], - [$request, $response] - ); + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(['failedSocialLogin']) + ->setConstructorArgs([$request, $response]) + ->getMock(); $this->Request = $request; $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', '_getProviderName', @@ -178,7 +177,9 @@ public function testGetUserSessionData() $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', '_getProviderName', '_mapUser', '_touch', '_validateConfig' ]); - $session = $this->getMock('Cake\Network\Session', ['read', 'delete']); + $session = $this->getMockBuilder('Cake\Network\Session') + ->setMethods(['read', 'delete']) + ->getMock(); $session->expects($this->once()) ->method('read') ->with('Users.social') @@ -188,7 +189,9 @@ public function testGetUserSessionData() ->method('delete') ->with('Users.social'); - $this->Request = $this->getMock('Cake\Network\Request', ['session']); + $this->Request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['session']) + ->getMock(); $this->Request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php index bde73f341..29d12d1b9 100644 --- a/tests/TestCase/Auth/SuperuserAuthorizeTest.php +++ b/tests/TestCase/Auth/SuperuserAuthorizeTest.php @@ -36,11 +36,10 @@ public function setUp() $request = new Request(); $response = new Response(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - null, - [$request, $response] - ); + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); $registry = new ComponentRegistry($this->controller); $this->superuserAuthorize = new SuperuserAuthorize($registry); } diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 3138bb384..7baae563a 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -59,9 +59,13 @@ public function setUp() ]); Security::salt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); Configure::write('App.namespace', 'Users'); - $this->request = $this->getMock('Cake\Network\Request', ['is', 'method']); + $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->getMock('Cake\Network\Response', ['stop']); + $this->response = $this->getMockBuilder('Cake\Network\Response') + ->setMethods(['stop']) + ->getMock(); $this->Controller = new Controller($this->request, $this->response); $this->Registry = $this->Controller->components(); $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); diff --git a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php index 90f142699..89c000651 100644 --- a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php +++ b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php @@ -19,10 +19,9 @@ class CustomUsersTableTraitTest extends TestCase public function setUp() { parent::setUp(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - ['header', 'redirect', 'render', '_stop'] - ); + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(['header', 'redirect', 'render', '_stop']) + ->getMock(); $this->controller->Trait = $this->getMockForTrait('CakeDC\Users\Controller\Traits\CustomUsersTableTrait'); } diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php index 655e83c18..8ce79ab38 100644 --- a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php +++ b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php @@ -45,8 +45,14 @@ public function tearDown() */ public function testValidateValidReCaptcha() { - $ReCaptcha = $this->getMock('ReCaptcha\ReCaptcha', ['verify'], [], '', false); - $Response = $this->getMock('ReCaptcha\Response', ['isSuccess'], [], '', false); + $ReCaptcha = $this->getMockBuilder('ReCaptcha\ReCaptcha') + ->setMethods(['verify']) + ->disableOriginalConstructor() + ->getMock(); + $Response = $this->getMockBuilder('ReCaptcha\Response') + ->setMethods(['isSuccess']) + ->disableOriginalConstructor() + ->getMock(); $Response->expects($this->any()) ->method('isSuccess') ->will($this->returnValue(true)); @@ -67,8 +73,14 @@ public function testValidateValidReCaptcha() */ public function testValidateInvalidReCaptcha() { - $ReCaptcha = $this->getMock('ReCaptcha\ReCaptcha', ['verify'], [], '', false); - $Response = $this->getMock('ReCaptcha\Response', ['isSuccess'], [], '', false); + $ReCaptcha = $this->getMockBuilder('ReCaptcha\ReCaptcha') + ->setMethods(['verify']) + ->disableOriginalConstructor() + ->getMock(); + $Response = $this->getMockBuilder('ReCaptcha\Response') + ->setMethods(['isSuccess']) + ->disableOriginalConstructor() + ->getMock(); $Response->expects($this->any()) ->method('isSuccess') ->will($this->returnValue(false)); diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index e5e02bbf5..584292905 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -19,10 +19,10 @@ class SocialTraitTest extends TestCase public function setUp() { parent::setUp(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - ['header', 'redirect', 'render', '_stop'] - ); + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(['header', 'redirect', 'render', '_stop']) + ->getMock(); + $this->controller->Trait = $this->getMockForTrait( 'CakeDC\Users\Controller\Traits\SocialTrait', [], @@ -45,7 +45,9 @@ public function tearDown() */ public function testSocialEmail() { - $session = $this->getMock('Cake\Network\Session', ['check', 'delete']); + $session = $this->getMockBuilder('Cake\Network\Session') + ->setMethods(['check', 'delete']) + ->getMock(); $session->expects($this->at(0)) ->method('check') ->with('Users.social') @@ -55,7 +57,9 @@ public function testSocialEmail() ->method('delete') ->with('Flash.auth'); - $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session']); + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['session']) + ->getMock(); $this->controller->Trait->request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); @@ -70,13 +74,17 @@ public function testSocialEmail() */ public function testSocialEmailInvalid() { - $session = $this->getMock('Cake\Network\Session', ['check']); + $session = $this->getMockBuilder('Cake\Network\Session') + ->setMethods(['check']) + ->getMock(); $session->expects($this->once()) ->method('check') ->with('Users.social') ->will($this->returnValue(null)); - $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session']); + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['session']) + ->getMock(); $this->controller->Trait->request->expects($this->once()) ->method('session') ->will($this->returnValue($session)); @@ -86,7 +94,9 @@ public function testSocialEmailInvalid() public function testSocialEmailPostValidateFalse() { - $session = $this->getMock('Cake\Network\Session', ['check', 'delete']); + $session = $this->getMockBuilder('Cake\Network\Session') + ->setMethods(['check', 'delete']) + ->getMock(); $session->expects($this->any()) ->method('check') ->with('Users.social') @@ -96,7 +106,9 @@ public function testSocialEmailPostValidateFalse() ->method('delete') ->with('Flash.auth'); - $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session', 'is']); + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['session', 'is']) + ->getMock(); $this->controller->Trait->request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); @@ -124,7 +136,9 @@ public function testSocialEmailPostValidateFalse() public function testSocialEmailPostValidateTrue() { - $session = $this->getMock('Cake\Network\Session', ['check', 'delete']); + $session = $this->getMockBuilder('Cake\Network\Session') + ->setMethods(['check', 'delete']) + ->getMock(); $session->expects($this->any()) ->method('check') ->with('Users.social') @@ -134,7 +148,9 @@ public function testSocialEmailPostValidateTrue() ->method('delete') ->with('Flash.auth'); - $this->controller->Trait->request = $this->getMock('Cake\Network\Request', ['session', 'is']); + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['session', 'is']) + ->getMock(); $this->controller->Trait->request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index e3c4311d7..2ae9cc7b5 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -38,7 +38,7 @@ public function setUp() { parent::setUp(); $this->out = new ConsoleOutput(); - $this->io = $this->getMock('Cake\Console\ConsoleIo'); + $this->io = $this->getMockBuilder('Cake\Console\ConsoleIo')->getMock(); $this->Users = TableRegistry::get('CakeDC/Users.Users'); $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') @@ -51,11 +51,10 @@ public function setUp() ->setMethods(['generateUniqueUsername', 'newEntity', 'save', 'updateAll']) ->getMock(); - $this->Shell->Command = $this->getMock( - 'Cake\Shell\Task\CommandTask', - ['in', '_stop', 'clear', 'out'], - [$this->io] - ); + $this->Shell->Command = $this->getMockBuilder('Cake\Shell\Task\CommandTask') + ->setMethods(['in', '_stop', 'clear', 'out']) + ->setConstructorArgs([$this->io]) + ->getMock(); } /** diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 5e5038f70..4265f8958 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -36,7 +36,9 @@ public function setUp() { parent::setUp(); Plugin::routes('CakeDC/Users'); - $this->View = $this->getMock('Cake\View\View', ['append']); + $this->View = $this->getMockBuilder('Cake\View\View') + ->setMethods(['append']) + ->getMock(); $this->User = new UserHelper($this->View); $this->request = new Request(); } @@ -156,7 +158,9 @@ public function testIsAuthorized() */ public function testWelcome() { - $session = $this->getMock('Cake\Network\Session', ['read']); + $session = $this->getMockBuilder('Cake\Network\Session') + ->setMethods(['read']) + ->getMock(); $session->expects($this->at(0)) ->method('read') ->with('Auth.User.id') @@ -167,7 +171,9 @@ public function testWelcome() ->with('Auth.User.first_name') ->will($this->returnValue('david')); - $this->User->request = $this->getMock('Cake\Network\Request', ['session']); + $this->User->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['session']) + ->getMock(); $this->User->request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); @@ -184,13 +190,17 @@ public function testWelcome() */ public function testWelcomeNotLoggedInUser() { - $session = $this->getMock('Cake\Network\Session', ['read']); + $session = $this->getMockBuilder('Cake\Network\Session') + ->setMethods(['read']) + ->getMock(); $session->expects($this->at(0)) ->method('read') ->with('Auth.User.id') ->will($this->returnValue(null)); - $this->User->request = $this->getMock('Cake\Network\Request', ['session']); + $this->User->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['session']) + ->getMock(); $this->User->request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); @@ -222,7 +232,7 @@ public function testAddReCaptchaEmpty() $expected = '

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

'; $this->assertEquals($expected, $result); } - + /** * Test add ReCaptcha field * From d8b938241a052770cc1ca97783b01ee421402a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Thu, 16 Jun 2016 17:16:37 +0100 Subject: [PATCH 0462/1476] refs #382 changed translations domain name to include plugin path --- config/bootstrap.php | 6 +- src/Auth/ApiKeyAuthenticate.php | 6 +- src/Auth/Rules/AbstractRule.php | 2 +- src/Auth/Rules/Owner.php | 4 +- src/Auth/SimpleRbacAuthorize.php | 2 +- src/Auth/SocialAuthenticate.php | 2 +- .../Component/RememberMeComponent.php | 2 +- .../Component/UsersAuthComponent.php | 2 +- src/Controller/SocialAccountsController.php | 20 ++-- src/Controller/Traits/LoginTrait.php | 18 ++-- .../Traits/PasswordManagementTrait.php | 22 ++--- src/Controller/Traits/ProfileTrait.php | 4 +- src/Controller/Traits/RegisterTrait.php | 8 +- src/Controller/Traits/SimpleCrudTrait.php | 12 +-- src/Controller/Traits/SocialTrait.php | 2 +- src/Controller/Traits/UserValidationTrait.php | 26 +++--- src/Email/EmailSender.php | 2 +- src/Locale/Users.pot | 4 + src/Locale/es/Users.mo | Bin 9035 -> 9108 bytes src/Locale/es/Users.po | 8 +- src/Mailer/UsersMailer.php | 4 +- src/Model/Behavior/PasswordBehavior.php | 16 ++-- src/Model/Behavior/RegisterBehavior.php | 6 +- src/Model/Behavior/SocialAccountBehavior.php | 8 +- src/Model/Behavior/SocialBehavior.php | 4 +- src/Model/Table/UsersTable.php | 8 +- src/Shell/UsersShell.php | 86 +++++++++--------- src/Template/Email/html/reset_password.ctp | 8 +- .../Email/html/social_account_validation.ctp | 8 +- src/Template/Email/html/validation.ctp | 8 +- src/Template/Email/text/reset_password.ctp | 6 +- .../Email/text/social_account_validation.ctp | 6 +- src/Template/Email/text/validation.ctp | 6 +- src/Template/Users/add.ctp | 10 +- src/Template/Users/change_password.ctp | 6 +- src/Template/Users/edit.ctp | 14 +-- src/Template/Users/index.ctp | 18 ++-- src/Template/Users/login.ctp | 10 +- src/Template/Users/profile.ctp | 18 ++-- src/Template/Users/register.ctp | 6 +- src/Template/Users/request_reset_password.ctp | 4 +- .../Users/resend_token_validation.ctp | 6 +- src/Template/Users/social_email.ctp | 4 +- src/Template/Users/view.ctp | 72 +++++++-------- src/View/Helper/UserHelper.php | 14 +-- tests/TestCase/Model/Entity/UserTest.php | 1 + tests/TestCase/View/Helper/UserHelperTest.php | 17 +++- tests/bootstrap.php | 2 + 48 files changed, 277 insertions(+), 251 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index f931659c4..ba2ac6cb1 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -10,10 +10,10 @@ */ use Cake\Core\Configure; -use Cake\Log\Log; 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; @@ -30,7 +30,7 @@ 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()); + Log::error($e->getMessage()); } } @@ -43,4 +43,4 @@ ['provider' => implode('|', array_keys(Configure::read('OAuth.providers')))] ); }); -} \ No newline at end of file +} diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 51d279ac8..3a6693416 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -70,11 +70,11 @@ public function getUser(Request $request) { $type = $this->config('type'); if (!in_array($type, $this->types)) { - throw new OutOfBoundsException(__d('Users', 'Type {0} is not valid', $type)); + throw new OutOfBoundsException(__d('CakeDC/Users', 'Type {0} is not valid', $type)); } if (!is_callable([$this, $type])) { - throw new OutOfBoundsException(__d('Users', 'Type {0} has no associated callable', $type)); + throw new OutOfBoundsException(__d('CakeDC/Users', 'Type {0} has no associated callable', $type)); } $apiKey = $this->$type($request); @@ -83,7 +83,7 @@ public function getUser(Request $request) } if ($this->config('require_ssl') && !$request->is('ssl')) { - throw new ForbiddenException(__d('Users', 'SSL is required for ApiKey Authentication', $type)); + throw new ForbiddenException(__d('CakeDC/Users', 'SSL is required for ApiKey Authentication', $type)); } $this->_config['fields']['username'] = $this->config('field'); diff --git a/src/Auth/Rules/AbstractRule.php b/src/Auth/Rules/AbstractRule.php index f8955fbbc..c8a8e8120 100644 --- a/src/Auth/Rules/AbstractRule.php +++ b/src/Auth/Rules/AbstractRule.php @@ -74,7 +74,7 @@ protected function _getTableFromRequest(Request $request) $this->modelFactory('Table', [$this->tableLocator(), 'get']); if (empty($modelClass)) { - throw new OutOfBoundsException(__d('Users', 'Table alias is empty, please define a table alias, we could not extract a default table from the request')); + throw new OutOfBoundsException(__d('CakeDC/Users', 'Table alias is empty, please define a table alias, we could not extract a default table from the request')); } return $this->loadModel($modelClass); } diff --git a/src/Auth/Rules/Owner.php b/src/Auth/Rules/Owner.php index 5be38835c..c5373f001 100644 --- a/src/Auth/Rules/Owner.php +++ b/src/Auth/Rules/Owner.php @@ -64,10 +64,10 @@ public function allowed(array $user, $role, Request $request) try { if (!$table->hasField($this->config('ownerForeignKey'))) { - throw new OutOfBoundsException(__d('Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); + throw new OutOfBoundsException(__d('CakeDC/Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); } } catch (Exception $ex) { - throw new OutOfBoundsException(__d('Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); + throw new OutOfBoundsException(__d('CakeDC/Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); } $idColumn = $this->config('id'); if (empty($idColumn)) { diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 612ccc3a7..ae4bab4dc 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -138,7 +138,7 @@ protected function _loadPermissions($key) Configure::load($key, 'default'); $permissions = Configure::read('Users.SimpleRbac.permissions'); } catch (Exception $ex) { - $msg = __d('Users', 'Missing configuration file: "config/{0}.php". Using default permissions', $key); + $msg = __d('CakeDC/Users', 'Missing configuration file: "config/{0}.php". Using default permissions', $key); $this->log($msg, LogLevel::WARNING); } diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 26cc411ed..8a52661f6 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -407,7 +407,7 @@ protected function _getProviderName($request = null) protected function _mapUser($provider, $data) { if (empty($provider)) { - throw new MissingProviderException(__d('Users', "Provider cannot be empty")); + throw new MissingProviderException(__d('CakeDC/Users', "Provider cannot be empty")); } $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; $providerMapper = new $providerMapperClass($data); diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 488fa272f..db37e9aac 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -66,7 +66,7 @@ protected function _validateConfig() { if (mb_strlen(Security::salt(), '8bit') < 32) { throw new InvalidArgumentException( - __d('Users', 'Invalid app salt, app salt must be at least 256 bits (32 bytes) long') + __d('CakeDC/Users', 'Invalid app salt, app salt must be at least 256 bits (32 bytes) long') ); } } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 471a828e3..0304d1ce6 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -154,7 +154,7 @@ public function isUrlAuthorized(Event $event) protected function _validateConfig() { if (!Configure::read('Users.Email.required') && Configure::read('Users.Email.validate')) { - $message = __d('Users', 'You can\'t enable email validation workflow if use_email is false'); + $message = __d('CakeDC/Users', 'You can\'t enable email validation workflow if use_email is false'); throw new BadConfigurationException($message); } } diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index c83b462f1..75ffa7a94 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -49,16 +49,16 @@ public function validateAccount($provider, $reference, $token) try { $result = $this->SocialAccounts->validateAccount($provider, $reference, $token); if ($result) { - $this->Flash->success(__d('Users', 'Account validated successfully')); + $this->Flash->success(__d('CakeDC/Users', 'Account validated successfully')); } else { - $this->Flash->error(__d('Users', 'Account could not be validated')); + $this->Flash->error(__d('CakeDC/Users', 'Account could not be validated')); } } catch (RecordNotFoundException $exception) { - $this->Flash->error(__d('Users', 'Invalid token and/or social account')); + $this->Flash->error(__d('CakeDC/Users', 'Invalid token and/or social account')); } catch (AccountAlreadyActiveException $exception) { - $this->Flash->error(__d('Users', 'Social Account already active')); + $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); } catch (Exception $exception) { - $this->Flash->error(__d('Users', 'Social Account could not be validated')); + $this->Flash->error(__d('CakeDC/Users', 'Social Account could not be validated')); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } @@ -76,16 +76,16 @@ public function resendValidation($provider, $reference) try { $result = $this->SocialAccounts->resendValidation($provider, $reference); if ($result) { - $this->Flash->success(__d('Users', 'Email sent successfully')); + $this->Flash->success(__d('CakeDC/Users', 'Email sent successfully')); } else { - $this->Flash->error(__d('Users', 'Email could not be sent')); + $this->Flash->error(__d('CakeDC/Users', 'Email could not be sent')); } } catch (RecordNotFoundException $exception) { - $this->Flash->error(__d('Users', 'Invalid account')); + $this->Flash->error(__d('CakeDC/Users', 'Invalid account')); } catch (AccountAlreadyActiveException $exception) { - $this->Flash->error(__d('Users', 'Social Account already active')); + $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); } catch (Exception $exception) { - $this->Flash->error(__d('Users', 'Email could not be resent')); + $this->Flash->error(__d('CakeDC/Users', 'Email could not be resent')); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 9d9e0a19b..8d3e0e29f 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -92,27 +92,27 @@ public function failedSocialLoginListener(Event $event) */ public function failedSocialLogin($exception, $data, $flash = false) { - $msg = __d('Users', 'Issues trying to log in with your social account'); + $msg = __d('CakeDC/Users', 'Issues trying to log in with your social account'); if (isset($exception)) { if ($exception instanceof MissingEmailException) { if ($flash) { - $this->Flash->success(__d('Users', 'Please enter your email')); + $this->Flash->success(__d('CakeDC/Users', 'Please enter your email')); } $this->request->session()->write(Configure::read('Users.Key.Session.social'), $data); return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); } if ($exception instanceof UserNotActiveException) { - $msg = __d('Users', 'Your user has not been validated yet. Please check your inbox for instructions'); + $msg = __d('CakeDC/Users', 'Your user has not been validated yet. Please check your inbox for instructions'); } elseif ($exception instanceof AccountNotActiveException) { - $msg = __d('Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); + $msg = __d('CakeDC/Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); } } if ($flash) { $this->Auth->config('authError', $msg); $this->Auth->config('flash.params', ['class' => 'success']); $this->request->session()->delete(Configure::read('Users.Key.Session.social')); - $this->Flash->success(__d('Users', $msg)); + $this->Flash->success(__d('CakeDC/Users', $msg)); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); } @@ -154,7 +154,7 @@ public function login() if ($this->request->is('post')) { if (!$this->_checkReCaptcha()) { - $this->Flash->error(__d('Users', 'Invalid reCaptcha')); + $this->Flash->error(__d('CakeDC/Users', 'Invalid reCaptcha')); return; } $user = $this->Auth->identify(); @@ -162,7 +162,7 @@ public function login() } if (!$this->request->is('post') && !$socialLogin) { if ($this->Auth->user()) { - $msg = __d('Users', 'You are already logged in'); + $msg = __d('CakeDC/Users', 'You are already logged in'); $this->Flash->error($msg); $url = $this->Auth->redirectUrl(); return $this->redirect($url); @@ -206,7 +206,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false) return $this->redirect($url); } else { if (!$socialLogin) { - $message = __d('Users', 'Username or password is incorrect'); + $message = __d('CakeDC/Users', 'Username or password is incorrect'); $this->Flash->error($message, 'default', [], 'auth'); } @@ -227,7 +227,7 @@ public function logout() } $this->request->session()->destroy(); - $this->Flash->success(__d('Users', 'You\'ve successfully logged out')); + $this->Flash->success(__d('CakeDC/Users', 'You\'ve successfully logged out')); $eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT); if (is_array($eventAfter->result)) { diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 9807df795..8187c22ab 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -50,22 +50,22 @@ public function changePassword() try { $user = $this->getUsersTable()->patchEntity($user, $this->request->data(), ['validate' => 'passwordConfirm']); if ($user->errors()) { - $this->Flash->error(__d('Users', 'Password could not be changed')); + $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); } else { $user = $this->getUsersTable()->changePassword($user); if ($user) { - $this->Flash->success(__d('Users', 'Password has been changed successfully')); + $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); return $this->redirect($redirect); } else { - $this->Flash->error(__d('Users', 'Password could not be changed')); + $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); } } } catch (UserNotFoundException $exception) { - $this->Flash->error(__d('Users', 'User was not found')); + $this->Flash->error(__d('CakeDC/Users', 'User was not found')); } catch (WrongPasswordException $wpe) { - $this->Flash->error(__d('Users', '{0}', $wpe->getMessage())); + $this->Flash->error(__d('CakeDC/Users', '{0}', $wpe->getMessage())); } catch (Exception $exception) { - $this->Flash->error(__d('Users', 'Password could not be changed')); + $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); } } $this->set(compact('user')); @@ -105,19 +105,19 @@ public function requestResetPassword() 'ensureActive' => true ]); if ($resetUser) { - $msg = __d('Users', 'Please check your email to continue with password reset process'); + $msg = __d('CakeDC/Users', 'Please check your email to continue with password reset process'); $this->Flash->success($msg); } else { - $msg = __d('Users', 'The password token could not be generated. Please try again'); + $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); $this->Flash->error($msg); } return $this->redirect(['action' => 'login']); } catch (UserNotFoundException $exception) { - $this->Flash->error(__d('Users', 'User {0} was not found', $reference)); + $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); } catch (UserNotActiveException $exception) { - $this->Flash->error(__d('Users', 'The user is not active')); + $this->Flash->error(__d('CakeDC/Users', 'The user is not active')); } catch (Exception $exception) { - $this->Flash->error(__d('Users', 'Token could not be reset')); + $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); } } } diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 0d68ac6bc..6053f424e 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -46,10 +46,10 @@ public function profile($id = null) $isCurrentUser = true; } } catch (RecordNotFoundException $ex) { - $this->Flash->error(__d('Users', 'User was not found')); + $this->Flash->error(__d('CakeDC/Users', 'User was not found')); return $this->redirect($this->request->referer()); } catch (InvalidPrimaryKeyException $ex) { - $this->Flash->error(__d('Users', 'Not authorized, please login first')); + $this->Flash->error(__d('CakeDC/Users', 'Not authorized, please login first')); return $this->redirect($this->request->referer()); } $this->set(compact('user', 'isCurrentUser')); diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 1aa65882f..648f62a5a 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -70,13 +70,13 @@ public function register() } if (!$this->_validateRegisterPost()) { - $this->Flash->error(__d('Users', 'Invalid reCaptcha')); + $this->Flash->error(__d('CakeDC/Users', 'Invalid reCaptcha')); return; } $userSaved = $usersTable->register($user, $requestData, $options); if (!$userSaved) { - $this->Flash->error(__d('Users', 'The user could not be saved')); + $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); return; } @@ -108,9 +108,9 @@ protected function _validateRegisterPost() protected function _afterRegister(EntityInterface $userSaved) { $validateEmail = (bool)Configure::read('Users.Email.validate'); - $message = __d('Users', 'You have registered successfully, please log in'); + $message = __d('CakeDC/Users', 'You have registered successfully, please log in'); if ($validateEmail) { - $message = __d('Users', 'Please validate your account before log in'); + $message = __d('CakeDC/Users', 'Please validate your account before log in'); } $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, [ 'user' => $userSaved diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index 63fd75b72..10525f2b7 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -73,10 +73,10 @@ public function add() $entity = $table->patchEntity($entity, $this->request->data); $singular = Inflector::singularize(Inflector::humanize($tableAlias)); if ($table->save($entity)) { - $this->Flash->success(__d('Users', 'The {0} has been saved', $singular)); + $this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular)); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__d('Users', 'The {0} could not be saved', $singular)); + $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular)); } /** @@ -102,10 +102,10 @@ public function edit($id = null) $entity = $table->patchEntity($entity, $this->request->data); $singular = Inflector::singularize(Inflector::humanize($tableAlias)); if ($table->save($entity)) { - $this->Flash->success(__d('Users', 'The {0} has been saved', $singular)); + $this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular)); return $this->redirect(['action' => 'index']); } - $this->Flash->error(__d('Users', 'The {0} could not be saved', $singular)); + $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular)); } /** @@ -125,9 +125,9 @@ public function delete($id = null) ]); $singular = Inflector::singularize(Inflector::humanize($tableAlias)); if ($table->delete($entity)) { - $this->Flash->success(__d('Users', 'The {0} has been deleted', $singular)); + $this->Flash->success(__d('CakeDC/Users', 'The {0} has been deleted', $singular)); } else { - $this->Flash->error(__d('Users', 'The {0} could not be deleted', $singular)); + $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be deleted', $singular)); } return $this->redirect(['action' => 'index']); } diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 05a90f957..8ac75d6db 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -36,7 +36,7 @@ public function socialEmail() if ($this->request->is('post')) { $validPost = $this->_validateRegisterPost(); if (!$validPost) { - $this->Flash->error(__d('Users', 'The reCaptcha could not be validated')); + $this->Flash->error(__d('CakeDC/Users', 'The reCaptcha could not be validated')); return; } $user = $this->Auth->identify(); diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 74836e61a..87ebedb7f 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -39,31 +39,31 @@ public function validate($type = null, $token = null) try { $result = $this->getUsersTable()->validate($token, 'activateUser'); if ($result) { - $this->Flash->success(__d('Users', 'User account validated successfully')); + $this->Flash->success(__d('CakeDC/Users', 'User account validated successfully')); } else { - $this->Flash->error(__d('Users', 'User account could not be validated')); + $this->Flash->error(__d('CakeDC/Users', 'User account could not be validated')); } } catch (UserAlreadyActiveException $exception) { - $this->Flash->error(__d('Users', 'User already active')); + $this->Flash->error(__d('CakeDC/Users', 'User already active')); } break; case 'password': $result = $this->getUsersTable()->validate($token); if (!empty($result)) { - $this->Flash->success(__d('Users', 'Reset password token was validated successfully')); + $this->Flash->success(__d('CakeDC/Users', 'Reset password token was validated successfully')); $this->request->session()->write(Configure::read('Users.Key.Session.resetPasswordUserId'), $result->id); return $this->redirect(['action' => 'changePassword']); } else { - $this->Flash->error(__d('Users', 'Reset password token could not be validated')); + $this->Flash->error(__d('CakeDC/Users', 'Reset password token could not be validated')); } break; default: - $this->Flash->error(__d('Users', 'Invalid validation type')); + $this->Flash->error(__d('CakeDC/Users', 'Invalid validation type')); } } catch (UserNotFoundException $ex) { - $this->Flash->error(__d('Users', 'Invalid token or user account already validated')); + $this->Flash->error(__d('CakeDC/Users', 'Invalid token or user account already validated')); } catch (TokenExpiredException $ex) { - $this->Flash->error(__d('Users', 'Token already expired')); + $this->Flash->error(__d('CakeDC/Users', 'Token already expired')); } return $this->redirect(['action' => 'login']); @@ -89,17 +89,17 @@ public function resendTokenValidation() 'sendEmail' => true, 'emailTemplate' => 'CakeDC/Users.validation' ])) { - $this->Flash->success(__d('Users', 'Token has been reset successfully. Please check your email.')); + $this->Flash->success(__d('CakeDC/Users', 'Token has been reset successfully. Please check your email.')); } else { - $this->Flash->error(__d('Users', 'Token could not be reset')); + $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); } return $this->redirect(['action' => 'login']); } catch (UserNotFoundException $ex) { - $this->Flash->error(__d('Users', 'User {0} was not found', $reference)); + $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); } catch (UserAlreadyActiveException $ex) { - $this->Flash->error(__d('Users', 'User {0} is already active', $reference)); + $this->Flash->error(__d('CakeDC/Users', 'User {0} is already active', $reference)); } catch (Exception $ex) { - $this->Flash->error(__d('Users', 'Token could not be reset')); + $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); } } } diff --git a/src/Email/EmailSender.php b/src/Email/EmailSender.php index 9b08f4121..609653b51 100644 --- a/src/Email/EmailSender.php +++ b/src/Email/EmailSender.php @@ -36,7 +36,7 @@ public function sendValidationEmail(EntityInterface $user, Email $email = null) 'CakeDC/Users.Users', $this->_getEmailInstance($email) ) - ->send('validation', [$user, __d('Users', 'Your account validation link')]); + ->send('validation', [$user, __d('CakeDC/Users', 'Your account validation link')]); } /** diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 61e6c7acc..28dc31436 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -715,6 +715,10 @@ msgstr "" msgid "Data" msgstr "" +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "" + #: View/Helper/UserHelper.php:49 msgid "fa fa-{0}" msgstr "" diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo index ffe80c6b57938b0790c026bbef1c06b602649ec1..1576395ea822d658bfbed7eff1ae9527f6faf096 100644 GIT binary patch delta 2569 zcmZYAe@xVM9LMqZ$q$7?(L_smN9*V2=G^M}I==KzpYguO=RWtn&#(9A zb9_;Mq9OL3FZrZV`iVT^y(F_i+%TIL%1D}74vymO_&F}YAFvcX>C^AmpuWP8sK}Jg_GEU*HIH}$}p?NHY~(9Q5}DZ zn!vZHiB95NoI>?`6E(3E8dDkHyi^L%hYh$6wMBQF5+tZ5tm~YvoFQ~#xzhj70tL0wZ%^(i?o+e9lVY!@f?=m6}%18d6>mm zA!@)X zP!lRfO{5OBb8V;{>cTtmFe>M#Q9Cn?K^#Tx+@Gl1Q^1MTZQB&1qC>O`^~E!&j?bcI zI*Qtv3#gn=;E>1c7HUPOn2jblj_U9mti-=iDOttr)L$dgWG$%neMlD;dy$HAG>FRC zFe+E)aRrXKpZ|)q<$!no&Eu6ZKpV^1Yb#Qqhc# zpjJAB{Mm=RXhL7R?blEp{ev1HmCLManTcWap$0sJ8}Su%@FJ@JUr`J5l1KHEjq`N> z^QdT`m8gybs2SFxcAybkF^amsmr#fAGOEK#T#A37u5k{l*o{@#jssYOH&FdmkSCpi z4yW=ZOnBF)$t;xtpS&!a#iBKuSNcB8!rLu#UQ?e4qiv4%F8HZ%kohZtU&Eh z8)^r7F{VQnrJ~b&2(^MCY{ZY<_Zj)qGcG~;wh)p9djd7UQPhqNqE7u8 ziM@o%J%sw+O>8D+$~G!&L}I7Y8UMec`>%38v4>D@!-NKCC$!>DLKB%O4OEhdLbss> zmFxS6I=8J4m3RGw&y*mQ8X_^ie(P1VwJQ3dSWhT5oW=hY9Uk5J$A~S2Qlz{6IPoyi zOw5#ixALfKEp8+pBFf$I6CaiFx`x<6Y$8Zeq9`3IN`tQ9R)U*kPZG-I2113~mpC&@ z&vG@mr5<%ib)b6*-J}Nz{hvsTzYCPh4q_IegS3`V(III|)HvBX}f8;UoxxCiBZr|VU z=(~x_%f0V&QV$xXpO{PxKVo(mE5~r5?9VWpghQB*N3jskVhq1^_nDby`bs$#U^NzD z3ufa^OveEni*F!b_3TY5r93#~UO12X!X@W*RKs^Lj6Y*4{)cKXlx4=pGPvk@1Zmg` zFbzv^B37U#5XU^+j1%bJ`uz$ca(_68v~9;x9h|`sUcl{m5jDV)ab`=g28(eIs^Je% z12~Nu&;=Zimr(6qLk;W(rqjROrZN@pV*XxfQhnoj3*iP%HKp#_<$x#6Pee zTOJMG8$=Cg7-!)*EW@9$0&|&#r;Zw^Xv7KB60bofX**C2^x_O0#40?AkKrh4K>y-2 z%;(EgEsk2b)u?tipjK!bYESIN1vngL{U4`tlLy*-4^W#Ye?rhf4QlhPLM>SbGD+*f z2<}D=9wRK$@Jpa#;Ud9=yW?R>eNTnRp8M*eDkb=ugx@ z!n~}8%TOy5!zXYBD%U+o7Of8(aR96EJnGc^f|}?!cBJ-Bxkp7`>_s*FGHRp)sFm4^ z%Joq^l4AB1Du*vH8V&FOs=*Jj4nISs%Dn(uw73HiCl`9X+ zamc-pLfko+UKn z^}3<-5Ig)DM-@8=wO>PY5-MAWJo@)@(X1zw*~C`A7A&2rFS`2%TuUq?wEQaT0{p9H zs(sN%C~YdMi6w+KAlt}a74S=ftEaOV3hu25*{s$@tRhI8zg$nEmYvD_KPDS-Co!LR zSQb&yPq0=`|5i*R^t+)G!wL0^a=wP>4sMlV&(F8+wamNRAC{wb@WawhCGKvN2Bl^W z!HM&Cb_;GGo+DJY2l)R%(Ggzh?%ObxXeDZi={o=0s60=+M5y!q^s%UAJszT9GimF0+I(a1q|8gcKI!c-$)dtn)BXpCTFUkS diff --git a/src/Locale/es/Users.po b/src/Locale/es/Users.po index 5a84224c4..3fe2e8f08 100644 --- a/src/Locale/es/Users.po +++ b/src/Locale/es/Users.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" "POT-Creation-Date: 2016-04-20 09:48-0300\n" -"PO-Revision-Date: 2016-06-06 09:50+0100\n" +"PO-Revision-Date: 2016-06-16 16:43+0100\n" "Last-Translator: André Teixeira \n" "Language-Team: CakeDC \n" "Language: es_ES\n" @@ -13,7 +13,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.7\n" +"X-Generator: Poedit 1.8.8\n" "X-Poedit-SourceCharset: UTF-8\n" #: Auth/ApiKeyAuthenticate.php:55 @@ -727,6 +727,10 @@ msgstr "Referencia" msgid "Data" msgstr "Datos" +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Iniciar sesión con" + #: View/Helper/UserHelper.php:49 msgid "fa fa-{0}" msgstr "" diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 5fa1beffc..3ef4c5c75 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -52,7 +52,7 @@ protected function validation(EntityInterface $user, $subject, $template = 'Cake protected function resetPassword(EntityInterface $user, $template = 'CakeDC/Users.reset_password') { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $subject = __d('Users', '{0}Your reset password link', $firstName); + $subject = __d('CakeDC/Users', '{0}Your reset password link', $firstName); $user->hiddenProperties(['password', 'token_expires', 'api_token']); $this @@ -75,7 +75,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('Users', '{0}Your social account validation link', $firstName); + $subject = __d('CakeDC/Users', '{0}Your social account validation link', $firstName); $this ->to($user['email']) ->subject($subject) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index b5a17ab78..e62ee0b28 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -53,29 +53,29 @@ public function initialize(array $config) public function resetToken($reference, array $options = []) { if (empty($reference)) { - throw new InvalidArgumentException(__d('Users', "Reference cannot be null")); + throw new InvalidArgumentException(__d('CakeDC/Users', "Reference cannot be null")); } $expiration = Hash::get($options, 'expiration'); if (empty($expiration)) { - throw new InvalidArgumentException(__d('Users', "Token expiration cannot be empty")); + throw new InvalidArgumentException(__d('CakeDC/Users', "Token expiration cannot be empty")); } $user = $this->_getUser($reference); if (empty($user)) { - throw new UserNotFoundException(__d('Users', "User not found")); + throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); } if (Hash::get($options, 'checkActive')) { if ($user->active) { - throw new UserAlreadyActiveException(__d('Users', "User account already validated")); + throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); } $user->active = false; $user->activation_date = null; } if (Hash::get($options, 'ensureActive')) { if (!$user['active']) { - throw new UserNotActiveException(__d('Users', "User not active")); + throw new UserNotActiveException(__d('CakeDC/Users', "User not active")); } } $user->updateToken($expiration); @@ -112,15 +112,15 @@ public function changePassword(EntityInterface $user) 'contain' => [] ]); } catch (RecordNotFoundException $e) { - throw new UserNotFoundException(__d('Users', "User not found")); + throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); } if (!empty($user->current_password)) { if (!$user->checkPassword($user->current_password, $currentUser->password)) { - throw new WrongPasswordException(__d('Users', 'The current password does not match')); + throw new WrongPasswordException(__d('CakeDC/Users', 'The current password does not match')); } if ($user->current_password === $user->password_confirm) { - throw new WrongPasswordException(__d('Users', 'You cannot use the current password as the new one')); + throw new WrongPasswordException(__d('CakeDC/Users', 'You cannot use the current password as the new one')); } } $user = $this->_table->save($user); diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 36bc66688..fe846589a 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -85,10 +85,10 @@ public function validate($token, $callback = null) ->where(['token' => $token]) ->first(); if (empty($user)) { - throw new UserNotFoundException(__d('Users', "User not found for the given token and email.")); + throw new UserNotFoundException(__d('CakeDC/Users', "User not found for the given token and email.")); } if ($user->tokenExpired()) { - throw new TokenExpiredException(__d('Users', "Token has already expired user with no token")); + throw new TokenExpiredException(__d('CakeDC/Users', "Token has already expired user with no token")); } if (!method_exists($this, $callback)) { return $user; @@ -107,7 +107,7 @@ public function validate($token, $callback = null) public function activateUser(EntityInterface $user) { if ($user->active) { - throw new UserAlreadyActiveException(__d('Users', "User account already validated")); + throw new UserAlreadyActiveException(__d('CakeDC/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 81a009213..9b2aea082 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -98,10 +98,10 @@ public function validateAccount($provider, $reference, $token) if (!empty($socialAccount) && $socialAccount->token === $token) { if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); + throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); } } else { - throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); + throw new RecordNotFoundException(__d('CakeDC/Users', "Account not found for the given token and email.")); } return $this->_activateAccount($socialAccount); @@ -125,10 +125,10 @@ public function resendValidation($provider, $reference) if (!empty($socialAccount)) { if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('Users', "Account already validated")); + throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); } } else { - throw new RecordNotFoundException(__d('Users', "Account not found for the given token and email.")); + throw new RecordNotFoundException(__d('CakeDC/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 319340c1f..eb98a5a49 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -53,7 +53,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('Users', 'Unable to login user with reference {0}', $reference)); + throw new InvalidArgumentException(__d('CakeDC/Users', 'Unable to login user with reference {0}', $reference)); } } else { $user = $existingAccount->user; @@ -94,7 +94,7 @@ protected function _createSocialUser($data, $options = []) $existingUser = null; $email = Hash::get($data, 'email'); if ($useEmail && empty($email)) { - throw new MissingEmailException(__d('Users', 'Email not present')); + throw new MissingEmailException(__d('CakeDC/Users', 'Email not present')); } else { $existingUser = $this->_table->find() ->where([$this->_table->alias() . '.email' => $email]) diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index da54831f5..0d98c3871 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -78,7 +78,7 @@ public function validationPasswordConfirm(Validator $validator) } return true; }, - 'message' => __d('Users', 'Your password does not match your confirm password. Please try again'), + 'message' => __d('CakeDC/Users', 'Your password does not match your confirm password. Please try again'), 'on' => ['create', 'update'], 'allowEmpty' => false ]); @@ -156,13 +156,13 @@ public function buildRules(RulesChecker $rules) { $rules->add($rules->isUnique(['username']), '_isUnique', [ 'errorField' => 'username', - 'message' => __d('Users', 'Username already exists') + 'message' => __d('CakeDC/Users', 'Username already exists') ]); if ($this->isValidateEmail) { $rules->add($rules->isUnique(['email']), '_isUnique', [ 'errorField' => 'email', - 'message' => __d('Users', 'Email already exists') + 'message' => __d('CakeDC/Users', 'Email already exists') ]); } @@ -194,7 +194,7 @@ public function findAuth(Query $query, array $options = []) { $identifier = Hash::get($options, 'username'); if (empty($identifier)) { - throw new \BadMethodCallException(__d('Users', 'Missing \'username\' in options data')); + throw new \BadMethodCallException(__d('CakeDC/Users', 'Missing \'username\' in options data')); } $query diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 908bfd502..8d9690e78 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -51,16 +51,16 @@ public function initialize() public function getOptionParser() { $parser = parent::getOptionParser(); - $parser->description(__d('Users', 'Utilities for CakeDC Users Plugin')) - ->addSubcommand('activateUser')->description(__d('Users', 'Activate an specific user')) - ->addSubcommand('addSuperuser')->description(__d('Users', 'Add a new superadmin user for testing purposes')) - ->addSubcommand('addUser')->description(__d('Users', 'Add a new user')) - ->addSubcommand('changeRole')->description(__d('Users', 'Change the role for an specific user')) - ->addSubcommand('deactivateUser')->description(__d('Users', 'Deactivate an specific user')) - ->addSubcommand('deleteUser')->description(__d('Users', 'Delete an specific user')) - ->addSubcommand('passwordEmail')->description(__d('Users', 'Reset the password via email')) - ->addSubcommand('resetAllPasswords')->description(__d('Users', 'Reset the password for all users')) - ->addSubcommand('resetPassword')->description(__d('Users', 'Reset the password for an specific user')) + $parser->description(__d('CakeDC/Users', 'Utilities for CakeDC Users Plugin')) + ->addSubcommand('activateUser')->description(__d('CakeDC/Users', 'Activate an specific user')) + ->addSubcommand('addSuperuser')->description(__d('CakeDC/Users', 'Add a new superadmin user for testing purposes')) + ->addSubcommand('addUser')->description(__d('CakeDC/Users', 'Add a new user')) + ->addSubcommand('changeRole')->description(__d('CakeDC/Users', 'Change the role for an specific user')) + ->addSubcommand('deactivateUser')->description(__d('CakeDC/Users', 'Deactivate an specific user')) + ->addSubcommand('deleteUser')->description(__d('CakeDC/Users', 'Delete an specific user')) + ->addSubcommand('passwordEmail')->description(__d('CakeDC/Users', 'Reset the password via email')) + ->addSubcommand('resetAllPasswords')->description(__d('CakeDC/Users', 'Reset the password for all users')) + ->addSubcommand('resetPassword')->description(__d('CakeDC/Users', 'Reset the password for an specific user')) ->addOptions([ 'username' => ['short' => 'u', 'help' => 'The username for the new user'], 'password' => ['short' => 'p', 'help' => 'The password for the new user'], @@ -94,11 +94,11 @@ public function addUser() $userEntity->is_superuser = true; $userEntity->role = 'user'; $savedUser = $this->Users->save($userEntity); - $this->out(__d('Users', 'User added:')); - $this->out(__d('Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('Users', 'Username: {0}', $username)); - $this->out(__d('Users', 'Email: {0}', $savedUser->email)); - $this->out(__d('Users', 'Password: {0}', $password)); + $this->out(__d('CakeDC/Users', 'User added:')); + $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); + $this->out(__d('CakeDC/Users', 'Username: {0}', $username)); + $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); } /** @@ -122,16 +122,16 @@ public function addSuperuser() $userEntity->role = 'superuser'; $savedUser = $this->Users->save($userEntity); if (!empty($savedUser)) { - $this->out(__d('Users', 'Superuser added:')); - $this->out(__d('Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('Users', 'Username: {0}', $username)); - $this->out(__d('Users', 'Email: {0}', $savedUser->email)); - $this->out(__d('Users', 'Password: {0}', $password)); + $this->out(__d('CakeDC/Users', 'Superuser added:')); + $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); + $this->out(__d('CakeDC/Users', 'Username: {0}', $username)); + $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); } else { - $this->out(__d('Users', 'Superuser could not be added:')); + $this->out(__d('CakeDC/Users', 'Superuser could not be added:')); collection($userEntity->errors())->each(function ($error, $field) { - $this->out(__d('Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); + $this->out(__d('CakeDC/Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); }); } } @@ -149,12 +149,12 @@ public function resetAllPasswords() { $password = Hash::get($this->args, 0); if (empty($password)) { - $this->error(__d('Users', 'Please enter a password.')); + $this->error(__d('CakeDC/Users', 'Please enter a password.')); } $hashedPassword = $this->_generatedHashedPassword($password); $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); - $this->out(__d('Users', 'Password changed for all users')); - $this->out(__d('Users', 'New password: {0}', $password)); + $this->out(__d('CakeDC/Users', 'Password changed for all users')); + $this->out(__d('CakeDC/Users', 'New password: {0}', $password)); } /** @@ -172,17 +172,17 @@ public function resetPassword() $username = Hash::get($this->args, 0); $password = Hash::get($this->args, 1); if (empty($username)) { - $this->error(__d('Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($password)) { - $this->error(__d('Users', 'Please enter a password.')); + $this->error(__d('CakeDC/Users', 'Please enter a password.')); } $data = [ 'password' => $password ]; $this->_updateUser($username, $data); - $this->out(__d('Users', 'Password changed for user: {0}', $username)); - $this->out(__d('Users', 'New password: {0}', $password)); + $this->out(__d('CakeDC/Users', 'Password changed for user: {0}', $username)); + $this->out(__d('CakeDC/Users', 'New password: {0}', $password)); } /** @@ -200,17 +200,17 @@ public function changeRole() $username = Hash::get($this->args, 0); $role = Hash::get($this->args, 1); if (empty($username)) { - $this->error(__d('Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($role)) { - $this->error(__d('Users', 'Please enter a role.')); + $this->error(__d('CakeDC/Users', 'Please enter a role.')); } $data = [ 'role' => $role ]; $savedUser = $this->_updateUser($username, $data); - $this->out(__d('Users', 'Role changed for user: {0}', $username)); - $this->out(__d('Users', 'New role: {0}', $savedUser->role)); + $this->out(__d('CakeDC/Users', 'Role changed for user: {0}', $username)); + $this->out(__d('CakeDC/Users', 'New role: {0}', $savedUser->role)); } /** @@ -225,7 +225,7 @@ public function changeRole() public function activateUser() { $user = $this->_changeUserActive(true); - $this->out(__d('Users', 'User was activated: {0}', $user->username)); + $this->out(__d('CakeDC/Users', 'User was activated: {0}', $user->username)); } /** @@ -240,7 +240,7 @@ public function activateUser() public function deactivateUser() { $user = $this->_changeUserActive(false); - $this->out(__d('Users', 'User was de-activated: {0}', $user->username)); + $this->out(__d('CakeDC/Users', 'User was de-activated: {0}', $user->username)); } /** @@ -252,7 +252,7 @@ public function passwordEmail() { $reference = Hash::get($this->args, 0); if (empty($reference)) { - $this->error(__d('Users', 'Please enter a username or email.')); + $this->error(__d('CakeDC/Users', 'Please enter a username or email.')); } $resetUser = $this->Users->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -260,10 +260,10 @@ public function passwordEmail() 'sendEmail' => true, ]); if ($resetUser) { - $msg = __d('Users', 'Please ask the user to check the email to continue with password reset process'); + $msg = __d('CakeDC/Users', 'Please ask the user to check the email to continue with password reset process'); $this->out($msg); } else { - $msg = __d('Users', 'The password token could not be generated. Please try again'); + $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); $this->error($msg); } } @@ -278,7 +278,7 @@ protected function _changeUserActive($active) { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->error(__d('Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } $data = [ 'active' => $active @@ -297,7 +297,7 @@ protected function _updateUser($username, $data) { $user = $this->Users->find()->where(['username' => $username])->first(); if (empty($user)) { - $this->error(__d('Users', 'The user was not found.')); + $this->error(__d('CakeDC/Users', 'The user was not found.')); } $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { @@ -318,7 +318,7 @@ public function deleteUser() { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->error(__d('Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } $user = $this->Users->find()->where(['username' => $username])->first(); if (isset($this->Users->SocialAccounts)) { @@ -326,9 +326,9 @@ public function deleteUser() } $deleteUser = $this->Users->delete($user); if (!$deleteUser) { - $this->error(__d('Users', 'The user {0} was not deleted. Please try again', $username)); + $this->error(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); } - $this->out(__d('Users', 'The user {0} was deleted successfully', $username)); + $this->out(__d('CakeDC/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 10feeba1f..5f585c3ad 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -18,14 +18,14 @@ $activationUrl = [ ]; ?>

-, +,

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

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

- , + ,

diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp index f4357c898..f6dbd7567 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', @@ -29,8 +29,8 @@ ?>

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

- , + ,

diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index df1dc3fe2..0e722b118 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -18,14 +18,14 @@ $activationUrl = [ ]; ?>

-, +,

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

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

- , + ,

diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp index c2f38948e..49018fb92 100644 --- a/src/Template/Email/text/reset_password.ctp +++ b/src/Template/Email/text/reset_password.ctp @@ -17,9 +17,9 @@ $activationUrl = [ isset($token) ? $token : '' ]; ?> -, +, -Url->build($activationUrl)) ?> +Url->build($activationUrl)) ?> -, +, diff --git a/src/Template/Email/text/social_account_validation.ctp b/src/Template/Email/text/social_account_validation.ctp index e2a7503d7..72b1f1279 100644 --- a/src/Template/Email/text/social_account_validation.ctp +++ b/src/Template/Email/text/social_account_validation.ctp @@ -19,9 +19,9 @@ $socialAccount['token'], ]; ?> -, +, -Url->build($activationUrl)) ?> +Url->build($activationUrl)) ?> -, +, diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp index 9bc3deb34..a423ee9ea 100644 --- a/src/Template/Email/text/validation.ctp +++ b/src/Template/Email/text/validation.ctp @@ -17,9 +17,9 @@ $activationUrl = [ isset($token) ? $token : '' ]; ?> -, +, -Url->build($activationUrl)) ?> +Url->build($activationUrl)) ?> -, +, diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp index 29a1dfb61..a57279ea5 100644 --- a/src/Template/Users/add.ctp +++ b/src/Template/Users/add.ctp @@ -10,16 +10,16 @@ */ ?>
-

+

    -
  • Html->link(__d('Users', 'List Users'), ['action' => 'index']) ?>
  • -
  • Html->link(__d('Users', 'List Accounts'), ['controller' => 'Accounts', 'action' => 'index']) ?>
  • +
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('CakeDC/Users', 'List Accounts'), ['controller' => 'Accounts', 'action' => 'index']) ?>
Form->create($Users); ?>
- + Form->input('username'); echo $this->Form->input('email'); @@ -29,6 +29,6 @@ echo $this->Form->input('active', ['type' => 'checkbox']); ?>
- Form->button(__d('Users', 'Submit')) ?> + Form->button(__d('CakeDC/Users', 'Submit')) ?> Form->end() ?>
diff --git a/src/Template/Users/change_password.ctp b/src/Template/Users/change_password.ctp index 129b1b87a..3e4be5ad2 100644 --- a/src/Template/Users/change_password.ctp +++ b/src/Template/Users/change_password.ctp @@ -2,18 +2,18 @@ Flash->render('auth') ?> Form->create($user) ?>
- + Form->input('current_password', [ 'type' => 'password', 'required' => true, - 'label' => __d('Users', 'Current password')]); + 'label' => __d('CakeDC/Users', 'Current password')]); ?> Form->input('password'); ?> Form->input('password_confirm', ['type' => 'password', 'required' => true]); ?>
- Form->button(__d('Users', 'Submit')); ?> + Form->button(__d('CakeDC/Users', 'Submit')); ?> Form->end() ?>
\ No newline at end of file diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index 550b124fe..185551d11 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -10,22 +10,22 @@ */ ?>
-

+

  • Form->postLink( - __d('Users', 'Delete'), + __d('CakeDC/Users', 'Delete'), ['action' => 'delete', $Users->id], - ['confirm' => __d('Users', 'Are you sure you want to delete # {0}?', $Users->id)] + ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] ) ?>
  • -
  • Html->link(__d('Users', 'List Users'), ['action' => 'index']) ?>
  • -
  • Html->link(__d('Users', 'List Accounts'), ['controller' => 'Accounts', 'action' => 'index']) ?>
  • +
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('CakeDC/Users', 'List Accounts'), ['controller' => 'Accounts', 'action' => 'index']) ?>
Form->create($Users); ?>
- + Form->input('username'); echo $this->Form->input('email'); @@ -39,6 +39,6 @@ echo $this->Form->input('active'); ?>
- Form->button(__d('Users', 'Submit')) ?> + Form->button(__d('CakeDC/Users', 'Submit')) ?> Form->end() ?>
diff --git a/src/Template/Users/index.ctp b/src/Template/Users/index.ctp index 500b381a7..28efea0e2 100644 --- a/src/Template/Users/index.ctp +++ b/src/Template/Users/index.ctp @@ -10,9 +10,9 @@ */ ?>
-

+

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

Paginator->counter() ?>

diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 24b791185..4532fbaa9 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -16,7 +16,7 @@ use Cake\Core\Configure; Flash->render('auth') ?> Form->create() ?>
- + Form->input('username', ['required' => true]) ?> Form->input('password', ['required' => true]) ?> Form->input(Configure::read('Users.Key.Data.rememberMe'), [ 'type' => 'checkbox', - 'label' => __d('Users', 'Remember me'), + 'label' => __d('CakeDC/Users', 'Remember me'), 'checked' => 'checked' ]); } @@ -34,17 +34,17 @@ use Cake\Core\Configure; Html->link(__d('users', 'Register'), ['action' => 'register']); + echo $this->Html->link(__d('CakeDC/Users', 'Register'), ['action' => 'register']); } if (Configure::read('Users.Email.required')) { if ($registrationActive) { echo ' | '; } - echo $this->Html->link(__d('users', 'Reset Password'), ['action' => 'requestResetPassword']); + echo $this->Html->link(__d('CakeDC/Users', 'Reset Password'), ['action' => 'requestResetPassword']); } ?>
User->socialLoginList()); ?> - Form->button(__d('Users', 'Login')); ?> + Form->button(__d('CakeDC/Users', 'Login')); ?> Form->end() ?>
diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index 59091709d..65f09904a 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -15,36 +15,36 @@ Html->tag( 'span', - __d('Users', '{0} {1}', $user->first_name, $user->last_name), + __d('CakeDC/Users', '{0} {1}', $user->first_name, $user->last_name), ['class' => 'full_name'] ) ?> - Html->link(__d('Users', 'Change Password'), ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword']); ?> + Html->link(__d('CakeDC/Users', 'Change Password'), ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword']); ?>
-
+

username) ?>

-
+

email) ?>

social_accounts)): ?> -
+
- - - + + + social_accounts as $socialAccount): $escapedUsername = h($socialAccount->username); - $linkText = empty($escapedUsername) ? __d('Users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) + $linkText = empty($escapedUsername) ? __d('CakeDC/Users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) ?>
Form->create($user); ?>
- + Form->input('username'); echo $this->Form->input('email'); @@ -22,13 +22,13 @@ use Cake\Core\Configure; echo $this->Form->input('first_name'); echo $this->Form->input('last_name'); if (Configure::read('Users.Tos.required')) { - echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('Users', 'Accept TOS conditions?'), 'required' => true]); + echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Accept TOS conditions?'), 'required' => true]); } if (Configure::read('Users.reCaptcha.registration')) { echo $this->User->addReCaptcha(); } ?>
- Form->button(__d('Users', 'Submit')) ?> + Form->button(__d('CakeDC/Users', 'Submit')) ?> Form->end() ?> diff --git a/src/Template/Users/request_reset_password.ctp b/src/Template/Users/request_reset_password.ctp index c8559a63c..462e29bc6 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->input('reference') ?>
- Form->button(__d('Users', 'Submit')); ?> + Form->button(__d('CakeDC/Users', 'Submit')); ?> Form->end() ?> diff --git a/src/Template/Users/resend_token_validation.ctp b/src/Template/Users/resend_token_validation.ctp index c64c38684..90b8aa9d7 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->input('reference', ['label' => __d('Users', 'Email or username')]); + echo $this->Form->input('reference', ['label' => __d('CakeDC/Users', 'Email or username')]); ?>
- Form->button(__d('Users', 'Submit')) ?> + Form->button(__d('CakeDC/Users', 'Submit')) ?> Form->end() ?>
diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp index 52cc6086e..7fb86c250 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->input('email') ?>
- Form->button(__d('Users', 'Submit')); ?> + Form->button(__d('CakeDC/Users', 'Submit')); ?> Form->end() ?> diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp index 17df81728..ab56a8164 100644 --- a/src/Template/Users/view.ctp +++ b/src/Template/Users/view.ctp @@ -10,71 +10,71 @@ */ ?>
-

+

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

id) ?>

-
+

id) ?>

-
+

username) ?>

-
+

email) ?>

-
+

first_name) ?>

-
+

last_name) ?>

-
+

token) ?>

-
+

api_token) ?>

-
+

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

-
+

token_expires) ?>

-
+

activation_date) ?>

-
+

tos_date) ?>

-
+

created) ?>

-
+

modified) ?>

From 505ba44d8f6e2d2c00ee59facfb3417d0cf32f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 2 Dec 2016 21:57:48 +0000 Subject: [PATCH 0539/1476] refs #383 add option to configure the api table and finder --- src/Auth/ApiKeyAuthenticate.php | 8 ++- .../TestCase/Auth/ApiKeyAuthenticateTest.php | 54 +++++++++++++++++-- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 2a7d358bf..68ed80fbf 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -38,6 +38,10 @@ class ApiKeyAuthenticate extends BaseAuthenticate 'field' => 'api_token', //require SSL to pass the token. You should always require SSL to use tokens for Auth 'require_ssl' => true, + //set a specific table for API auth, set as null to use Users.table + 'table' => null, + //set a specific finder for API auth, set as null to use Auth.authenticate.all.finder + 'finder' => null, ]; /** @@ -87,8 +91,8 @@ public function getUser(Request $request) } $this->_config['fields']['username'] = $this->config('field'); - $this->_config['userModel'] = Configure::read('Users.table'); - $this->_config['finder'] = 'all'; + $this->_config['userModel'] = $this->config('table') ?: Configure::read('Users.table'); + $this->_config['finder'] = $this->config('finder') ?: Configure::read('Auth.authenticate.all.finder') ?: 'all'; $result = $this->_query($apiKey)->first(); if (empty($result)) { diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php index 90a95c28e..e3ab0ec59 100644 --- a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -13,6 +13,7 @@ use CakeDC\Users\Auth\ApiKeyAuthenticate; use Cake\Controller\ComponentRegistry; +use Cake\Core\Configure; use Cake\Network\Request; use Cake\Network\Response; use Cake\TestSuite\TestCase; @@ -62,9 +63,9 @@ public function tearDown() */ public function testAuthenticateHappy() { - $request = new Request('/?api_key=yyy'); + $request = new Request('/?api_key=xxx'); $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-1', $result['username']); + $this->assertEquals('user-2', $result['username']); } /** @@ -85,6 +86,10 @@ public function testAuthenticateFail() $request = new Request('/?api_key='); $result = $this->apiKey->authenticate($request, new Response()); $this->assertFalse($result); + + $request = new Request('/?api_key=yyy'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); } /** @@ -140,10 +145,10 @@ public function testHeaderHappy() $request->expects($this->once()) ->method('header') ->with('api_key') - ->will($this->returnValue('yyy')); + ->will($this->returnValue('xxx')); $this->apiKey->config('type', 'header'); $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-1', $result['username']); + $this->assertEquals('user-2', $result['username']); } /** @@ -164,4 +169,45 @@ public function testAuthenticateHeaderFail() $result = $this->apiKey->authenticate($request, new Response()); $this->assertFalse($result); } + + /** + * test + * + * @return void + * @expectedException \BadMethodCallException + * @expectedExceptionMessage Unknown finder method "undefinedInConfig" + */ + public function testAuthenticateFinderConfig() + { + $this->apiKey->config('finder', 'undefinedInConfig'); + $request = new Request('/?api_key=xxx'); + $result = $this->apiKey->authenticate($request, new Response()); + } + + /** + * test + * + * @return void + * @expectedException \BadMethodCallException + * @expectedExceptionMessage Unknown finder method "undefinedFinderInAuth" + */ + public function testAuthenticateFinderAuthConfig() + { + Configure::write('Auth.authenticate.all.finder', 'undefinedFinderInAuth'); + $request = new Request('/?api_key=xxx'); + $result = $this->apiKey->authenticate($request, new Response()); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateDefaultAllFinder() + { + Configure::write('Auth.authenticate.all.finder', null); + $request = new Request('/?api_key=yyy'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertEquals('user-1', $result['username']); + } } From 964fb747d0c64254730d919c45d3381ad38f6b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 19 Dec 2016 13:20:43 +0000 Subject: [PATCH 0540/1476] fix changelog and installation docs --- .semver | 6 +++--- CHANGELOG.md | 6 ++++++ Docs/Documentation/Installation.md | 12 ++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.semver b/.semver index 7048659d7..2b479677e 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- -:major: 3 -:minor: 2 -:patch: 5 +:major: 4 +:minor: 0 +:patch: 0 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aaae87b8..cb47b90f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ Changelog Releases for CakePHP 3 ------------- +* 4.0.0 + * Add Google Authenticator + * Add improvements to SimpleRbac, like star to invert rules and `user.` prefix to match values from the user array + * Add `allowed` to manage the AuthLinkHelper when action is allowed + * Add option to configure the api table and finder in ApiKeyAuthenticate + * 3.2.5 * Fixed RegisterBehavior api, make getRegisterValidators public. diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 35a6b8967..d303fc9dd 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -34,6 +34,18 @@ composer require google/recaptcha:@stable NOTE: you'll need to configure the reCaptcha key and secret, check the [Configuration](Configuration.md) page for more details. +If you want to use Google Authenticator features... + +``` +composer require robthree/twofactorauth:"^1.5.2" +``` + +NOTE: you'll need to enable `Users.GoogleAuthenticator.login` + +``` +Configure::write('Users.GoogleAuthenticator.login', true); +``` + Creating Required Tables ------------------------ If you want to use the Users tables to store your users and social accounts: From d70064d03fade82dd497d574c5ab60f9eb6ccd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 21 Dec 2016 10:36:23 +0000 Subject: [PATCH 0541/1476] add facebook version note --- Docs/Documentation/SocialAuthenticate.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index 602611076..f8648a649 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -50,6 +50,12 @@ If email is required and the social network does not return the user email then In most situations you would not need to change any Oauth setting besides applications details. +For new facebook aps you must use the graphApiVersion 2.8 or greater: + +``` +Configure::write('OAuth.providers.facebook.options.graphApiVersion', 'v2.8'); +``` + User Helper --------------------- From a9256b4b30aae49ab4a708c9a300f6f6ed4044c6 Mon Sep 17 00:00:00 2001 From: Andrey Vystavkin Date: Thu, 22 Dec 2016 16:18:25 +0200 Subject: [PATCH 0542/1476] Adding Reset for Google Authenticator Token --- config/routes.php | 1 - src/Controller/Traits/LoginTrait.php | 6 +- .../Traits/PasswordManagementTrait.php | 50 ++++++++++++++ src/Template/Users/edit.ctp | 16 +++++ tests/Fixture/UsersFixture.php | 2 + .../Traits/PasswordManagementTraitTest.php | 65 +++++++++++++++++++ 6 files changed, 137 insertions(+), 3 deletions(-) diff --git a/config/routes.php b/config/routes.php index 97a7aa111..389f53290 100644 --- a/config/routes.php +++ b/config/routes.php @@ -29,4 +29,3 @@ Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); - diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index a39e58e4e..57842b7ac 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -238,11 +238,13 @@ public function verify() } if ($this->request->is('post')) { + $codeVerified = false; $verificationCode = $this->request->data('code'); $user = $this->request->session()->read('temporarySession'); + $entity = $this->getUsersTable()->get($user['id']); - if (array_key_exists('secret', $user)) { - $codeVerified = $this->GoogleAuthenticator->verifyCode($user['secret'], $verificationCode); + if (!empty($entity['secret'])) { + $codeVerified = $this->GoogleAuthenticator->verifyCode($entity['secret'], $verificationCode); } if ($codeVerified) { diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index baa28ad93..0d8a37c9f 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -133,4 +133,54 @@ public function requestResetPassword() $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); } } + + /** + * resetGoogleAuthenticator + * + * Resets Google Authenticator token by setting secret_verified + * to false. + * Currently allowed to be done either by superuser or user himself. + * + * @param mixed $id of the user record. + * @return mixed. + */ + public function resetGoogleAuthenticator($id = null) + { + $allowed = false; + $currentUser = !empty($this->Auth->user()) ? $this->Auth->user() : false; + + if (!$currentUser) { + $message = __d('CakeDC/User', 'Please login to the system'); + $this->Flash->error($message, 'auth'); + + return $this->redirect($this->Auth->config('loginAction')); + } + + if (true == $currentUser['is_superuser'] || $id == $currentUser['id']) { + $allowed = true; + } + + if (!$allowed) { + $message = __d('CakeDC/Users', 'You are not allowed to reset users Google Authenticator token'); + $this->Flash->error($message, 'default'); + } + + if ($this->request->is('post') && $allowed) { + try { + $query = $this->getUsersTable()->query(); + $query->update() + ->set(['secret_verified' => false, 'secret' => null]) + ->where(['id' => $id]); + $executed = $query->execute(); + + $message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset'); + $this->Flash->success($message, 'default'); + } catch (\Exception $e) { + $message = __d('CakeDC/Users', $e->getMessage()); + $this->Flash->error($message, 'default'); + } + } + + return $this->redirect($this->request->referer()); + } } diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index b789d73c5..4b9891c23 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -8,6 +8,7 @@ * @copyright Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +use Cake\Core\Configure; $Users = ${$tableAlias}; ?> @@ -55,4 +56,19 @@ $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 + ], [ + 'class' => 'btn btn-danger', + 'confirm' => __d('CakeDC/Users', 'Are you sure you want to reset token for user "{0}"?', $Users->username) + ]); + ?> +
+ diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index bcbc85458..ee6e4aa7b 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -113,6 +113,7 @@ class UsersFixture extends TestFixture 'api_token' => 'xxx', 'activation_date' => '2015-06-24 17:33:54', 'secret' => 'xxx', + 'secret_verified' => true, 'is_superuser' => true, 'tos_date' => '2015-06-24 17:33:54', 'active' => false, @@ -133,6 +134,7 @@ class UsersFixture extends TestFixture 'api_token' => 'Lorem ipsum dolor sit amet', 'activation_date' => '2015-06-24 17:33:54', 'secret' => 'Lorem ipsum dolor sit amet', + 'secret_verified' => true, 'is_superuser' => false, 'tos_date' => '2015-06-24 17:33:54', 'active' => true, diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index b681227be..e5d6a86c1 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -383,4 +383,69 @@ public function ensureUserActiveForResetPasswordFeature() [$defaultBehavior] ]; } + + public function testRequestGoogleAuthTokenResetWithoutSession() + { + $this->_mockRequestGet(true); + $this->_mockAuth(); + $this->_mockFlash(); + + $this->Trait->Auth->expects($this->any()) + ->method('user') + ->will($this->returnValue(null)); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Please login to the system'); + $this->Trait->resetGoogleAuthenticator(); + } + + /** + * @dataProvider ensureGoogleAuthenticatorResets + * + * @return void + */ + public function testRequestGoogleAuthTokenResetWithValidUser($userId, $entityId, $method, $msg) + { + $this->_mockRequestPost(); + $this->_mockFlash(); + + $user = $this->table->get($userId); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'config']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->Auth->expects($this->any()) + ->method('user') + ->will($this->returnValue($user)); + + $this->Trait->Flash->expects($this->any()) + ->method($method) + ->with($msg); + + $this->Trait->resetGoogleAuthenticator($entityId); + } + + public function ensureGoogleAuthenticatorResets() + { + $error = 'error'; + $success = 'success'; + $errorMsg = 'You are not allowed to reset users Google Authenticator token'; + $successMsg = 'Google Authenticator token was successfully reset'; + + return [ + //is_superuser = true. + ['00000000-0000-0000-0000-000000000003', null, $success, $successMsg], + //is_superuser = true. + ['00000000-0000-0000-0000-000000000001', null, $success, $successMsg], + //is_superuser = false, and not his profile. + ['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000001', $error, $errorMsg], + //is_superuser = false, editing own record. + ['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000004', $success, $successMsg], + //is_superuser = false, and no entity-id given. + ['00000000-0000-0000-0000-000000000004', null, $error, $errorMsg], + ]; + } } From 5481d4cdaac3945a9586574cf43ba21e2513a03e Mon Sep 17 00:00:00 2001 From: Manuel Tancoigne Date: Mon, 2 Jan 2017 16:54:41 +0100 Subject: [PATCH 0543/1476] Fixed two typos --- src/Template/Email/html/reset_password.ctp | 2 +- src/Template/Email/html/social_account_validation.ctp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp index 5f585c3ad..307c9c3cf 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -24,7 +24,7 @@ $activationUrl = [ Html->link(__d('CakeDC/Users', 'Reset your password here'), $activationUrl) ?>

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

, diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp index f6dbd7567..5dcd6dc71 100644 --- a/src/Template/Email/html/social_account_validation.ctp +++ b/src/Template/Email/html/social_account_validation.ctp @@ -29,7 +29,7 @@ ?>

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

, From 6254b3f7ba90aeb74f7d5c4adcc00b716f89b8ef Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 6 Jan 2017 07:50:28 -0500 Subject: [PATCH 0544/1476] Fix issue with twitter when email is returned --- src/Auth/SocialAuthenticate.php | 2 +- src/Model/Behavior/SocialBehavior.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 38be68a24..90bdffaf9 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -368,7 +368,7 @@ public function getUser(Request $request) { $data = $request->session()->read(Configure::read('Users.Key.Session.social')); $requestDataEmail = $request->data('email'); - if (!empty($data) && (!empty($data['email']) || !empty($requestDataEmail))) { + if (!empty($data) && empty($data['uid']) && (!empty($data['email']) || !empty($requestDataEmail))) { if (!empty($requestDataEmail)) { $data['email'] = $requestDataEmail; } diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index d0c666a30..d8b0816c3 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -44,7 +44,7 @@ public function socialLogin(array $data, array $options) { $reference = Hash::get($data, 'id'); $existingAccount = $this->_table->SocialAccounts->find() - ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => $data['provider']]) + ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => Hash::get($data, 'provider')]) ->contain(['Users']) ->first(); if (empty($existingAccount->user)) { From 52a28fe764c425addce88641c229da9a833a7acd Mon Sep 17 00:00:00 2001 From: Andrey Vystavkin Date: Mon, 9 Jan 2017 14:32:17 +0200 Subject: [PATCH 0545/1476] Removed checks for permissions and added minor fixes on urls --- config/routes.php | 13 ++++++++++++- src/Controller/Traits/PasswordManagementTrait.php | 12 +----------- src/Template/Users/edit.ctp | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/config/routes.php b/config/routes.php index 389f53290..4968e02fc 100644 --- a/config/routes.php +++ b/config/routes.php @@ -8,6 +8,7 @@ * @copyright Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +use Cake\Core\Configure; use Cake\Routing\Router; Router::plugin('CakeDC/Users', ['path' => '/users'], function ($routes) { @@ -25,7 +26,17 @@ 'controller' => 'SocialAccounts', 'action' => 'validate' ]); +// Google Authenticator related routes +if (Configure::read('Users.GoogleAuthenticator.login')) { + Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); + + Router::connect('/resetGoogleAuthenticator', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetGoogleAuthenticator' + ]); +} + Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); -Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 0d8a37c9f..f6318da99 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -146,7 +146,6 @@ public function requestResetPassword() */ public function resetGoogleAuthenticator($id = null) { - $allowed = false; $currentUser = !empty($this->Auth->user()) ? $this->Auth->user() : false; if (!$currentUser) { @@ -156,16 +155,7 @@ public function resetGoogleAuthenticator($id = null) return $this->redirect($this->Auth->config('loginAction')); } - if (true == $currentUser['is_superuser'] || $id == $currentUser['id']) { - $allowed = true; - } - - if (!$allowed) { - $message = __d('CakeDC/Users', 'You are not allowed to reset users Google Authenticator token'); - $this->Flash->error($message, 'default'); - } - - if ($this->request->is('post') && $allowed) { + if ($this->request->is('post')) { try { $query = $this->getUsersTable()->query(); $query->update() diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index 4b9891c23..e85c53d36 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -63,7 +63,7 @@ $Users = ${$tableAlias}; __d('CakeDC/Users', 'Reset Google Authenticator Token'), [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => '/resetGoogleAuthenticator', $Users->id + 'action' => 'resetGoogleAuthenticator', $Users->id ], [ 'class' => 'btn btn-danger', 'confirm' => __d('CakeDC/Users', 'Are you sure you want to reset token for user "{0}"?', $Users->username) From 255ff95e91c96039c3df0a17376acd712c52012b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 9 Jan 2017 12:36:34 +0000 Subject: [PATCH 0546/1476] propagate typo fixes --- src/Locale/es/Users.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Locale/es/Users.po b/src/Locale/es/Users.po index 10aa3bcd6..9748f8420 100644 --- a/src/Locale/es/Users.po +++ b/src/Locale/es/Users.po @@ -495,7 +495,7 @@ msgstr "Restablezca su contraseña aquí" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 msgid "" -"If the link is not correcly displayed, please copy the following address in " +"If the link is not correctly displayed, please copy the following address in " "your web browser {0}" msgstr "" "Si el enlace no se ve correctamente, por favor copie la siguente URL en su " From d76955e2a5ad7d0f31e7c18e9993298b9da0aca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 9 Jan 2017 12:37:31 +0000 Subject: [PATCH 0547/1476] propagate typo fixes --- src/Locale/fr_FR/Users.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Locale/fr_FR/Users.po b/src/Locale/fr_FR/Users.po index f998c4787..e26968b85 100644 --- a/src/Locale/fr_FR/Users.po +++ b/src/Locale/fr_FR/Users.po @@ -499,7 +499,7 @@ msgstr "Réinitialisez votre mot de passe ici" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 msgid "" -"If the link is not correcly displayed, please copy the following address in " +"If the link is not correctly displayed, please copy the following address in " "your web browser {0}" msgstr "" "Si le lien n'est pas correctement affiché, veuillez copier l'adresse " From c07b6c6f8c40721d59b6686bc813003a68b12e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 9 Jan 2017 12:38:10 +0000 Subject: [PATCH 0548/1476] propagate typo changes --- src/Locale/pt_BR/Users.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Locale/pt_BR/Users.po b/src/Locale/pt_BR/Users.po index 18830c397..276267c68 100644 --- a/src/Locale/pt_BR/Users.po +++ b/src/Locale/pt_BR/Users.po @@ -483,7 +483,7 @@ msgstr "Redefina sua senha aqui" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 msgid "" -"If the link is not correcly displayed, please copy the following address in " +"If the link is not correctly displayed, please copy the following address in " "your web browser {0}" msgstr "" "Se o link não estiver sendo exibido corretamente, por favor, copie o " From ec705e7449a3a9a0ef9baec80df5958fde9041de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 9 Jan 2017 12:38:36 +0000 Subject: [PATCH 0549/1476] propagate typo changes --- src/Locale/sv/Users.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Locale/sv/Users.po b/src/Locale/sv/Users.po index fbbc50d89..1f0d2f41f 100644 --- a/src/Locale/sv/Users.po +++ b/src/Locale/sv/Users.po @@ -492,7 +492,7 @@ msgstr "Återställ ditt lösenord här" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 msgid "" -"If the link is not correcly displayed, please copy the following address in " +"If the link is not correctly displayed, please copy the following address in " "your web browser {0}" msgstr "" "Om länken inte visas korrekt, vänligen kopiera följande adress till " From ffe93368b9dd4ed5f2e48419cc52e02cba5761d9 Mon Sep 17 00:00:00 2001 From: Andrey Vystavkin Date: Mon, 9 Jan 2017 14:48:06 +0200 Subject: [PATCH 0550/1476] not logged in user will be redirected to login automagically --- src/Controller/Traits/PasswordManagementTrait.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index f6318da99..450862c10 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -139,22 +139,12 @@ public function requestResetPassword() * * Resets Google Authenticator token by setting secret_verified * to false. - * Currently allowed to be done either by superuser or user himself. * * @param mixed $id of the user record. * @return mixed. */ public function resetGoogleAuthenticator($id = null) { - $currentUser = !empty($this->Auth->user()) ? $this->Auth->user() : false; - - if (!$currentUser) { - $message = __d('CakeDC/User', 'Please login to the system'); - $this->Flash->error($message, 'auth'); - - return $this->redirect($this->Auth->config('loginAction')); - } - if ($this->request->is('post')) { try { $query = $this->getUsersTable()->query(); From 6e0e0f2a4375f5b8481163e1de741642ed747041 Mon Sep 17 00:00:00 2001 From: Andrey Vystavkin Date: Mon, 9 Jan 2017 17:45:57 +0200 Subject: [PATCH 0551/1476] Adding permissions check for the Owners Token reset --- config/permissions.php | 15 +++++++++++++++ .../Traits/PasswordManagementTraitTest.php | 16 ---------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/config/permissions.php b/config/permissions.php index 0f8451259..ee6b207c1 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -63,6 +63,21 @@ 'controller' => 'Users', 'action' => ['register', 'edit', 'view'], ], + [ + 'role' => '*', + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetGoogleAuthenticator', + 'allowed' => function (array $user, $role, \Cake\Network\Request $request) { + $userId = \Cake\Utility\Hash::get($request->params, 'pass.0'); + $userRecord = \Cake\ORM\TableRegistry::get('Users')->get($userId); + if (!empty($userId) && !empty($userRecord)) { + return $userRecord->id === $user['id']; + } + + return false; + } + ], [ 'role' => 'user', 'plugin' => 'CakeDC/Users', diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index e5d6a86c1..681c4ef33 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -384,22 +384,6 @@ public function ensureUserActiveForResetPasswordFeature() ]; } - public function testRequestGoogleAuthTokenResetWithoutSession() - { - $this->_mockRequestGet(true); - $this->_mockAuth(); - $this->_mockFlash(); - - $this->Trait->Auth->expects($this->any()) - ->method('user') - ->will($this->returnValue(null)); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Please login to the system'); - $this->Trait->resetGoogleAuthenticator(); - } - /** * @dataProvider ensureGoogleAuthenticatorResets * From 56e0d0f4df39b467ca1f9b19d051b3134b3017b1 Mon Sep 17 00:00:00 2001 From: Andrey Vystavkin Date: Mon, 9 Jan 2017 18:40:22 +0200 Subject: [PATCH 0552/1476] Removing unnecessary user checks on the user record ownership --- config/permissions.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config/permissions.php b/config/permissions.php index ee6b207c1..a0525fa5b 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -70,9 +70,8 @@ 'action' => 'resetGoogleAuthenticator', 'allowed' => function (array $user, $role, \Cake\Network\Request $request) { $userId = \Cake\Utility\Hash::get($request->params, 'pass.0'); - $userRecord = \Cake\ORM\TableRegistry::get('Users')->get($userId); - if (!empty($userId) && !empty($userRecord)) { - return $userRecord->id === $user['id']; + if (!empty($userId) && !empty($user)) { + return $userId === $user['id']; } return false; From 7c40d80c525eee16d81cfec12f7a2e233dd510e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 9 Jan 2017 16:59:13 +0000 Subject: [PATCH 0553/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 2b479677e..0845a9533 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 4 -:minor: 0 +:minor: 1 :patch: 0 :special: '' From bca6c370d5663419f25ceb50300eb78a93b7390f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 9 Jan 2017 16:59:57 +0000 Subject: [PATCH 0554/1476] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb47b90f1..97c024cef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ Changelog Releases for CakePHP 3 ------------- +* 4.1.0 + * Add reset action for Google Authenticator + * 4.0.0 * Add Google Authenticator * Add improvements to SimpleRbac, like star to invert rules and `user.` prefix to match values from the user array From 7c3033f79c11aec11037e6c55c809b7ca2b5adc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 13 Jan 2017 15:02:03 +0000 Subject: [PATCH 0555/1476] add missing password field in users add --- .semver | 2 +- CHANGELOG.md | 3 +++ src/Template/Users/add.ctp | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.semver b/.semver index 0845a9533..76cdb6c3a 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 4 :minor: 1 -:patch: 0 +:patch: 1 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 97c024cef..680d59104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ Changelog Releases for CakePHP 3 ------------- +* 4.1.1 + * Add missing password field in add user + * 4.1.0 * Add reset action for Google Authenticator diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp index 3d83f6f4a..6e4e213ce 100644 --- a/src/Template/Users/add.ctp +++ b/src/Template/Users/add.ctp @@ -22,6 +22,7 @@ Form->input('username', ['label' => __d('CakeDC/Users', 'Username')]); echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->input('password', ['label' => __d('CakeDC/Users', 'Password')]); echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); echo $this->Form->input('active', [ From a5f2a2e15d400acb967915d23dffe9e16fef6fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 18 Jan 2017 03:02:34 +0000 Subject: [PATCH 0556/1476] fix copy --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f369f656c..4f7c7e035 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,6 @@ This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugin-st License ------- -Copyright 2015 Cake Development Corporation (CakeDC). All rights reserved. +Copyright 2017 Cake Development Corporation (CakeDC). All rights reserved. Licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) License. Redistributions of the source code included in this repository must retain the copyright notice found in each file. From 2bd53e7c1ae5d6e265e7af7d1bf86979fd0d74f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 18 Jan 2017 03:03:14 +0000 Subject: [PATCH 0557/1476] fix copy --- LICENSE.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 6ee7e8fc0..270499663 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,11 +1,11 @@ The MIT License -Copyright 2009-2014 +Copyright 2009-2017 Cake Development Corporation 1785 E. Sahara Avenue, Suite 490-423 Las Vegas, Nevada 89104 Phone: +1 702 425 5085 -http://cakedc.com +https://www.cakedc.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,4 +23,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file +DEALINGS IN THE SOFTWARE. From f5c3b45d066772b657592a403e9b6f8634426538 Mon Sep 17 00:00:00 2001 From: Andrej Griniuk Date: Fri, 20 Jan 2017 13:55:41 +0930 Subject: [PATCH 0558/1476] fix redirect after RememberMe --- src/Controller/Component/RememberMeComponent.php | 2 +- .../Controller/Component/RememberMeComponentTest.php | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index ae3c41201..33a085548 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -146,7 +146,7 @@ public function beforeFilter(Event $event) if (is_array($event->result)) { return $this->_registry->getController()->redirect($event->result); } - $url = $this->Auth->redirectUrl(); + $url = $this->request->here(false); return $this->_registry->getController()->redirect($url); } diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 701bdf587..c2c53c21e 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -150,12 +150,9 @@ public function testBeforeFilter() $this->rememberMeComponent->Auth->expects($this->once()) ->method('setUser') ->with($user); - $this->rememberMeComponent->Auth->expects($this->once()) - ->method('redirectUrl') - ->will($this->returnValue('/login')); $this->controller->expects($this->once()) ->method('redirect') - ->with('/login'); + ->with('/controller_posts/index'); $this->rememberMeComponent->beforeFilter($event); } From 069a4a807d108b490257fb9f6da639a09151ba0e Mon Sep 17 00:00:00 2001 From: Andrej Griniuk Date: Fri, 20 Jan 2017 23:42:01 +0930 Subject: [PATCH 0559/1476] update CHANGELOG.md and .semver --- .semver | 2 +- CHANGELOG.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.semver b/.semver index 76cdb6c3a..0dd3d3dd5 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 4 :minor: 1 -:patch: 1 +:patch: 2 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 680d59104..674a1103c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ Changelog Releases for CakePHP 3 ------------- +* 4.1.2 + * Fixed RememberMe redirect + * 4.1.1 * Add missing password field in add user From dd1fde8c4dda4be9982c89aac2112c4d03e7c541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 23 Jan 2017 12:12:14 +0000 Subject: [PATCH 0560/1476] fix isAuthorized to use global event manager to allow cells access it too --- src/Controller/Component/UsersAuthComponent.php | 3 ++- src/View/Helper/AuthLinkHelper.php | 3 ++- tests/TestCase/View/Helper/AuthLinkHelperTest.php | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index b3ee322fe..810ec39e8 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Component; +use Cake\Event\EventManager; use CakeDC\Users\Exception\BadConfigurationException; use Cake\Controller\Component; use Cake\Core\Configure; @@ -98,7 +99,7 @@ protected function _loadRememberMe() */ protected function _attachPermissionChecker() { - $this->_registry->getController()->eventManager()->on(self::EVENT_IS_AUTHORIZED, [], [$this, 'isUrlAuthorized']); + EventManager::instance()->on(self::EVENT_IS_AUTHORIZED, [], [$this, 'isUrlAuthorized']); } /** diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index 2b02c3fcb..ac1aedfdc 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -1,6 +1,7 @@ $url]); - $result = $this->_View->eventManager()->dispatch($event); + $result = EventManager::instance()->dispatch($event); return $result->result; } diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index 426f2f7f3..6aab0808c 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -1,6 +1,7 @@ getMockBuilder('Cake\Event\EventManager') ->setMethods(['dispatch']) ->getMock(); - $view->eventManager($eventManagerMock); + EventManager::instance($eventManagerMock); $this->AuthLink = new AuthLinkHelper($view); $result = new Event('dispatch-result'); $result->result = true; @@ -89,7 +90,7 @@ public function testLinkAuthorizedAllowedTrue() $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') ->setMethods(['dispatch']) ->getMock(); - $view->eventManager($eventManagerMock); + EventManager::instance($eventManagerMock); $this->AuthLink = new AuthLinkHelper($view); $result = new Event('dispatch-result'); $result->result = true; @@ -131,7 +132,7 @@ public function testIsAuthorized() $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') ->setMethods(['dispatch']) ->getMock(); - $view->eventManager($eventManagerMock); + EventManager::instance($eventManagerMock); $this->AuthLink = new AuthLinkHelper($view); $result = new Event('dispatch-result'); $result->result = true; From 772fb7921aa0c52f8f87cc462cee70b5b5a3a18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 23 Jan 2017 12:35:45 +0000 Subject: [PATCH 0561/1476] update travis to run local phpunit, fix cs --- .travis.yml | 4 ++-- src/Controller/Component/UsersAuthComponent.php | 2 +- src/View/Helper/AuthLinkHelper.php | 2 +- tests/TestCase/View/Helper/AuthLinkHelperTest.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97ee5fed5..3fb9ef8cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,9 +39,9 @@ before_script: - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" script: - - sh -c "if [ '$DEFAULT' = '1' ]; then phpunit --stderr; fi" + - sh -c "if [ '$DEFAULT' = '1' ]; then ./vendor/bin/phpunit --stderr; fi" - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p -n --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then phpunit --stderr --coverage-clover build/logs/clover.xml; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then ./vendor/bin/phpunit --stderr --coverage-clover build/logs/clover.xml; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then php vendor/bin/coveralls -c .coveralls.yml -v; fi" notifications: diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 810ec39e8..0eb75546f 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -11,11 +11,11 @@ namespace CakeDC\Users\Controller\Component; -use Cake\Event\EventManager; use CakeDC\Users\Exception\BadConfigurationException; use Cake\Controller\Component; use Cake\Core\Configure; use Cake\Event\Event; +use Cake\Event\EventManager; use Cake\Network\Request; use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index ac1aedfdc..69eed8070 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -1,9 +1,9 @@ Date: Mon, 23 Jan 2017 13:11:33 +0000 Subject: [PATCH 0562/1476] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 674a1103c..9b541f59c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ Changelog Releases for CakePHP 3 ------------- * 4.1.2 - * Fixed RememberMe redirect + * Fix RememberMe redirect + * Fix AuthLink rendering inside Cells * 4.1.1 * Add missing password field in add user From 24ec8d0033ecc1fa3d31fbb7f5cef7fbb1b4a26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Wed, 8 Feb 2017 21:14:43 +0100 Subject: [PATCH 0563/1476] Solves Issue #431 - Allow custom role on user registration * Added option --role in console users addUser too assign role * Added textfield role in add.ctp and edit.ctp * Added display of role in view.ctp * Updated test UserShellTest testSddUser and testAddUserWithNoParams to check for role. Since role is a protected field this had to be handled slightly awkward --- src/Shell/UsersShell.php | 10 +++++++--- src/Template/Users/add.ctp | 1 + src/Template/Users/edit.ctp | 1 + src/Template/Users/view.ctp | 2 ++ tests/TestCase/Shell/UsersShellTest.php | 7 +++++-- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 8c11632bc..b7e1e2b57 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -64,7 +64,8 @@ public function getOptionParser() ->addOptions([ 'username' => ['short' => 'u', 'help' => 'The username for the new user'], 'password' => ['short' => 'p', 'help' => 'The password for the new user'], - 'email' => ['short' => 'e', 'help' => 'The email for the new user'] + 'email' => ['short' => 'e', 'help' => 'The email for the new user'], + 'role' => ['short' => 'r', 'help' => 'The role for the new user'] ]); return $parser; @@ -84,20 +85,22 @@ public function addUser() $password = (empty($this->params['password']) ? $this->_generateRandomPassword() : $this->params['password']); $email = (empty($this->params['email']) ? $username . '@example.com' : $this->params['email']); + $role = (empty($this->params['role']) ? 'user' : $this->params['role']); $user = [ 'username' => $username, 'email' => $email, 'password' => $password, - 'active' => 1, + 'active' => 1 ]; $userEntity = $this->Users->newEntity($user); - $userEntity->role = 'user'; + $userEntity->role = $role; $savedUser = $this->Users->save($userEntity); $this->out(__d('CakeDC/Users', 'User added:')); $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); $this->out(__d('CakeDC/Users', 'Username: {0}', $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)); } @@ -126,6 +129,7 @@ public function addSuperuser() $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); $this->out(__d('CakeDC/Users', 'Username: {0}', $username)); $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('CakeDC/Users', 'Role: {0}', $savedUser->role)); $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); } else { $this->out(__d('CakeDC/Users', 'Superuser could not be added:')); diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp index 6e4e213ce..d2c23d8f7 100644 --- a/src/Template/Users/add.ctp +++ b/src/Template/Users/add.ctp @@ -25,6 +25,7 @@ echo $this->Form->input('password', ['label' => __d('CakeDC/Users', 'Password')]); echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->input('role', ['label' => __d('CakeDC/Users', 'Role')]); echo $this->Form->input('active', [ 'type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Active') diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index e85c53d36..476beb2ad 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -36,6 +36,7 @@ $Users = ${$tableAlias}; echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->input('role', ['label' => __d('CakeDC/Users', 'Role')]); echo $this->Form->input('token', ['label' => __d('CakeDC/Users', 'Token')]); echo $this->Form->input('token_expires', [ 'label' => __d('CakeDC/Users', 'Token expires') diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp index 8d3c08302..b9d513959 100644 --- a/src/Template/Users/view.ctp +++ b/src/Template/Users/view.ctp @@ -34,6 +34,8 @@ $Users = ${$tableAlias};

first_name) ?>

last_name) ?>

+
+

role) ?>

token) ?>

diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 34d9c7e35..ba3341b4e 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -82,7 +82,8 @@ public function testAddUser() 'email' => 'yeli.parra@gmail.com', 'active' => 1, ]; - + $role = 'tester'; + $this->Shell->expects($this->never()) ->method('_generateRandomUsername'); @@ -95,6 +96,7 @@ public function testAddUser() ->will($this->returnValue($user['username'])); $entityUser = $this->Users->newEntity($user); + $entityUser->role = $role; $this->Shell->Users->expects($this->once()) ->method('newEntity') @@ -109,7 +111,7 @@ public function testAddUser() ->with($entityUser) ->will($this->returnValue($userSaved)); - $this->Shell->runCommand(['addUser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email']]); + $this->Shell->runCommand(['addUser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email'], '--role=' . $role]); } /** @@ -141,6 +143,7 @@ public function testAddUserWithNoParams() ->will($this->returnValue($user['username'])); $entityUser = $this->Users->newEntity($user); + $entityUser->role = 'user'; $this->Shell->Users->expects($this->once()) ->method('newEntity') From 6d6df85fcb705184bbb8371969e21d07d8252650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Thu, 9 Feb 2017 08:03:22 +0100 Subject: [PATCH 0564/1476] Removed role filed in add and edit template Realised that it will not work since role field is protected. --- src/Template/Users/add.ctp | 1 - src/Template/Users/edit.ctp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp index d2c23d8f7..6e4e213ce 100644 --- a/src/Template/Users/add.ctp +++ b/src/Template/Users/add.ctp @@ -25,7 +25,6 @@ echo $this->Form->input('password', ['label' => __d('CakeDC/Users', 'Password')]); echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - echo $this->Form->input('role', ['label' => __d('CakeDC/Users', 'Role')]); echo $this->Form->input('active', [ 'type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Active') diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index 476beb2ad..e85c53d36 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -36,7 +36,6 @@ $Users = ${$tableAlias}; echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - echo $this->Form->input('role', ['label' => __d('CakeDC/Users', 'Role')]); echo $this->Form->input('token', ['label' => __d('CakeDC/Users', 'Token')]); echo $this->Form->input('token_expires', [ 'label' => __d('CakeDC/Users', 'Token expires') From 5253234119baf9c6da843b881bec711f331c65ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 10 Feb 2017 11:18:55 +0000 Subject: [PATCH 0565/1476] fix phpunit version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0372c618d..b30f86f1e 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "cakephp/cakephp": ">=3.2.9 <4.0.0" }, "require-dev": { - "phpunit/phpunit": "@stable", + "phpunit/phpunit": "^5.0", "cakephp/cakephp-codesniffer": "^2.0", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", From 0c50c7ce5cb3b83bebd6ee4ce3d585e48bc1bff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Fri, 10 Feb 2017 15:02:10 +0100 Subject: [PATCH 0566/1476] Removed trailing whitespace Fixed problems from automatic code check 86 | ERROR | [x] Whitespace found at end of line --- tests/TestCase/Shell/UsersShellTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index ba3341b4e..097331735 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -83,7 +83,7 @@ public function testAddUser() 'active' => 1, ]; $role = 'tester'; - + $this->Shell->expects($this->never()) ->method('_generateRandomUsername'); From 8a4d26c2812b0cae13c9793c4e50bfab3f53ad71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 13 Feb 2017 11:35:38 +0000 Subject: [PATCH 0567/1476] fix to enforce php5.6+ --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f7c7e035..307a25719 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Requirements ------------ * CakePHP 3.2.9+ -* PHP 5.5.9+ +* PHP 5.6+ Documentation ------------- From fa25d9c3505c9377d8a65aa240207bb74cc7da03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 13 Feb 2017 11:36:25 +0000 Subject: [PATCH 0568/1476] Update .travis.yml --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3fb9ef8cb..303ead93f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: php php: - - 5.5 - 5.6 - 7.0 + - 7.1 sudo: false @@ -20,10 +20,10 @@ matrix: fast_finish: true include: - - php: 5.5 + - php: 5.6 env: PHPCS=1 DEFAULT=0 - - php: 5.5 + - php: 5.6 env: COVERALLS=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' before_script: From 163bbd30702eb037f748e9d1ce86ea02ba7602da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 15 Feb 2017 11:18:16 +0000 Subject: [PATCH 0569/1476] refs #fix-tests-3.4 fix 3.4 unit tests --- .../Component/UsersAuthComponentTest.php | 186 +++++++++--------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index e6db00b79..1b1d2cb1f 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -66,12 +66,12 @@ public function setUp() Security::salt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); Configure::write('App.namespace', 'Users'); $this->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'method']) - ->getMock(); + ->setMethods(['is', 'method']) + ->getMock(); $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); $this->response = $this->getMockBuilder('Cake\Network\Response') - ->setMethods(['stop']) - ->getMock(); + ->setMethods(['stop']) + ->getMock(); $this->Controller = new Controller($this->request, $this->response); $this->Registry = $this->Controller->components(); $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); @@ -111,13 +111,13 @@ 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(); + ->setMethods(['_loadRememberMe', '_initAuth', '_loadSocialLogin', '_attachPermissionChecker']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->UsersAuth->expects($this->once()) - ->method('_initAuth'); + ->method('_initAuth'); $this->Controller->UsersAuth->expects($this->never()) - ->method('_loadRememberMe'); + ->method('_loadRememberMe'); $this->Controller->UsersAuth->initialize([]); } @@ -133,12 +133,12 @@ public function testIsUrlAuthorizedUserNotLoggedIn() 'url' => '/route', ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(false)); + ->method('user') + ->will($this->returnValue(false)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); $this->assertFalse($result); } @@ -220,9 +220,9 @@ public function testIsUrlAuthorizedNoUrl() { $event = new Event('event'); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); $this->assertFalse($result); } @@ -239,24 +239,24 @@ public function testIsUrlAuthorizedUrlRelativeString() 'url' => '/route', ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $request = new Request('/route'); - $request->params = [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - 'pass' => [], - '_matchedRoute' => '/route/*', - ]; + ->method('user') + ->will($this->returnValue(['id' => 1])); $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $request) - ->will($this->returnValue(true)); + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->params === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); $this->assertTrue($result); } @@ -274,11 +274,11 @@ public function testIsUrlAuthorizedMissingRouteString() 'url' => '/missingRoute', ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->never()) - ->method('user'); + ->method('user'); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); } @@ -298,11 +298,11 @@ public function testIsUrlAuthorizedMissingRouteArray() ], ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->never()) - ->method('user'); + ->method('user'); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); } @@ -318,24 +318,24 @@ public function testIsUrlAuthorizedUrlAbsoluteForCurrentAppString() 'url' => Router::fullBaseUrl() . '/route', ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $request = new Request('/route'); - $request->params = [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - 'pass' => [], - '_matchedRoute' => '/route/*', - ]; + ->method('user') + ->will($this->returnValue(['id' => 1])); $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $request) - ->will($this->returnValue(true)); + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->params === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); $this->assertTrue($result); } @@ -352,24 +352,24 @@ public function testIsUrlAuthorizedUrlRelativeForCurrentAppString() 'url' => 'route', ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $request = new Request('/route'); - $request->params = [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - 'pass' => [], - '_matchedRoute' => '/route/*', - ]; + ->method('user') + ->will($this->returnValue(['id' => 1])); $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $request) - ->will($this->returnValue(true)); + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->params === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); $this->assertTrue($result); } @@ -386,11 +386,11 @@ public function testIsUrlAuthorizedUrlAbsoluteForOtherAppString() 'url' => 'http://example.com', ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->never()) - ->method('user'); + ->method('user'); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); $this->assertTrue($result); } @@ -412,24 +412,24 @@ public function testIsUrlAuthorizedUrlArray() ], ]; $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $request = new Request('/route/pass-one'); - $request->params = [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - 'pass' => ['pass-one'], - '_matchedRoute' => '/route/*', - ]; + ->method('user') + ->will($this->returnValue(['id' => 1])); $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $request) - ->will($this->returnValue(true)); + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->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); } From f9f4f80b6b351dee78b666e5a448d0ce532a5b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Wed, 15 Feb 2017 21:33:40 +0100 Subject: [PATCH 0570/1476] add parameters to UserShell::addSuperuser - issue #497 added same parameters to addSuperusers that already exists in addUser method (-e, -p, -r, -u) updated tests in UsersShellTest to test addSuperuser with and without parameters. addSuperuser and addUser are now more or less a repetition and should be rewritten to keep it DRY. But I'll save that work for a rainy day. --- src/Shell/UsersShell.php | 18 +++++---- tests/TestCase/Shell/UsersShellTest.php | 52 ++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index b7e1e2b57..d47a737a7 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -98,7 +98,7 @@ public function addUser() $savedUser = $this->Users->save($userEntity); $this->out(__d('CakeDC/Users', 'User added:')); $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('CakeDC/Users', 'Username: {0}', $username)); + $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)); @@ -111,23 +111,27 @@ public function addUser() */ public function addSuperuser() { - $username = $this->Users->generateUniqueUsername('superadmin'); - $password = $this->_generateRandomPassword(); + $username = (empty($this->params['username']) ? + 'superadmin' : $this->params['username']); + $password = (empty($this->params['password']) ? + $this->_generateRandomPassword() : $this->params['password']); + $email = (empty($this->params['email']) ? $username . '@example.com' : $this->params['email']); + $role = (empty($this->params['role']) ? 'superuser' : $this->params['role']); $user = [ - 'username' => $username, - 'email' => $username . '@example.com', + 'username' => $this->Users->generateUniqueUsername($username), + 'email' => $email, 'password' => $password, 'active' => 1, ]; $userEntity = $this->Users->newEntity($user); $userEntity->is_superuser = true; - $userEntity->role = 'superuser'; + $userEntity->role = $role; $savedUser = $this->Users->save($userEntity); if (!empty($savedUser)) { $this->out(__d('CakeDC/Users', 'Superuser added:')); $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('CakeDC/Users', 'Username: {0}', $username)); + $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)); diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 097331735..11b96c8b1 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -70,7 +70,7 @@ public function tearDown() /** * Add user test - * Adding user with username, email and password + * Adding user with username, email, password and role * * @return void */ @@ -164,11 +164,58 @@ public function testAddUserWithNoParams() } /** - * Add superadmin user + * Add user test + * Adding user with username, email, password and role * * @return void */ public function testAddSuperuser() + { + $user = [ + 'username' => 'yeliparra', + 'password' => '123', + 'email' => 'yeli.parra@gmail.com', + 'active' => 1, + ]; + $role = 'tester'; + + $this->Shell->expects($this->never()) + ->method('_generateRandomUsername'); + + $this->Shell->expects($this->never()) + ->method('_generateRandomPassword'); + + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with($user['username']) + ->will($this->returnValue($user['username'])); + + $entityUser = $this->Users->newEntity($user); + $entityUser->role = $role; + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + $userSaved->is_superuser = true; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + $this->Shell->runCommand(['addSuperuser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email'], '--role=' . $role]); + } + + /** + * Add superadmin user + * + * @return void + */ + public function testAddSuperuserWithNoParams() { $this->Shell->Users->expects($this->once()) ->method('generateUniqueUsername') @@ -205,6 +252,7 @@ public function testAddSuperuser() $this->Shell->runCommand(['addSuperuser']); } + /** * Reset all passwords * From f2e3e36e3acc6a6531c8e39e6dc006accd061814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE?= Date: Thu, 16 Feb 2017 22:20:40 +0100 Subject: [PATCH 0571/1476] You can add class, label, title with UserHelper like $this->User->socialLoginList(['facebook' => ['label' => 'custom label']]) With this you can also use btn-social-icon from bootstrap-social etc. It also read options from Configure::write() for each provider if its set (class, title, label...) --- src/View/Helper/UserHelper.php | 88 +++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 82c37e8d7..48e3554e7 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -40,44 +40,56 @@ class UserHelper extends Helper * @param array $options options * @return string */ - public function socialLogin($name, $options = []) - { - if (empty($options['label'])) { - $options['label'] = __d('CakeDC/Users', 'Sign in with'); - } - $icon = $this->Html->tag('i', '', [ - 'class' => __d('CakeDC/Users', 'fa fa-{0}', strtolower($name)), - ]); - $providerTitle = __d('CakeDC/Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)); - $providerClass = __d('CakeDC/Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', strtolower($name)); - - return $this->Html->link($icon . $providerTitle, "/auth/$name", [ - 'escape' => false, 'class' => $providerClass - ]); - } - - /** - * All available Social Login Icons - * - * @return array Links to Social Login Urls - */ - public function socialLoginList() - { - if (!Configure::read('Users.Social.login')) { - return []; - } - $outProviders = []; - $providers = Configure::read('OAuth.providers'); - foreach ($providers as $provider => $options) { - if (!empty($options['options']['redirectUri']) && - !empty($options['options']['clientId']) && - !empty($options['options']['clientSecret'])) { - $outProviders[] = $this->socialLogin($provider); - } - } - - return $outProviders; - } + public function socialLogin($name, $options = []) + { + if (empty($options['label'])) { + $options['label'] = __d('CakeDC/Users', 'Sign in with'); + } + $icon = $this->Html->tag('i', '', [ + 'class' => __d('CakeDC/Users', 'fa fa-{0}', strtolower($name)), + ]); + + if (isset($options['title'])) { + $providerTitle = $options['title']; + } else { + $providerTitle = __d('CakeDC/Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)); + } + + $providerClass = __d('CakeDC/Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', strtolower($name)); + + return $this->Html->link($icon . $providerTitle, "/auth/$name", [ + 'escape' => false, 'class' => $providerClass + ]); + } + + /** + * All available Social Login Icons + * + * @param array $providerOptions Provider link options. + * @return array Links to Social Login Urls + */ + public function socialLoginList(array $providerOptions = []) + { + if (!Configure::read('Users.Social.login')) { + return []; + } + $outProviders = []; + $providers = Configure::read('OAuth.providers'); + foreach ($providers as $provider => $options) { + if (!empty($options['options']['redirectUri']) && + !empty($options['options']['clientId']) && + !empty($options['options']['clientSecret'])) { + + if (isset($providerOptions[$provider])) { + $options['options'] = Hash::merge($options['options'], $providerOptions[$provider]); + } + + $outProviders[] = $this->socialLogin($provider, $options['options']); + } + } + + return $outProviders; + } /** * Logout link From 8d4766483ad5a2d15b78b21528d7fb50b93f4074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blaz=CC=8C=20Smolnikar?= Date: Mon, 20 Feb 2017 18:23:30 +0100 Subject: [PATCH 0572/1476] Fixing phpcs issues --- src/View/Helper/UserHelper.php | 102 ++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 48e3554e7..fdefd4431 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -40,56 +40,56 @@ class UserHelper extends Helper * @param array $options options * @return string */ - public function socialLogin($name, $options = []) - { - if (empty($options['label'])) { - $options['label'] = __d('CakeDC/Users', 'Sign in with'); - } - $icon = $this->Html->tag('i', '', [ - 'class' => __d('CakeDC/Users', 'fa fa-{0}', strtolower($name)), - ]); - - if (isset($options['title'])) { - $providerTitle = $options['title']; - } else { - $providerTitle = __d('CakeDC/Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)); - } - - $providerClass = __d('CakeDC/Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', strtolower($name)); - - return $this->Html->link($icon . $providerTitle, "/auth/$name", [ - 'escape' => false, 'class' => $providerClass - ]); - } - - /** - * All available Social Login Icons - * - * @param array $providerOptions Provider link options. - * @return array Links to Social Login Urls - */ - public function socialLoginList(array $providerOptions = []) - { - if (!Configure::read('Users.Social.login')) { - return []; - } - $outProviders = []; - $providers = Configure::read('OAuth.providers'); - foreach ($providers as $provider => $options) { - if (!empty($options['options']['redirectUri']) && - !empty($options['options']['clientId']) && - !empty($options['options']['clientSecret'])) { - - if (isset($providerOptions[$provider])) { - $options['options'] = Hash::merge($options['options'], $providerOptions[$provider]); - } - - $outProviders[] = $this->socialLogin($provider, $options['options']); - } - } - - return $outProviders; - } + public function socialLogin($name, $options = []) + { + if (empty($options['label'])) { + $options['label'] = __d('CakeDC/Users', 'Sign in with'); + } + $icon = $this->Html->tag('i', '', [ + 'class' => __d('CakeDC/Users', 'fa fa-{0}', strtolower($name)), + ]); + + if (isset($options['title'])) { + $providerTitle = $options['title']; + } else { + $providerTitle = __d('CakeDC/Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)); + } + + $providerClass = __d('CakeDC/Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', strtolower($name)); + + return $this->Html->link($icon . $providerTitle, "/auth/$name", [ + 'escape' => false, 'class' => $providerClass + ]); + } + + /** + * All available Social Login Icons + * + * @param array $providerOptions Provider link options. + * @return array Links to Social Login Urls + */ + public function socialLoginList(array $providerOptions = []) + { + if (!Configure::read('Users.Social.login')) { + return []; + } + $outProviders = []; + $providers = Configure::read('OAuth.providers'); + foreach ($providers as $provider => $options) { + if (!empty($options['options']['redirectUri']) && + !empty($options['options']['clientId']) && + !empty($options['options']['clientSecret']) + ) { + if (isset($providerOptions[$provider])) { + $options['options'] = Hash::merge($options['options'], $providerOptions[$provider]); + } + + $outProviders[] = $this->socialLogin($provider, $options['options']); + } + } + + return $outProviders; + } /** * Logout link @@ -102,7 +102,7 @@ public function logout($message = null, $options = []) { return $this->AuthLink->link(empty($message) ? __d('CakeDC/Users', 'Logout') : $message, [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout' - ], $options); + ], $options); } /** From a54af9d2f056c36297cebdb173e5f95d34c2ade2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Mon, 20 Feb 2017 19:05:52 +0100 Subject: [PATCH 0573/1476] Corrected email domains in UserShellTest Switched to example.com domains --- composer.json | 2 +- tests/TestCase/Shell/UsersShellTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index b30f86f1e..bb7063b97 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": ">=3.2.9 <4.0.0" + "cakephp/cakephp": ">=3.2.9 <3.4.0" }, "require-dev": { "phpunit/phpunit": "^5.0", diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 11b96c8b1..a6a7fde92 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -79,7 +79,7 @@ public function testAddUser() $user = [ 'username' => 'yeliparra', 'password' => '123', - 'email' => 'yeli.parra@gmail.com', + 'email' => 'yeli.parra@example.com', 'active' => 1, ]; $role = 'tester'; @@ -174,7 +174,7 @@ public function testAddSuperuser() $user = [ 'username' => 'yeliparra', 'password' => '123', - 'email' => 'yeli.parra@gmail.com', + 'email' => 'yeli.parra@example.com', 'active' => 1, ]; $role = 'tester'; From aa75deeb5e4788266133a5dc6b9ab2abc1aa432e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 20 Feb 2017 18:21:45 +0000 Subject: [PATCH 0574/1476] fallback to robthree/twofactorauth 1.5 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bb7063b97..f7fdb5c2c 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "league/oauth2-google": "@stable", "league/oauth2-linkedin": "@stable", "google/recaptcha": "@stable", - "robthree/twofactorauth": "^1.5.2" + "robthree/twofactorauth": "~1.5.0" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", From d57c54436431eb0de3ea8d8110aef1f3fe29485c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Mon, 20 Feb 2017 19:56:30 +0100 Subject: [PATCH 0575/1476] Refactored UserShell to make it DRY addUser and addSuperuser where repeats. Moved most of the logic to a new method called _createUser Sorry for one more commit on this ;) --- src/Shell/UsersShell.php | 123 ++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 55 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index d47a737a7..49238ab5e 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -78,30 +78,11 @@ public function getOptionParser() */ public function addUser() { - $username = (empty($this->params['username']) ? - $this->_generateRandomUsername() : $this->params['username']); - - $username = $this->Users->generateUniqueUsername($username); - $password = (empty($this->params['password']) ? - $this->_generateRandomPassword() : $this->params['password']); - $email = (empty($this->params['email']) ? $username . '@example.com' : $this->params['email']); - $role = (empty($this->params['role']) ? 'user' : $this->params['role']); - $user = [ - 'username' => $username, - 'email' => $email, - 'password' => $password, - 'active' => 1 - ]; - - $userEntity = $this->Users->newEntity($user); - $userEntity->role = $role; - $savedUser = $this->Users->save($userEntity); - $this->out(__d('CakeDC/Users', 'User added:')); - $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('CakeDC/Users', 'Username: {0}', $savedUser->username)); - $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); - $this->out(__d('CakeDC/Users', 'Role: {0}', $savedUser->role)); - $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); + $this->_createUser([ + 'role' => 'user' + ], + false + ); } /** @@ -111,37 +92,13 @@ public function addUser() */ public function addSuperuser() { - $username = (empty($this->params['username']) ? - 'superadmin' : $this->params['username']); - $password = (empty($this->params['password']) ? - $this->_generateRandomPassword() : $this->params['password']); - $email = (empty($this->params['email']) ? $username . '@example.com' : $this->params['email']); - $role = (empty($this->params['role']) ? 'superuser' : $this->params['role']); - $user = [ - 'username' => $this->Users->generateUniqueUsername($username), - 'email' => $email, - 'password' => $password, - 'active' => 1, - ]; - - $userEntity = $this->Users->newEntity($user); - $userEntity->is_superuser = true; - $userEntity->role = $role; - $savedUser = $this->Users->save($userEntity); - if (!empty($savedUser)) { - $this->out(__d('CakeDC/Users', 'Superuser added:')); - $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('CakeDC/Users', 'Username: {0}', $savedUser->username)); - $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); - $this->out(__d('CakeDC/Users', 'Role: {0}', $savedUser->role)); - $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); - } else { - $this->out(__d('CakeDC/Users', 'Superuser could not be added:')); - - collection($userEntity->errors())->each(function ($error, $field) { - $this->out(__d('CakeDC/Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); - }); - } + $this->_createUser([ + 'username' => 'superadmin', + 'role' => 'superuser', + 'is_superuser' => true + ], + true + ); } /** @@ -295,6 +252,62 @@ protected function _changeUserActive($active) return $this->_updateUser($username, $data); } + /** + * Create a new user or superuser + * + * @param bool $is_superuser is superuser value + * @param array $template template with deafault user values + * @return void + */ + public function _createUser($template) + { + if (!empty($this->params['username'])) { + $username = $this->params['username']; + } else { + $username = !empty($template['username']) ? + $template['username'] : $this->_generateRandomUsername(); + } + + $password = (empty($this->params['password']) ? + $this->_generateRandomPassword() : $this->params['password']); + $email = (empty($this->params['email']) ? + $username . '@example.com' : $this->params['email']); + $role = (empty($this->params['role']) ? + $template['role'] : $this->params['role']); + + $user = [ + 'username' => $this->Users->generateUniqueUsername($username), + 'email' => $email, + 'password' => $password, + 'active' => 1, + ]; + + $userEntity = $this->Users->newEntity($user); + $userEntity->is_superuser = empty($template['is_superuser']) ? + false : $template['is_superuser']; + $userEntity->role = $role; + $savedUser = $this->Users->save($userEntity); + + if (!empty($savedUser)) { + if ($savedUser->is_superuser) { + $this->out(__d('CakeDC/Users', 'Superuser added:')); + } else { + $this->out(__d('CakeDC/Users', 'User added:')); + } + $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); + $this->out(__d('CakeDC/Users', 'Username: {0}', $savedUser->username)); + $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('CakeDC/Users', 'Role: {0}', $savedUser->role)); + $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); + } else { + $this->out(__d('CakeDC/Users', 'User could not be added:')); + + collection($userEntity->errors())->each(function ($error, $field) { + $this->out(__d('CakeDC/Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); + }); + } + } + /** * Update user by username * From d4af2fcb896c00c963de44edee43540ccb562c3a Mon Sep 17 00:00:00 2001 From: Andrey Vystavkin Date: Mon, 20 Feb 2017 21:02:10 +0200 Subject: [PATCH 0576/1476] removing obsolete args due to 1.6 2fa update --- config/users.php | 4 +--- src/Controller/Component/GoogleAuthenticatorComponent.php | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/config/users.php b/config/users.php index 0b8627148..486309570 100644 --- a/config/users.php +++ b/config/users.php @@ -69,9 +69,7 @@ // QR-code provider (more on this later) 'qrcodeprovider' => null, // Random Number Generator provider (more on this later) - 'rngprovider' => null, - // Key used for encrypting the user credentials, leave this false to use Security.salt - 'encryptionKey' => false + 'rngprovider' => null ], 'Profile' => [ //Allow view other users profiles diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php index c9c9034a9..ddebb49f0 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -34,8 +34,7 @@ public function initialize(array $config) Configure::read('Users.GoogleAuthenticator.period'), Configure::read('Users.GoogleAuthenticator.algorithm'), Configure::read('Users.GoogleAuthenticator.qrcodeprovider'), - Configure::read('Users.GoogleAuthenticator.rngprovider'), - Configure::read('Users.GoogleAuthenticator.encryptionKey') + Configure::read('Users.GoogleAuthenticator.rngprovider') ); } } From 261fdc8c87c8b7981b3993b4faaa8633fcf4cbce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 21 Feb 2017 09:42:47 +0000 Subject: [PATCH 0577/1476] update to robthree/twofactorauth 1.6 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f7fdb5c2c..e74604e02 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "league/oauth2-google": "@stable", "league/oauth2-linkedin": "@stable", "google/recaptcha": "@stable", - "robthree/twofactorauth": "~1.5.0" + "robthree/twofactorauth": "~1.6.0" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", From 9255688b839c279b18458295bcc61641d0040176 Mon Sep 17 00:00:00 2001 From: Livio Ribeiro Date: Sun, 26 Feb 2017 17:46:21 -0300 Subject: [PATCH 0578/1476] Update brazilian portuguese translations --- src/Locale/pt_BR/Users.mo | Bin 14231 -> 15158 bytes src/Locale/pt_BR/Users.po | 368 +++++++++++++++++++++++--------------- 2 files changed, 221 insertions(+), 147 deletions(-) diff --git a/src/Locale/pt_BR/Users.mo b/src/Locale/pt_BR/Users.mo index 12049d19a9a0cf269b75d83cd67fdcd9665fb602..35582e87e17ad794b8d28f06efd5bba48694ea0c 100644 GIT binary patch delta 4770 zcmY+_3v?9K9mnyzgggik9^sJ?3d1V_Ng#=YH{}(e2m&U6A_mwblVl~?iTel?t*e3+ z1Zj1US80&~LXc8n8x)R|+SErCdpOqGR*P0zt)AAlo_dZIOX>HwJK@kd`OoLh-I+W0 z{_nk$UC!y2*n7P@KWRA55Ce%nryBDW9`DMDV|Nc@y5Jt{hX*ki&*C6_3ybkz-u3XF z#-wvS8+G3T9Dp_s#s`pF%~MHZ=2;49RQwDx@D&_`7cmR3p*oP&%b0x3LES$c)zDne z);aN;GF=O7Qput|k{`d*%Mqlsbi_?&#n4Z`N`=LfQ z8g>613H=IVkY%_urD6+uFrbDglW9rT%^zme~aqzJGcffqaSByCr5f1%eiht zz3>VS!*29yEEc0Wv<8cDJt}jpo^jN`&Y=eUbBuMT@GA=H=^s!d{R=9^pW;yb9B;$^ z3}YS!P*Zi%^DK7bx*gTAi>P)lqXzU(R6GAhJ(tHq(%Ko`kNm4Jn~JYtHENC@Ks9g# z7hxMt$IcAzb}Yw9xDRviZKRLpA2prVPHJ~L@{_4Tt*s~);GrDye-niZRH$cP zAb*JoR_bz@Xk8CO{XP}7xaOczxE$4RHEOYLz|pt`H6?9m;fJUfrm+>Y%f_JET@a(7 z?NQ5V6zW>3Y(@3_G>*WxP^Zoa0#3m{;&2>D zFDRPWObTSzRG~%^LA`JrDpjYDKl1@6-fjMi>Ul12)pMnu^HFPO4QlG@km)uN)cud5 zg$KRge}RR(-@HjdJ-db)!4wvRdR&fbpaGS-`%#POY2?qG;H3NB@caxlC4C1Q!^SW} zP#G&jP0buE!lkHzK7<3b|Mya0rI;vM*RT!i!3JLKlk_0h&JO)Jc4X}^NCmAjb5rl zqfwcfhin{Ek5h3wDzmR+OfUSHLT~IeE;-kIQTucRYHnv>ADoL>xDqYA8(BVPD|W-v zsE)MbEc^&HfKkj3-yBnlIk+78$v9=?Ukx6jLL-W!8hjI#qN~^khml8ha3c1^1*nGZ zLX9Yjeesl6|0=4z4?N9;WXA@ho}Y!9s>%uEe^arEOC*bi64Sn}G>&8Spu@Z5+Cx!#5; z_?BI5Z8biAYC7UO2#~e z_bUH&6bih`9{5AzQKHJLyOD2k5xAkEgmMa@X|#zuiT=b~LdQ3V@5lzHE;vwR8Vicj{S)FDsnQuj$wRSK*F)Q1b?vDhVpjGS6>T$7$ z6RZn_nyhAjIK0jY)y8}Fyvdh7HxLR(tYCb6uaAAHeihx^?AZefqG3A}^f%cBRv>6O z&1xoW)%qiTw=(;Tdo6ou{FXj>DQWeAaKsL|)%~YtEa_->SO1~Du7UcXo?I7*G`P>@ zY)fBUsi$psX70ZD)!aH?c0(X+)dlRvT8l!+z9$+8xvTS<((U!lfsh@Jzm(TKrKrXq z3_1~u&RCHK+p39%LUu56eF&C6oTv}l>ntbeUKmtXXf;I{M59x0InfB2py^~EEx)DP zG%m|uQ{zN~k@(d?`+e?iYh&4jqTf25n2-`hPuVqAPh{z{*F zte|r64fEn>D8Yzr1xbR_+By?o%0ycOMjcJ*QjthN$RBcFES%E4 z!VcRJUY5M!tHN7-T^2g^RMa?4?z}O(GZ?GiTDrK>eQ(S&@xx>9_vOxEime)dQ?p~W zw^~khC{XW@w8ujMcSy;m`0kSZDTTrIgO1hg)Y{~iw*1MlSpG=V->8-yE9kU%wQh0Q ytg;r{s+w2l#2L5+C(ys?rJ@e+K_+kZ;&glfHIpY$H@tw! z_>T3mz5W?0S&4j^hMA~#IjZAojKNyeKySotxE6i%Z_ZHB%#u?05_6DCrUmn`7t8So zY9Mc-2mgc`cxq~N#@VPD&cp<(fRMhWgVJj|24e+TD z6|M0zn1k=*BK!iiyXVuJc5yQ@Nz;oO`F>P~!>EkBg&OF;kUuknn;3(sMBP`9+5@+u zmZlZ8Swp>4^uvAV#$hbQ*KrYkf=X>UPuD;fqHf%T%1{?-ZyZ7GiQ}l>{o49xRLZ9? zeYTZJLuIH4Iqo6jrBcR)Rj8TuqGoUa+2CfxwqHWc3qxMV^y=!I_sP;0{ zd%%ZNaR-uA(~UK_AIo+A-=@N!`41lq)?~8|I)>GF3x-g;_&rpI1@7qDEkkv%8a1GG zSc^BKGBSuH&m2RYieF*KWz1#N#9BB?DIqF5sb~QG=*1D#NIyh9Xxx4uM_zSGW})_m z7xkbmsI|S*ws)eQ(~rvJtEkO3hWYpx)aFd$At9|zIu$t+wWf1WKWMVoH={aeL!~x| z8rVV9?jA&vV@{*)dlR+BzenBo0cr_8LjCSjWYx^{eDbd~t7KT3agDVZ_2%k9%{YV; zZ~&F+L5#uUsDTXQ?RWXXr&L z^Qm0Ga!gi9+E zG=>unLoTo#~vfLaotOOvJr75eHBi8A6g^p20mhh8nPs(MK|e>ZlKEaTqyB z<|F%kJZZ_&`7ffPl&nDZhwit}&<>Ops-X3~dx(37Z)`~lVB7np*H=rTiXMUcNC<4H`$r%@>$#hY*p zwe}TkC}p%A-Pn(7@G11;XXwLCRpei5{W1$b1>Z%bX3Y9AuBCkywaJz)hz?{WDkGif zLX}NXBAaw8^?L~onlVMn9zL~S_7NwEBSekX|Jssn8#_^{dW4uttR|WXZ9tXoD3RNT zs1MurZmY7ff%pkgN3eB_Lwu7^=_i!&QuY4?p`sZnog9S7f0H^<>DowqRUW7EKueyEloLPTWHD z5-NIkAB)tCc^G%ux=0|rw#~ta?58fsikx1r9vHn7TVgf_QIJ8>&X-zQq^H8(D^^;~NVo+9=V2Z_kuI!xs;qLBCoF+w~< z_=s|1CUKnj|MFdXp#rOj3}OcnKAx27a$cMEM)>jMLRa{ADVJT&%hQ)SIcYz4E~eFm zOVd+gow`hK_`%F9m-F29{mz=KBeB8G7UxWEMtCf%!{zw0+rsZny6x#Girot5Zvrp~?+jwx8~a#j~MJMWaG z#sq@S^M&~_qsN@P3LC@TqPZ@ow|KQPR(#fZwxltfSb8efd8NEMcD=jDsrBT9i#)|H zXLH42XT0KcUah;^A87TteSw~~+kEc8=!u|vdoZxW-{m*l5bW>=oE%R^`1Q)IE~jSR Yz2S579*%Ve7A^`Wc+a_t6=s{jB1 diff --git a/src/Locale/pt_BR/Users.po b/src/Locale/pt_BR/Users.po index 276267c68..591c020cf 100644 --- a/src/Locale/pt_BR/Users.po +++ b/src/Locale/pt_BR/Users.po @@ -4,40 +4,40 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2016-04-19 10:17-0300\n" -"PO-Revision-Date: 2016-04-19 10:37-0300\n" -"Last-Translator: André Teixeira \n" +"POT-Creation-Date: 2017-02-26 16:21-0300\n" +"PO-Revision-Date: 2017-02-26 17:44-0300\n" +"Last-Translator: Livio Ribeiro \n" "Language-Team: CakeDC \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 1.8.7\n" +"X-Generator: Poedit 1.8.7.1\n" -#: Auth/ApiKeyAuthenticate.php:55 +#: Auth/ApiKeyAuthenticate.php:73 msgid "Type {0} is not valid" msgstr "Tipo {0} não é válido" -#: Auth/ApiKeyAuthenticate.php:59 +#: Auth/ApiKeyAuthenticate.php:77 msgid "Type {0} has no associated callable" msgstr "Tipo {0} não tem chamada associada" -#: Auth/ApiKeyAuthenticate.php:68 +#: Auth/ApiKeyAuthenticate.php:86 msgid "SSL is required for ApiKey Authentication" msgstr "SSL é requerido para autenticação por chave da API." -#: Auth/SimpleRbacAuthorize.php:141 +#: Auth/SimpleRbacAuthorize.php:142 msgid "" "Missing configuration file: \"config/{0}.php\". Using default permissions" msgstr "" "Arquivo de configuração ausente: \"config/{0}.php\". Usando permissões padrão" -#: Auth/SocialAuthenticate.php:410 +#: Auth/SocialAuthenticate.php:432 msgid "Provider cannot be empty" msgstr "O provedor não pode ser vazio" -#: Auth/Rules/AbstractRule.php:77 +#: Auth/Rules/AbstractRule.php:78 msgid "" "Table alias is empty, please define a table alias, we could not extract a " "default table from the request" @@ -65,7 +65,7 @@ msgstr "A conta não pode ser validada" msgid "Invalid token and/or social account" msgstr "Token e/ou conta social inválido(s)" -#: Controller/SocialAccountsController.php:59;86 +#: Controller/SocialAccountsController.php:59;87 msgid "Social Account already active" msgstr "Conta social já ativa" @@ -73,19 +73,19 @@ msgstr "Conta social já ativa" msgid "Social Account could not be validated" msgstr "A conta social não pode ser validada" -#: Controller/SocialAccountsController.php:79 +#: Controller/SocialAccountsController.php:80 msgid "Email sent successfully" msgstr "Email enviado com sucesso" -#: Controller/SocialAccountsController.php:81 +#: Controller/SocialAccountsController.php:82 msgid "Email could not be sent" msgstr "O email não pode ser enviado" -#: Controller/SocialAccountsController.php:84 +#: Controller/SocialAccountsController.php:85 msgid "Invalid account" msgstr "Conta inválida" -#: Controller/SocialAccountsController.php:88 +#: Controller/SocialAccountsController.php:89 msgid "Email could not be resent" msgstr "O email não pode ser reenviado" @@ -95,20 +95,20 @@ msgstr "" "Salt da aplicação inválido, o salt da aplicação deve ser de pelo menos 256 " "bits (32 bytes)" -#: Controller/Component/UsersAuthComponent.php:157 +#: Controller/Component/UsersAuthComponent.php:178 msgid "You can't enable email validation workflow if use_email is false" msgstr "" "Você não pode habilitar o fluxo de validação por email se use_email for false" -#: Controller/Traits/LoginTrait.php:95 +#: Controller/Traits/LoginTrait.php:96 msgid "Issues trying to log in with your social account" msgstr "Problemas ao tentar autenticar a partir da sua conta social" -#: Controller/Traits/LoginTrait.php:100 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "Por favor indique seu email" -#: Controller/Traits/LoginTrait.php:106 +#: Controller/Traits/LoginTrait.php:108 msgid "" "Your user has not been validated yet. Please check your inbox for " "instructions" @@ -116,7 +116,7 @@ msgstr "" "Seu usuário ainda não foi validado. Por favor, verifique sua caixa de " "entrada para instruções" -#: Controller/Traits/LoginTrait.php:108 +#: Controller/Traits/LoginTrait.php:110 msgid "" "Your social account has not been validated yet. Please check your inbox for " "instructions" @@ -124,92 +124,96 @@ msgstr "" "Sua conta social ainda não foi validada. Por favor, verifique sua caixa de " "entrada para instruções" -#: Controller/Traits/LoginTrait.php:157 Controller/Traits/RegisterTrait.php:73 +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 msgid "Invalid reCaptcha" msgstr "ReCaptcha inválido" -#: Controller/Traits/LoginTrait.php:165 +#: Controller/Traits/LoginTrait.php:171 msgid "You are already logged in" msgstr "Você já está autenticado" -#: Controller/Traits/LoginTrait.php:209 +#: Controller/Traits/LoginTrait.php:217 msgid "Username or password is incorrect" msgstr "Nome de usuário e/ou senha incorreto(s)" -#: Controller/Traits/LoginTrait.php:230 +#: Controller/Traits/LoginTrait.php:238 msgid "You've successfully logged out" msgstr "Você desconectou-se com êxito" -#: Controller/Traits/PasswordManagementTrait.php:53;60;68 +#: Controller/Traits/PasswordManagementTrait.php:47;76 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "O usuário não foi encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 msgid "Password could not be changed" msgstr "A senha não pode ser alterada" -#: Controller/Traits/PasswordManagementTrait.php:57 +#: Controller/Traits/PasswordManagementTrait.php:68 msgid "Password has been changed successfully" msgstr "Senha alterada com êxito" -#: Controller/Traits/PasswordManagementTrait.php:64 -#: Controller/Traits/ProfileTrait.php:49 -msgid "User was not found" -msgstr "O usuário não foi encontrado" +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" -#: Controller/Traits/PasswordManagementTrait.php:66 -msgid "The current password does not match" -msgstr "A senha atual não corresponde" - -#: Controller/Traits/PasswordManagementTrait.php:108 +#: Controller/Traits/PasswordManagementTrait.php:120 msgid "Please check your email to continue with password reset process" msgstr "" "Por favor, verifique seu email para continuar o processo de redefinição de " "senha" -#: Controller/Traits/PasswordManagementTrait.php:111 Shell/UsersShell.php:266 +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 msgid "The password token could not be generated. Please try again" msgstr "O token de senha não pode ser gerado. Por favor, tente novamente" -#: Controller/Traits/PasswordManagementTrait.php:116 -#: Controller/Traits/UserValidationTrait.php:98 +#: Controller/Traits/PasswordManagementTrait.php:129 +#: Controller/Traits/UserValidationTrait.php:100 msgid "User {0} was not found" msgstr "O usuário {0} não foi encontrado" -#: Controller/Traits/PasswordManagementTrait.php:118 +#: Controller/Traits/PasswordManagementTrait.php:131 msgid "The user is not active" msgstr "O usuário não está ativo" -#: Controller/Traits/PasswordManagementTrait.php:120 -#: Controller/Traits/UserValidationTrait.php:94;102 +#: Controller/Traits/PasswordManagementTrait.php:133 +#: Controller/Traits/UserValidationTrait.php:95;104 msgid "Token could not be reset" msgstr "O token não pode ser redefinido" -#: Controller/Traits/ProfileTrait.php:52 +#: Controller/Traits/ProfileTrait.php:53 msgid "Not authorized, please login first" msgstr "Não autorizado, por favor, autentique-se primeiro" -#: Controller/Traits/RegisterTrait.php:79 +#: Controller/Traits/RegisterTrait.php:42 +msgid "You must log out to register a new user account" +msgstr "Você deve deslogar para registrar uma nova conta de usuário" + +#: Controller/Traits/RegisterTrait.php:88 msgid "The user could not be saved" msgstr "O usuário não pode ser salvo" -#: Controller/Traits/RegisterTrait.php:111 +#: Controller/Traits/RegisterTrait.php:122 msgid "You have registered successfully, please log in" msgstr "Você registrou-se com sucesso, por favor, autentique-se" -#: Controller/Traits/RegisterTrait.php:113 +#: Controller/Traits/RegisterTrait.php:124 msgid "Please validate your account before log in" msgstr "Por favor, valide sua conta antes de autenticar" -#: Controller/Traits/SimpleCrudTrait.php:76;105 +#: Controller/Traits/SimpleCrudTrait.php:76;106 msgid "The {0} has been saved" msgstr "O {0} foi salvo" -#: Controller/Traits/SimpleCrudTrait.php:79;108 +#: Controller/Traits/SimpleCrudTrait.php:80;110 msgid "The {0} could not be saved" msgstr "O {0} não pode ser salvo" -#: Controller/Traits/SimpleCrudTrait.php:128 +#: Controller/Traits/SimpleCrudTrait.php:130 msgid "The {0} has been deleted" msgstr "O {0} foi deletado" -#: Controller/Traits/SimpleCrudTrait.php:130 +#: Controller/Traits/SimpleCrudTrait.php:132 msgid "The {0} could not be deleted" msgstr "O {0} não pode ser deletado" @@ -233,27 +237,27 @@ msgstr "Usuário já ativo" msgid "Reset password token was validated successfully" msgstr "Token de redefinição de senha validado com êxito" -#: Controller/Traits/UserValidationTrait.php:57 +#: Controller/Traits/UserValidationTrait.php:58 msgid "Reset password token could not be validated" msgstr "O token de redefinição de senha não pode ser validado" -#: Controller/Traits/UserValidationTrait.php:61 +#: Controller/Traits/UserValidationTrait.php:62 msgid "Invalid validation type" msgstr "Tipo de validação inválido" -#: Controller/Traits/UserValidationTrait.php:64 +#: Controller/Traits/UserValidationTrait.php:65 msgid "Invalid token or user account already validated" msgstr "Token inválido ou conta já validada" -#: Controller/Traits/UserValidationTrait.php:66 +#: Controller/Traits/UserValidationTrait.php:67 msgid "Token already expired" msgstr "Token expirado" -#: Controller/Traits/UserValidationTrait.php:92 +#: Controller/Traits/UserValidationTrait.php:93 msgid "Token has been reset successfully. Please check your email." msgstr "O token foi redefinido com êxito. Por favor, verifique seu email." -#: Controller/Traits/UserValidationTrait.php:100 +#: Controller/Traits/UserValidationTrait.php:102 msgid "User {0} is already active" msgstr "O usuário {0} já está ativo" @@ -277,12 +281,12 @@ msgstr "A referência não pode ser nula" msgid "Token expiration cannot be empty" msgstr "A expiração do token não pode ser vazia" -#: Model/Behavior/PasswordBehavior.php:67;115 +#: Model/Behavior/PasswordBehavior.php:67;116 msgid "User not found" msgstr "Usuário não encontrado" #: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:110 +#: Model/Behavior/RegisterBehavior.php:111 msgid "User account already validated" msgstr "Conta de usuário já validada" @@ -290,23 +294,27 @@ msgstr "Conta de usuário já validada" msgid "User not active" msgstr "Usuário inativo" -#: Model/Behavior/PasswordBehavior.php:120 -msgid "The old password does not match" -msgstr "A senha antiga não confere" +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "A senha atual não corresponde" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "Você não pode usar a senha atual como nova senha" -#: Model/Behavior/RegisterBehavior.php:88 +#: Model/Behavior/RegisterBehavior.php:89 msgid "User not found for the given token and email." msgstr "Usuário não encontrado com a combinação de token e email" -#: Model/Behavior/RegisterBehavior.php:91 +#: Model/Behavior/RegisterBehavior.php:92 msgid "Token has already expired user with no token" msgstr "Token expirado, usuário sem token" -#: Model/Behavior/SocialAccountBehavior.php:101;128 +#: Model/Behavior/SocialAccountBehavior.php:102;129 msgid "Account already validated" msgstr "Conta já validada" -#: Model/Behavior/SocialAccountBehavior.php:104;131 +#: Model/Behavior/SocialAccountBehavior.php:105;132 msgid "Account not found for the given token and email." msgstr "Conta não encontrada com a combinação de token e email" @@ -314,23 +322,27 @@ msgstr "Conta não encontrada com a combinação de token e email" msgid "Unable to login user with reference {0}" msgstr "Incapaz de autenticar usuário com a referência {0}" -#: Model/Behavior/SocialBehavior.php:97 +#: Model/Behavior/SocialBehavior.php:98 msgid "Email not present" msgstr "Email ausente" -#: Model/Table/UsersTable.php:81 +#: Model/Table/UsersTable.php:82 msgid "Your password does not match your confirm password. Please try again" msgstr "" "Sua senha não corresponde com a confirmação. Por favor, tente novamente" -#: Model/Table/UsersTable.php:159 +#: Model/Table/UsersTable.php:175 msgid "Username already exists" msgstr "Nome de usuário em uso" -#: Model/Table/UsersTable.php:165 +#: Model/Table/UsersTable.php:181 msgid "Email already exists" msgstr "Email em uso" +#: Model/Table/UsersTable.php:214 +msgid "Missing 'username' in options data" +msgstr "'username' ausente nas opções" + #: Shell/UsersShell.php:54 msgid "Utilities for CakeDC Users Plugin" msgstr "Utilitários para CakeDC Users Plugin" @@ -371,83 +383,83 @@ msgstr "Redefinir a senha de todos usuários" msgid "Reset the password for an specific user" msgstr "Redefinir a senha de um usuário específico" -#: Shell/UsersShell.php:97 +#: Shell/UsersShell.php:98 msgid "User added:" msgstr "Usuário adicionado:" -#: Shell/UsersShell.php:98;126 +#: Shell/UsersShell.php:99;127 msgid "Id: {0}" msgstr "Id: {0}" -#: Shell/UsersShell.php:99;127 +#: Shell/UsersShell.php:100;128 msgid "Username: {0}" msgstr "Nome de usuário: {0}" -#: Shell/UsersShell.php:100;128 +#: Shell/UsersShell.php:101;129 msgid "Email: {0}" msgstr "Email: {0}" -#: Shell/UsersShell.php:101;129 +#: Shell/UsersShell.php:102;130 msgid "Password: {0}" msgstr "Senha: {0}" -#: Shell/UsersShell.php:125 +#: Shell/UsersShell.php:126 msgid "Superuser added:" msgstr "Superusuário adicionado:" -#: Shell/UsersShell.php:131 +#: Shell/UsersShell.php:132 msgid "Superuser could not be added:" msgstr "O superusuário não pode ser adicionado:" -#: Shell/UsersShell.php:134 +#: Shell/UsersShell.php:135 msgid "Field: {0} Error: {1}" msgstr "Campo: {0} Erro: {1}" -#: Shell/UsersShell.php:152;178 +#: Shell/UsersShell.php:153;179 msgid "Please enter a password." msgstr "Por favor, indique uma senha." -#: Shell/UsersShell.php:156 +#: Shell/UsersShell.php:157 msgid "Password changed for all users" msgstr "As senhas de todos usuários foram alteradas" -#: Shell/UsersShell.php:157;185 +#: Shell/UsersShell.php:158;186 msgid "New password: {0}" msgstr "Nova senha: {0}" -#: Shell/UsersShell.php:175;203;281;321 +#: Shell/UsersShell.php:176;204;282;324 msgid "Please enter a username." msgstr "Por favor, indique um nome de usuário." -#: Shell/UsersShell.php:184 +#: Shell/UsersShell.php:185 msgid "Password changed for user: {0}" msgstr "Senha alterada para usuário: {0}" -#: Shell/UsersShell.php:206 +#: Shell/UsersShell.php:207 msgid "Please enter a role." msgstr "Por favor, indique um papel." -#: Shell/UsersShell.php:212 +#: Shell/UsersShell.php:213 msgid "Role changed for user: {0}" msgstr "Papel alterado para usuário: {0}" -#: Shell/UsersShell.php:213 +#: Shell/UsersShell.php:214 msgid "New role: {0}" msgstr "Novo papel: {0}" -#: Shell/UsersShell.php:228 +#: Shell/UsersShell.php:229 msgid "User was activated: {0}" msgstr "Usuário ativado: {0}" -#: Shell/UsersShell.php:243 +#: Shell/UsersShell.php:244 msgid "User was de-activated: {0}" msgstr "Usuário desativado: {0}" -#: Shell/UsersShell.php:255 +#: Shell/UsersShell.php:256 msgid "Please enter a username or email." msgstr "Por favor, indique um nome de usuário ou senha." -#: Shell/UsersShell.php:263 +#: Shell/UsersShell.php:264 msgid "" "Please ask the user to check the email to continue with password reset " "process" @@ -455,15 +467,15 @@ msgstr "" "Por favor, peça ao usuário para verificar seu email para continuar o " "processo de redefinição de senha" -#: Shell/UsersShell.php:300 +#: Shell/UsersShell.php:302 msgid "The user was not found." msgstr "O usuário não foi encontrado." -#: Shell/UsersShell.php:329 +#: Shell/UsersShell.php:332 msgid "The user {0} was not deleted. Please try again" msgstr "O usuário {0} não foi deletado. Por favor, tente novamente" -#: Shell/UsersShell.php:331 +#: Shell/UsersShell.php:334 msgid "The user {0} was deleted successfully" msgstr "O usuário {0} foi deletado com êxito" @@ -483,11 +495,11 @@ msgstr "Redefina sua senha aqui" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 msgid "" -"If the link is not correctly displayed, please copy the following address in " +"If the link is not correcly displayed, please copy the following address in " "your web browser {0}" msgstr "" "Se o link não estiver sendo exibido corretamente, por favor, copie o " -"endereço a seguir no seu navegador {0}" +"seguinte endereço em seu navegador {0}" #: Template/Email/html/reset_password.ctp:30 #: Template/Email/html/social_account_validation.ctp:35 @@ -511,8 +523,8 @@ msgid "" "If the link is not correctly displayed, please copy the following address in " "your web browser {0}" msgstr "" -"Se o link não está exibido corretamente, por favor, copie o seguinte " -"endereço em seu navegador {0}" +"Se o link não estiver sendo exibido corretamente, por favor, copie o " +"seguinte endereço em seu navegador {0}" #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 @@ -527,18 +539,18 @@ msgstr "" "Por favor, copie o endereço a seguir em seu navegador para ativar sua " "autenticação social {0}" -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:13 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:13;77 +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 msgid "Actions" msgstr "Ações" -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:21 -#: Template/Users/view.ctp:17 +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 +#: Template/Users/view.ctp:19 msgid "List Users" msgstr "Listar usuários" -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:22 -#: Template/Users/view.ctp:19 +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:21 msgid "List Accounts" msgstr "Listar contas" @@ -546,8 +558,35 @@ msgstr "Listar contas" msgid "Add User" msgstr "Adicionar usuário" -#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:17 -#: Template/Users/edit.ctp:42 Template/Users/register.ctp:32 +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 +#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Nome de usuário" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "Email" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +msgid "First name" +msgstr "Nome" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Sobrenome" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Ativo" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 #: Template/Users/request_reset_password.ctp:8 #: Template/Users/resend_token_validation.ctp:20 #: Template/Users/social_email.ctp:19 @@ -562,25 +601,53 @@ msgstr "Por favor, indique a nova senha" msgid "Current password" msgstr "Senha atual" -#: Template/Users/edit.ctp:16 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:99 +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nova senha" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Confirmar senha" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:101 msgid "Delete" msgstr "Deletar" -#: Template/Users/edit.ctp:18 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:16;99 +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:18;101 msgid "Are you sure you want to delete # {0}?" msgstr "Tem certeza que deseja deletar # {0}?" -#: Template/Users/edit.ctp:28 Template/Users/view.ctp:15 +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 msgid "Edit User" msgstr "Editar usuário" +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token expira" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "Token da API" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Data de ativação" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Data TOS" + #: Template/Users/index.ctp:15 msgid "New {0}" msgstr "Novo {0}" -#: Template/Users/index.ctp:37 Template/Users/view.ctp:95 +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 msgid "View" msgstr "Visualizar" @@ -588,7 +655,7 @@ msgstr "Visualizar" msgid "Change password" msgstr "Mudar senha" -#: Template/Users/index.ctp:39 Template/Users/view.ctp:97 +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 msgid "Edit" msgstr "Editar" @@ -608,6 +675,14 @@ msgstr "Por favor, indique seu nome de usuário e senha" msgid "Remember me" msgstr "Lembrar" +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Registrar" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Resetar Senha" + #: Template/Users/login.ctp:48 msgid "Login" msgstr "Autenticar" @@ -620,23 +695,15 @@ msgstr "{0} {1}" msgid "Change Password" msgstr "Mudar senha" -#: Template/Users/profile.ctp:27 Template/Users/view.ctp:28;68 -msgid "Username" -msgstr "Nome de usuário" - -#: Template/Users/profile.ctp:29 Template/Users/view.ctp:30 -msgid "Email" -msgstr "Email" - #: Template/Users/profile.ctp:34 msgid "Social Accounts" msgstr "Contas sociais" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:70 +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 msgid "Avatar" msgstr "Avatar" -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:67 +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 msgid "Provider" msgstr "Provedor" @@ -648,7 +715,11 @@ msgstr "Link" msgid "Link to {0}" msgstr "Link para {0}" -#: Template/Users/register.ctp:25 +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Senha" + +#: Template/Users/register.ctp:28 msgid "Accept TOS conditions?" msgstr "Concordar com TOS?" @@ -664,74 +735,70 @@ msgstr "Reenviar email de validação" msgid "Email or username" msgstr "Email ou nome de usuário" -#: Template/Users/view.ctp:16 +#: Template/Users/view.ctp:18 msgid "Delete User" msgstr "Deletar usuário" -#: Template/Users/view.ctp:18 +#: Template/Users/view.ctp:20 msgid "New User" msgstr "Novo usuário" -#: Template/Users/view.ctp:26;65 +#: Template/Users/view.ctp:28;67 msgid "Id" msgstr "Id" -#: Template/Users/view.ctp:32 +#: Template/Users/view.ctp:34 msgid "First Name" msgstr "Nome" -#: Template/Users/view.ctp:34 +#: Template/Users/view.ctp:36 msgid "Last Name" msgstr "Sobrenome" -#: Template/Users/view.ctp:36;71 -msgid "Token" -msgstr "Token" - -#: Template/Users/view.ctp:38 +#: Template/Users/view.ctp:40 msgid "Api Token" msgstr "Api Token" -#: Template/Users/view.ctp:42;73 -msgid "Active" -msgstr "Ativo" - -#: Template/Users/view.ctp:46;72 +#: Template/Users/view.ctp:48;74 msgid "Token Expires" msgstr "Expiração do token" -#: Template/Users/view.ctp:48 +#: Template/Users/view.ctp:50 msgid "Activation Date" msgstr "Data de ativação" -#: Template/Users/view.ctp:50 +#: Template/Users/view.ctp:52 msgid "Tos Date" msgstr "Data TOS" -#: Template/Users/view.ctp:52;75 +#: Template/Users/view.ctp:54;77 msgid "Created" msgstr "Criado" -#: Template/Users/view.ctp:54;76 +#: Template/Users/view.ctp:56;78 msgid "Modified" msgstr "Modificado" -#: Template/Users/view.ctp:61 +#: Template/Users/view.ctp:63 msgid "Related Accounts" msgstr "Contas relacionadas" -#: Template/Users/view.ctp:66 +#: Template/Users/view.ctp:68 msgid "User Id" msgstr "Id de usuário" -#: Template/Users/view.ctp:69 +#: Template/Users/view.ctp:71 msgid "Reference" msgstr "Referência" -#: Template/Users/view.ctp:74 +#: Template/Users/view.ctp:76 msgid "Data" msgstr "Dados" +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Logar com" + #: View/Helper/UserHelper.php:49 msgid "fa fa-{0}" msgstr "fa-fa-{0}" @@ -740,19 +807,26 @@ msgstr "fa-fa-{0}" msgid "btn btn-social btn-{0} " msgstr "btn btn-social btn-{0}" -#: View/Helper/UserHelper.php:90 +#: View/Helper/UserHelper.php:91 msgid "Logout" msgstr "Desconectar" -#: View/Helper/UserHelper.php:139 +#: View/Helper/UserHelper.php:108 msgid "Welcome, {0}" msgstr "Bem-vindo(a), {0}" -#: View/Helper/UserHelper.php:161 +#: View/Helper/UserHelper.php:131 msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" msgstr "" "O reCaptcha não está configurado! Por favor, configure Users.reCaptcha.key" +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Este campo é obrigatório" + +#~ msgid "The old password does not match" +#~ msgstr "A senha antiga não confere" + #~ msgid "SocialAccount already active" #~ msgstr "Conta social já ativa" From 81c42b0f700a821638a9e4d3f6b5c76c6143b532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Tue, 28 Feb 2017 22:20:47 +0100 Subject: [PATCH 0579/1476] Fixed phpcs issues --- src/Shell/UsersShell.php | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 49238ab5e..2c5ef1895 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -78,11 +78,7 @@ public function getOptionParser() */ public function addUser() { - $this->_createUser([ - 'role' => 'user' - ], - false - ); + $this->_createUser(['role' => 'user']); } /** @@ -93,12 +89,10 @@ public function addUser() public function addSuperuser() { $this->_createUser([ - 'username' => 'superadmin', - 'role' => 'superuser', - 'is_superuser' => true - ], - true - ); + 'username' => 'superadmin', + 'role' => 'superuser', + 'is_superuser' => true + ]); } /** @@ -255,24 +249,23 @@ protected function _changeUserActive($active) /** * Create a new user or superuser * - * @param bool $is_superuser is superuser value * @param array $template template with deafault user values * @return void */ - public function _createUser($template) + protected function _createUser($template) { if (!empty($this->params['username'])) { $username = $this->params['username']; } else { - $username = !empty($template['username']) ? + $username = !empty($template['username']) ? $template['username'] : $this->_generateRandomUsername(); } $password = (empty($this->params['password']) ? $this->_generateRandomPassword() : $this->params['password']); - $email = (empty($this->params['email']) ? + $email = (empty($this->params['email']) ? $username . '@example.com' : $this->params['email']); - $role = (empty($this->params['role']) ? + $role = (empty($this->params['role']) ? $template['role'] : $this->params['role']); $user = [ From 8410c80e652d906d91ba3fdd24622d4c2e06c235 Mon Sep 17 00:00:00 2001 From: Livio Ribeiro Date: Tue, 28 Feb 2017 23:39:20 -0300 Subject: [PATCH 0580/1476] Fix social login button icon --- src/Locale/pt_BR/Users.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Locale/pt_BR/Users.po b/src/Locale/pt_BR/Users.po index 591c020cf..db8f2bbe5 100644 --- a/src/Locale/pt_BR/Users.po +++ b/src/Locale/pt_BR/Users.po @@ -801,7 +801,7 @@ msgstr "Logar com" #: View/Helper/UserHelper.php:49 msgid "fa fa-{0}" -msgstr "fa-fa-{0}" +msgstr "fa fa-{0}" #: View/Helper/UserHelper.php:52 msgid "btn btn-social btn-{0} " From c03980be5247f04870d88f99670cdb32d99b2f89 Mon Sep 17 00:00:00 2001 From: Livio Ribeiro Date: Wed, 1 Mar 2017 09:52:00 -0300 Subject: [PATCH 0581/1476] Fix social login button icon (compile User.po) --- src/Locale/pt_BR/Users.mo | Bin 15158 -> 15158 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Locale/pt_BR/Users.mo b/src/Locale/pt_BR/Users.mo index 35582e87e17ad794b8d28f06efd5bba48694ea0c..787c09266da5993ebcf6db06844c54eae8f144fe 100644 GIT binary patch delta 29 lcmdm1wykW#PGv4*T?0b}14}DY!_9}4*NZVKOfI%M3;?3d3R?gG delta 29 lcmdm1wykW#PGv45T_ZCELvt$=)6IvK*NZXgPA;}O3;?5!3UB}b From 1b1cf787714a3290e814d198e0e6fc83582ee1b8 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 3 Mar 2017 11:04:03 -0500 Subject: [PATCH 0582/1476] Add active finder to SocialAccountsTable --- src/Model/Table/SocialAccountsTable.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 0ebd54235..79bc59b4f 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -116,4 +116,17 @@ public function buildRules(RulesChecker $rules) return $rules; } + + /** + * Finder for active social accounts + * + * @param Query $query + * @return \Cake\ORM\Query + */ + public function findActive(Query $query) + { + return $query->where([ + $this->aliasField('active') => true + ]); + } } From fa94f9d0c6d383609f0dd1bd71347067c957cff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 3 Mar 2017 16:56:40 +0000 Subject: [PATCH 0583/1476] fix cs --- src/Model/Table/SocialAccountsTable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 79bc59b4f..b7d135416 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -116,11 +116,11 @@ public function buildRules(RulesChecker $rules) return $rules; } - + /** * Finder for active social accounts * - * @param Query $query + * @param Query $query query * @return \Cake\ORM\Query */ public function findActive(Query $query) From 35a855c37b27a7f37eaf2e33820ab728315fd1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 3 Mar 2017 17:00:11 +0000 Subject: [PATCH 0584/1476] fix cs --- src/Controller/Component/RememberMeComponent.php | 1 - tests/TestCase/Auth/ApiKeyAuthenticateTest.php | 1 - tests/TestCase/Auth/RememberMeAuthenticateTest.php | 1 - tests/TestCase/Auth/SimpleRbacAuthorizeTest.php | 1 - tests/TestCase/Auth/SocialAuthenticateTest.php | 1 - tests/TestCase/Controller/Traits/LoginTraitTest.php | 1 - tests/TestCase/Mailer/UsersMailerTest.php | 2 -- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 1 - tests/TestCase/Model/Behavior/SocialBehaviorTest.php | 1 - tests/TestCase/Shell/UsersShellTest.php | 1 - tests/bootstrap.php | 1 - 11 files changed, 12 deletions(-) diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 33a085548..f186cb189 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -40,7 +40,6 @@ class RememberMeComponent extends Component */ protected $_cookieName = null; - /** * Initialize config data and properties. * diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php index e3ab0ec59..38de9b23f 100644 --- a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -131,7 +131,6 @@ public function testAuthenticateRequireSSLNoKey() $this->assertFalse($this->apiKey->authenticate($request, new Response())); } - /** * test * diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php index 4a5eb09b7..a23b1f95f 100644 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -115,7 +115,6 @@ public function testAuthenticateBadUser() $this->assertFalse($result); } - /** * test * diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index 0d4eb865b..d2cdf1167 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -53,7 +53,6 @@ class SimpleRbacAuthorizeTest extends TestCase ], ]; - /** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index 392bdcb40..9a43e882c 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -123,7 +123,6 @@ public function testGetUserAuth($rawData, $mapper) ->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']); diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 254d50f87..f1fbc17a4 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -363,7 +363,6 @@ public function testFailedSocialUserAccountNotActive() $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } - /** * test * diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 1aae78b62..9b1e18606 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -154,7 +154,6 @@ public function testSocialAccountValidation() ->with('first1, Your social account validation link') ->will($this->returnValue($this->Email)); - $this->Email->expects($this->once()) ->method('viewVars') ->with(['user' => $social->user, 'socialAccount' => $social]) @@ -197,7 +196,6 @@ public function testResetPassword() ->with('myTemplate') ->will($this->returnValue($this->Email)); - $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user, 'myTemplate']); } diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index df14e10ce..d8c8ebd9d 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -62,7 +62,6 @@ public function tearDown() parent::tearDown(); } - /** * Test resetToken * diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php index 33f700836..b972c2093 100644 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -295,7 +295,6 @@ public function testSocialLoginNoEmail($data, $options) $this->Behavior->socialLogin($data, $options); } - /** * Provider for socialLogin with facebook and not existing user * diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index a6a7fde92..1159fe3aa 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -252,7 +252,6 @@ public function testAddSuperuserWithNoParams() $this->Shell->runCommand(['addSuperuser']); } - /** * Reset all passwords * diff --git a/tests/bootstrap.php b/tests/bootstrap.php index efa649358..4ec62c563 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -91,7 +91,6 @@ 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 a2feed6d1882922e1b4c4b0c63656731514a6a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 6 Mar 2017 14:22:11 +0000 Subject: [PATCH 0585/1476] add restrictive Auth->allow() configuration --- config/users.php | 2 + .../Component/UsersAuthComponent.php | 38 ++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/config/users.php b/config/users.php index 486309570..b5e95a17f 100644 --- a/config/users.php +++ b/config/users.php @@ -16,6 +16,8 @@ 'Users' => [ //Table used to manage users 'table' => 'CakeDC/Users.Users', + //Controller used to manage users + 'controller' => 'CakeDC/Users.Users', //configure Auth component 'auth' => true, //Password Hasher diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 0eb75546f..7d55173c7 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -114,20 +114,30 @@ protected function _initAuth() $this->_registry->getController()->loadComponent('Auth', Configure::read('Auth')); } - $this->_registry->getController()->Auth->allow([ - 'register', - 'validateEmail', - 'resendTokenValidation', - 'login', - 'twitterLogin', - 'socialEmail', - 'resetPassword', - 'requestResetPassword', - 'changePassword', - 'endpoint', - 'authenticated', - 'verify' - ]); + list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); + if ($this->request->param('plugin') === $plugin && + $this->request->param('controller') === $controller + ) { + $this->_registry->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', + ]); + } } /** From 561fec1a47db8f73f1225e75dd0b6ddf42a2f509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 6 Mar 2017 14:45:46 +0000 Subject: [PATCH 0586/1476] refs #core34 minor message change --- src/Auth/Exception/MissingEventListenerException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth/Exception/MissingEventListenerException.php b/src/Auth/Exception/MissingEventListenerException.php index 8aec17f8f..1c1d08388 100644 --- a/src/Auth/Exception/MissingEventListenerException.php +++ b/src/Auth/Exception/MissingEventListenerException.php @@ -5,5 +5,5 @@ class MissingEventListenerException extends Exception { - protected $_messageTemplate = 'Missing listener to the `%s` event.'; + protected $_messageTemplate = 'Missing listener to the (%s) event.'; } From e6b35dcab3c4928a41849c3439e936dd7521cda0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 6 Mar 2017 14:46:01 +0000 Subject: [PATCH 0587/1476] refs #core34 fix deprecations --- src/Auth/ApiKeyAuthenticate.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 68ed80fbf..25555fd25 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -13,8 +13,8 @@ use Cake\Auth\BaseAuthenticate; use Cake\Core\Configure; +use Cake\Http\ServerRequest; use Cake\Network\Exception\ForbiddenException; -use Cake\Network\Request; use Cake\Network\Response; use \OutOfBoundsException; @@ -48,11 +48,11 @@ class ApiKeyAuthenticate extends BaseAuthenticate * Authenticate callback * Reads the API Key based on configuration and login the user * - * @param Request $request Cake request object. - * @param Response $response Cake response object. + * @param ServerRequest $request request object. + * @param Response $response response object. * @return mixed */ - public function authenticate(Request $request, Response $response) + public function authenticate(ServerRequest $request, Response $response) { return $this->getUser($request); } @@ -70,9 +70,9 @@ public function authenticate(Request $request, Response $response) * @param Request $request Cake request object. * @return mixed */ - public function getUser(Request $request) + public function getUser(ServerRequest $request) { - $type = $this->config('type'); + $type = $this->getConfig('type'); if (!in_array($type, $this->types)) { throw new OutOfBoundsException(__d('CakeDC/Users', 'Type {0} is not valid', $type)); } @@ -109,7 +109,7 @@ public function getUser(Request $request) * @param Request $request request * @return string api key */ - public function querystring(Request $request) + public function querystring(ServerRequest $request) { $name = $this->config('name'); @@ -122,7 +122,7 @@ public function querystring(Request $request) * @param Request $request request * @return string api key */ - public function header(Request $request) + public function header(ServerRequest $request) { $name = $this->config('name'); From c1c07fb4b899ce7d1b53ce00ee5548143a96bcf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 6 Mar 2017 14:46:17 +0000 Subject: [PATCH 0588/1476] refs #core34 update composer versions --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e74604e02..d6059f4a6 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": ">=3.2.9 <3.4.0" + "cakephp/cakephp": "~3.4.0" }, "require-dev": { "phpunit/phpunit": "^5.0", From 640a4366d0e454e9fcbcdb40aef00016de4053b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 6 Mar 2017 15:40:00 +0000 Subject: [PATCH 0589/1476] refs #core34 fix deprecations --- src/Auth/ApiKeyAuthenticate.php | 27 ++++----- src/Auth/RememberMeAuthenticate.php | 13 +++-- src/Auth/Rules/AbstractRule.php | 26 ++++----- src/Auth/Rules/Owner.php | 36 ++++++++---- src/Auth/Rules/Rule.php | 6 +- src/Auth/SimpleRbacAuthorize.php | 36 ++++++------ src/Auth/SocialAuthenticate.php | 58 +++++++++---------- src/Auth/SuperuserAuthorize.php | 8 +-- .../Component/UsersAuthComponent.php | 2 +- 9 files changed, 114 insertions(+), 98 deletions(-) diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 25555fd25..b0591277c 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -48,7 +48,7 @@ class ApiKeyAuthenticate extends BaseAuthenticate * Authenticate callback * Reads the API Key based on configuration and login the user * - * @param ServerRequest $request request object. + * @param \Cake\Http\ServerRequest $request request object. * @param Response $response response object. * @return mixed */ @@ -67,7 +67,7 @@ public function authenticate(ServerRequest $request, Response $response) * $this->Auth->config('checkAuthIn', 'Controller.initialize'); * $this->Auth->config('loginAction', false); * - * @param Request $request Cake request object. + * @param \Cake\Http\ServerRequest $request Cake request object. * @return mixed */ public function getUser(ServerRequest $request) @@ -86,13 +86,15 @@ public function getUser(ServerRequest $request) return false; } - if ($this->config('require_ssl') && !$request->is('ssl')) { + if ($this->getConfig('require_ssl') && !$request->is('ssl')) { throw new ForbiddenException(__d('CakeDC/Users', 'SSL is required for ApiKey Authentication', $type)); } - $this->_config['fields']['username'] = $this->config('field'); - $this->_config['userModel'] = $this->config('table') ?: Configure::read('Users.table'); - $this->_config['finder'] = $this->config('finder') ?: Configure::read('Auth.authenticate.all.finder') ?: 'all'; + $this->_config['fields']['username'] = $this->getConfig('field'); + $this->_config['userModel'] = $this->getConfig('table') ?: Configure::read('Users.table'); + $this->_config['finder'] = $this->getConfig('finder') ?: + Configure::read('Auth.authenticate.all.finder') ?: + 'all'; $result = $this->_query($apiKey)->first(); if (empty($result)) { @@ -100,32 +102,31 @@ public function getUser(ServerRequest $request) } return $result->toArray(); - //idea: add array with checks to be passed to $request->is(...) } /** * Get the api key from the querystring * - * @param Request $request request + * @param \Cake\Http\ServerRequest $request request * @return string api key */ public function querystring(ServerRequest $request) { - $name = $this->config('name'); + $name = $this->getConfig('name'); - return $request->query($name); + return $request->getQuery($name); } /** * Get the api key from the header * - * @param Request $request request + * @param \Cake\Http\ServerRequest $request request * @return string api key */ public function header(ServerRequest $request) { - $name = $this->config('name'); + $name = $this->getConfig('name'); - return $request->header($name); + return $request->getHeader($name); } } diff --git a/src/Auth/RememberMeAuthenticate.php b/src/Auth/RememberMeAuthenticate.php index c83bfc220..c7faa899d 100644 --- a/src/Auth/RememberMeAuthenticate.php +++ b/src/Auth/RememberMeAuthenticate.php @@ -13,7 +13,7 @@ use Cake\Auth\BaseAuthenticate; use Cake\Core\Configure; -use Cake\Network\Request; +use Cake\Http\ServerRequest; use Cake\Network\Response; /** @@ -26,22 +26,23 @@ class RememberMeAuthenticate extends BaseAuthenticate * Authenticate callback * Reads the stored cookie and auto login the user * - * @param Request $request Cake request object. + * @param \Cake\Http\ServerRequest $request Cake request object. * @param Response $response Cake response object. * @return mixed */ - public function authenticate(Request $request, Response $response) + public function authenticate(ServerRequest $request, Response $response) { $cookieName = Configure::read('Users.RememberMe.Cookie.name'); - $cookie = $this->_registry->Cookie->read($cookieName); + $cookie = $this->_registry->getController()->Cookie->read($cookieName); if (empty($cookie)) { return false; } - $this->config('fields.username', 'id'); + $this->setConfig('fields.username', 'id'); $user = $this->_findUser($cookie['id']); if ($user && !empty($cookie['user_agent']) && - $request->header('User-Agent') === $cookie['user_agent']) { + $request->getHeader('User-Agent') === $cookie['user_agent'] + ) { return $user; } diff --git a/src/Auth/Rules/AbstractRule.php b/src/Auth/Rules/AbstractRule.php index 0517e3d71..d0b25cc02 100644 --- a/src/Auth/Rules/AbstractRule.php +++ b/src/Auth/Rules/AbstractRule.php @@ -12,11 +12,10 @@ use Cake\Core\InstanceConfigTrait; use Cake\Datasource\ModelAwareTrait; -use Cake\Network\Request; +use Cake\Http\ServerRequest; use Cake\ORM\Locator\LocatorAwareTrait; use Cake\ORM\Table; use Cake\ORM\TableRegistry; -use Cake\Utility\Hash; use OutOfBoundsException; /** @@ -40,18 +39,18 @@ abstract class AbstractRule implements Rule */ public function __construct($config = []) { - $this->config($config); + $this->setConfig($config); } /** * Get a table from the alias, table object or inspecting the request for a default table * - * @param Request $request request + * @param \Cake\Http\ServerRequest $request request * @param mixed $table table * @return \Cake\ORM\Table * @throws \OutOfBoundsException if table alias is empty */ - protected function _getTable(Request $request, $table = null) + protected function _getTable(ServerRequest $request, $table = null) { if (empty($table)) { return $this->_getTableFromRequest($request); @@ -66,19 +65,20 @@ protected function _getTable(Request $request, $table = null) /** * Inspect the request and try to retrieve a table based on the current controller * - * @param Request $request request - * @return Table + * @param \Cake\Http\ServerRequest $request request + * @return \Cake\Datasource\RepositoryInterface * @throws \OutOfBoundsException if table alias can't be extracted from request */ - protected function _getTableFromRequest(Request $request) + protected function _getTableFromRequest(ServerRequest $request) { - $plugin = Hash::get($request->params, 'plugin'); - $controller = Hash::get($request->params, 'controller'); + $plugin = $request->getParam('plugin'); + $controller = $request->getParams('controller'); $modelClass = ($plugin ? $plugin . '.' : '') . $controller; $this->modelFactory('Table', [$this->tableLocator(), 'get']); if (empty($modelClass)) { - throw new OutOfBoundsException(__d('CakeDC/Users', 'Table alias is empty, please define a table alias, we could not extract a default table from the request')); + $msg = __d('CakeDC/Users', 'Missing Table alias, we could not extract a default table from the request'); + throw new OutOfBoundsException($msg); } return $this->loadModel($modelClass); @@ -89,9 +89,9 @@ protected function _getTableFromRequest(Request $request) * * @param array $user Auth array with the logged in data * @param string $role role of the user - * @param Request $request current request, used to get a default table if not provided + * @param \Cake\Http\ServerRequest $request current request, used to get a default table if not provided * @return bool * @throws \OutOfBoundsException if table is not found or it doesn't have the expected fields */ - abstract public function allowed(array $user, $role, Request $request); + abstract public function allowed(array $user, $role, ServerRequest $request); } diff --git a/src/Auth/Rules/Owner.php b/src/Auth/Rules/Owner.php index c5373f001..5c72ce935 100644 --- a/src/Auth/Rules/Owner.php +++ b/src/Auth/Rules/Owner.php @@ -11,7 +11,7 @@ namespace CakeDC\Users\Auth\Rules; use Cake\Core\Exception\Exception; -use Cake\Network\Request; +use Cake\Http\ServerRequest; use Cake\Utility\Hash; use OutOfBoundsException; @@ -55,28 +55,42 @@ class Owner extends AbstractRule /** * {@inheritdoc} */ - public function allowed(array $user, $role, Request $request) + public function allowed(array $user, $role, ServerRequest $request) { - $table = $this->_getTable($request, $this->config('table')); + $table = $this->_getTable($request, $this->getConfig('table')); //retrieve table id from request - $id = Hash::get($request->{$this->config('tableKeyType')}, $this->config('tableIdParamsKey')); + $id = Hash::get($request->{$this->getConfig('tableKeyType')}, $this->getConfig('tableIdParamsKey')); $userId = Hash::get($user, 'id'); try { - if (!$table->hasField($this->config('ownerForeignKey'))) { - throw new OutOfBoundsException(__d('CakeDC/Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); + if (!$table->hasField($this->getConfig('ownerForeignKey'))) { + $msg = __d( + 'CakeDC/Users', + 'Missing column {0} in table {1} while checking ownership permissions for user {2}', + $this->getConfig('ownerForeignKey'), + $table->getAlias(), + $userId + ); + throw new OutOfBoundsException($msg); } } catch (Exception $ex) { - throw new OutOfBoundsException(__d('CakeDC/Users', 'Missing column {0} in table {1} while checking ownership permissions for user {2}', $this->config('ownerForeignKey'), $table->alias(), $userId)); + $msg = __d( + 'CakeDC/Users', + 'Missing column {0} in table {1} while checking ownership permissions for user {2}', + $this->getConfig('ownerForeignKey'), + $table->getAlias(), + $userId + ); + throw new OutOfBoundsException($msg); } - $idColumn = $this->config('id'); + $idColumn = $this->getConfig('id'); if (empty($idColumn)) { - $idColumn = $table->primaryKey(); + $idColumn = $table->getPrimaryKey(); } $conditions = array_merge([ $idColumn => $id, - $this->config('ownerForeignKey') => $userId - ], $this->config('conditions')); + $this->getConfig('ownerForeignKey') => $userId + ], $this->getConfig('conditions')); return $table->exists($conditions); } diff --git a/src/Auth/Rules/Rule.php b/src/Auth/Rules/Rule.php index 9acd999d3..517630abe 100644 --- a/src/Auth/Rules/Rule.php +++ b/src/Auth/Rules/Rule.php @@ -10,7 +10,7 @@ */ namespace CakeDC\Users\Auth\Rules; -use Cake\Network\Request; +use Cake\Http\ServerRequest; interface Rule { @@ -19,8 +19,8 @@ interface Rule * * @param array $user Auth array with the logged in data * @param string $role role of the user - * @param Request $request current request, used to get a default table if not provided + * @param \Cake\Http\ServerRequest $request current request, used to get a default table if not provided * @return bool */ - public function allowed(array $user, $role, Request $request); + public function allowed(array $user, $role, ServerRequest $request); } diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 120bdeaa7..1317ddbfa 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -17,7 +17,7 @@ use Cake\Core\Configure; use Cake\Core\Exception\Exception; use Cake\Log\LogTrait; -use Cake\Network\Request; +use Cake\Http\ServerRequest; use Cake\Utility\Hash; use Cake\Utility\Inflector; use Psr\Log\LogLevel; @@ -118,10 +118,10 @@ class SimpleRbacAuthorize extends BaseAuthorize public function __construct(ComponentRegistry $registry, array $config = []) { parent::__construct($registry, $config); - $autoload = $this->config('autoload_config'); + $autoload = $this->getConfig('autoload_config'); if ($autoload) { $loadedPermissions = $this->_loadPermissions($autoload); - $this->config('permissions', $loadedPermissions); + $this->setConfig('permissions', $loadedPermissions); } } @@ -155,13 +155,13 @@ protected function _loadPermissions($key) * Set a default role if no role is provided * * @param array $user user data - * @param Request $request request + * @param \Cake\Http\ServerRequest $request request * @return bool */ - public function authorize($user, Request $request) + public function authorize($user, ServerRequest $request) { - $roleField = $this->config('role_field'); - $role = $this->config('default_role'); + $roleField = $this->getConfig('role_field'); + $role = $this->getConfig('default_role'); if (Hash::check($user, $roleField)) { $role = Hash::get($user, $roleField); } @@ -177,12 +177,12 @@ public function authorize($user, Request $request) * * @param array $user current user array * @param string $role effective role for the current user - * @param Request $request request + * @param \Cake\Http\ServerRequest $request request * @return bool true if there is a match in permissions */ - protected function _checkPermissions(array $user, $role, Request $request) + protected function _checkPermissions(array $user, $role, ServerRequest $request) { - $permissions = $this->config('permissions'); + $permissions = $this->getConfig('permissions'); foreach ($permissions as $permission) { $allowed = $this->_matchPermission($permission, $user, $role, $request); if ($allowed !== null) { @@ -199,11 +199,11 @@ protected function _checkPermissions(array $user, $role, Request $request) * @param array $permission The permission configuration * @param array $user Current user data * @param string $role Effective user's role - * @param \Cake\Network\Request $request Current request + * @param \Cake\Http\ServerRequest $request Current request * * @return null|bool Null if permission is discarded, boolean if a final result is produced */ - protected function _matchPermission(array $permission, array $user, $role, Request $request) + protected function _matchPermission(array $permission, array $user, $role, ServerRequest $request) { $issetController = isset($permission['controller']) || isset($permission['*controller']); $issetAction = isset($permission['action']) || isset($permission['*action']); @@ -229,11 +229,11 @@ protected function _matchPermission(array $permission, array $user, $role, Reque $permission += ['allowed' => true]; $userArr = ['user' => $user]; $reserved = [ - 'prefix' => Hash::get($request->params, 'prefix'), - 'plugin' => $request->plugin, - 'extension' => Hash::get($request->params, '_ext'), - 'controller' => $request->controller, - 'action' => $request->action, + 'prefix' => $request->getParams('prefix'), + 'plugin' => $request->getParam('plugin'), + 'extension' => $request->getParam('_ext'), + 'controller' => $request->getParam('controller'), + 'action' => $request->getParam('action'), 'role' => $role ]; @@ -301,7 +301,7 @@ protected function _matchOrAsterisk($possibleValues, $value, $allowEmpty = false } /** - * Checks if $heystack begins with $needle + * Checks if $haystack begins with $needle * * @see http://stackoverflow.com/a/7168986/2588539 * diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 90bdffaf9..fe9f7abf8 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -28,7 +28,7 @@ use Cake\Event\EventDispatcherTrait; use Cake\Event\EventManager; use Cake\Log\LogTrait; -use Cake\Network\Request; +use Cake\Http\ServerRequest; use Cake\Network\Response; use Cake\ORM\TableRegistry; use Cake\Utility\Hash; @@ -134,8 +134,8 @@ protected function _normalizeConfig(&$config, $alias, $parent) * @param mixed $value Value. * @param string $key Key. * @return void - * @throws CakeDC\Users\Auth\Exception\InvalidProviderException - * @throws CakeDC\Users\Auth\Exception\InvalidSettingsException + * @throws \CakeDC\Users\Auth\Exception\InvalidProviderException + * @throws \CakeDC\Users\Auth\Exception\InvalidSettingsException */ protected function _validateConfig(&$value, $key) { @@ -159,12 +159,12 @@ protected function _getController() /** * Get a user based on information in the request. * - * @param \Cake\Network\Request $request Request object. + * @param \Cake\Http\ServerRequest $request Request object. * @param \Cake\Network\Response $response Response object. * @return bool * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. */ - public function authenticate(Request $request, Response $response) + public function authenticate(ServerRequest $request, Response $response) { return $this->getUser($request); } @@ -173,17 +173,17 @@ public function authenticate(Request $request, Response $response) * Authenticates with OAuth2 provider by getting an access token and * retrieving the authorized user's profile data. * - * @param \Cake\Network\Request $request Request object. + * @param \Cake\Http\ServerRequest $request Request object. * @return array|bool */ - protected function _authenticate(Request $request) + protected function _authenticate(ServerRequest $request) { if (!$this->_validate($request)) { return false; } $provider = $this->provider($request); - $code = $request->query('code'); + $code = $request->getQuery('code'); try { $token = $provider->getAccessToken('authorization_code', compact('code')); @@ -204,20 +204,20 @@ protected function _authenticate(Request $request) /** * Validates OAuth2 request. * - * @param \Cake\Network\Request $request Request object. + * @param \Cake\Http\ServerRequest $request Request object. * @return bool */ - protected function _validate(Request $request) + protected function _validate(ServerRequest $request) { - if (!array_key_exists('code', $request->query) || !$this->provider($request)) { + if (!array_key_exists('code', $request->getQueryParams()) || !$this->provider($request)) { return false; } $session = $request->session(); $sessionKey = 'oauth2state'; - $state = $request->query('state'); + $state = $request->getQuery('state'); - if ($this->config('options.state') && + if ($this->getConfig('options.state') && (!$state || $state !== $session->read($sessionKey))) { $session->delete($sessionKey); @@ -235,7 +235,7 @@ protected function _validate(Request $request) */ protected function _map($data) { - if (!$map = $this->config('mapFields')) { + if (!$map = $this->getConfig('mapFields')) { return $data; } @@ -252,22 +252,22 @@ protected function _map($data) * requested provider's authorization URL to let the user grant access to the * application. * - * @param \Cake\Network\Request $request Request object. + * @param \Cake\Http\ServerRequest $request Request object. * @param \Cake\Network\Response $response Response object. * @return \Cake\Network\Response|null */ - public function unauthenticated(Request $request, Response $response) + public function unauthenticated(ServerRequest $request, Response $response) { $provider = $this->provider($request); if (empty($provider) || !empty($request->query['code'])) { return null; } - if ($this->config('options.state')) { + if ($this->getConfig('options.state')) { $request->session()->write('oauth2state', $provider->getState()); } - $response->location($provider->getAuthorizationUrl()); + $response = $response->withLocation($provider->getAuthorizationUrl()); return $response; } @@ -275,12 +275,12 @@ public function unauthenticated(Request $request, Response $response) /** * Returns the `$request`-ed provider. * - * @param \Cake\Network\Request $request Current HTTP request. + * @param \Cake\Http\ServerRequest $request Current HTTP request. * @return \League\Oauth2\Client\Provider\GenericProvider|false */ - public function provider(Request $request) + public function provider(ServerRequest $request) { - if (!$alias = $request->param('provider')) { + if (!$alias = $request->getParam('provider')) { return false; } @@ -299,11 +299,11 @@ public function provider(Request $request) */ protected function _getProvider($alias) { - if (!$config = $this->config('providers.' . $alias)) { + if (!$config = $this->getConfig('providers.' . $alias)) { return false; } - $this->config($config); + $this->getConfig($config); if (is_object($config) && $config instanceof AbstractProvider) { return $config; @@ -360,14 +360,14 @@ protected function _touch(array $data) /** * Get a user based on information in the request. * - * @param \Cake\Network\Request $request Request object. + * @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(Request $request) + public function getUser(ServerRequest $request) { $data = $request->session()->read(Configure::read('Users.Key.Session.social')); - $requestDataEmail = $request->data('email'); + $requestDataEmail = $request->getData('email'); if (!empty($data) && empty($data['uid']) && (!empty($data['email']) || !empty($requestDataEmail))) { if (!empty($requestDataEmail)) { $data['email'] = $requestDataEmail; @@ -394,7 +394,7 @@ public function getUser(Request $request) } } - if (!$user || !$this->config('userModel')) { + if (!$user || !$this->getConfig('userModel')) { return false; } @@ -412,7 +412,7 @@ public function getUser(Request $request) /** * Get the provider name based on the request or on the provider set. * - * @param \Cake\Network\Request $request Request object. + * @param \Cake\Http\ServerRequest $request Request object. * @return mixed Either false or an array of user information */ protected function _getProviderName($request = null) @@ -421,7 +421,7 @@ protected function _getProviderName($request = null) if (!is_null($this->_provider)) { $provider = SocialUtils::getProvider($this->_provider); } elseif (!empty($request)) { - $provider = ucfirst($request->param('provider')); + $provider = ucfirst($request->getParam('provider')); } return $provider; diff --git a/src/Auth/SuperuserAuthorize.php b/src/Auth/SuperuserAuthorize.php index 3a37f24c4..0f38fb42c 100644 --- a/src/Auth/SuperuserAuthorize.php +++ b/src/Auth/SuperuserAuthorize.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Auth; use Cake\Auth\BaseAuthorize; -use Cake\Network\Request; +use Cake\Http\ServerRequest; use Cake\Utility\Hash; /** @@ -37,13 +37,13 @@ class SuperuserAuthorize extends BaseAuthorize * Check if the user is superuser * * @param type $user User information object. - * @param Request $request Cake request object. + * @param \Cake\Http\ServerRequest $request Cake request object. * @return bool */ - public function authorize($user, Request $request) + public function authorize($user, ServerRequest $request) { $user = (array)$user; - $superuserField = $this->config('superuser_field'); + $superuserField = $this->getConfig('superuser_field'); if (Hash::check($user, $superuserField)) { return (bool)Hash::get($user, $superuserField); } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 7d55173c7..147dcfa98 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -16,7 +16,7 @@ use Cake\Core\Configure; use Cake\Event\Event; use Cake\Event\EventManager; -use Cake\Network\Request; +use Cake\Http\ServerRequest; use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; use Cake\Utility\Hash; From cabf1fdea503dd58e3db3d8eb32b6995799fce8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 7 Mar 2017 13:09:15 +0000 Subject: [PATCH 0590/1476] refs #core34 fix missing import --- src/Model/Table/SocialAccountsTable.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index b7d135416..2596b4763 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Model\Table; use Cake\Core\Configure; +use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; From d535c5f3f26caa899f7903771a356ae99bee316e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 8 Mar 2017 09:47:56 +0000 Subject: [PATCH 0591/1476] refs #core34 fix tests to match 3.4 changes --- src/Auth/ApiKeyAuthenticate.php | 5 +- src/Auth/RememberMeAuthenticate.php | 2 +- src/Auth/Rules/AbstractRule.php | 2 +- src/Auth/SimpleRbacAuthorize.php | 2 +- .../Component/RememberMeComponent.php | 8 +- .../Component/UsersAuthComponent.php | 20 ++--- .../TestCase/Auth/ApiKeyAuthenticateTest.php | 74 +++++++++++++------ .../Auth/RememberMeAuthenticateTest.php | 21 +++--- tests/TestCase/Auth/Rules/OwnerTest.php | 57 ++++++-------- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 27 +++---- .../TestCase/Auth/SocialAuthenticateTest.php | 3 +- .../TestCase/Auth/SuperuserAuthorizeTest.php | 9 ++- .../Component/RememberMeComponentTest.php | 5 +- .../Component/UsersAuthComponentTest.php | 12 ++- .../SocialAccountsControllerTest.php | 3 +- .../Controller/Traits/LoginTraitTest.php | 3 +- tests/TestCase/View/Helper/UserHelperTest.php | 3 +- 17 files changed, 142 insertions(+), 114 deletions(-) diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index b0591277c..56921b71b 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -126,7 +126,10 @@ public function querystring(ServerRequest $request) public function header(ServerRequest $request) { $name = $this->getConfig('name'); + if (!empty($request->getHeader($name))) { + return $request->getHeaderLine($name); + } - return $request->getHeader($name); + return null; } } diff --git a/src/Auth/RememberMeAuthenticate.php b/src/Auth/RememberMeAuthenticate.php index c7faa899d..6eb4a01cc 100644 --- a/src/Auth/RememberMeAuthenticate.php +++ b/src/Auth/RememberMeAuthenticate.php @@ -41,7 +41,7 @@ public function authenticate(ServerRequest $request, Response $response) $user = $this->_findUser($cookie['id']); if ($user && !empty($cookie['user_agent']) && - $request->getHeader('User-Agent') === $cookie['user_agent'] + $request->getHeaderLine('User-Agent') === $cookie['user_agent'] ) { return $user; } diff --git a/src/Auth/Rules/AbstractRule.php b/src/Auth/Rules/AbstractRule.php index d0b25cc02..4d4b2e2c1 100644 --- a/src/Auth/Rules/AbstractRule.php +++ b/src/Auth/Rules/AbstractRule.php @@ -72,7 +72,7 @@ protected function _getTable(ServerRequest $request, $table = null) protected function _getTableFromRequest(ServerRequest $request) { $plugin = $request->getParam('plugin'); - $controller = $request->getParams('controller'); + $controller = $request->getParam('controller'); $modelClass = ($plugin ? $plugin . '.' : '') . $controller; $this->modelFactory('Table', [$this->tableLocator(), 'get']); diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 1317ddbfa..b06c5445b 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -229,7 +229,7 @@ protected function _matchPermission(array $permission, array $user, $role, Serve $permission += ['allowed' => true]; $userArr = ['user' => $user]; $reserved = [ - 'prefix' => $request->getParams('prefix'), + 'prefix' => $request->getParam('prefix'), 'plugin' => $request->getParam('plugin'), 'extension' => $request->getParam('_ext'), 'controller' => $request->getParam('controller'), diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index f186cb189..396c1d8d5 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -77,7 +77,7 @@ protected function _validateConfig() */ protected function _attachEvents() { - $eventManager = $this->_registry->getController()->eventManager(); + $eventManager = $this->getController()->eventManager(); $eventManager->on(UsersAuthComponent::EVENT_AFTER_LOGIN, [], [$this, 'setLoginCookie']); $eventManager->on(UsersAuthComponent::EVENT_BEFORE_LOGOUT, [], [$this, 'destroy']); } @@ -141,12 +141,12 @@ public function beforeFilter(Event $event) return; } $this->Auth->setUser($user); - $event = $this->_registry->getController()->dispatchEvent(UsersAuthComponent::EVENT_AFTER_COOKIE_LOGIN); + $event = $this->getController()->dispatchEvent(UsersAuthComponent::EVENT_AFTER_COOKIE_LOGIN); if (is_array($event->result)) { - return $this->_registry->getController()->redirect($event->result); + return $this->getController()->redirect($event->result); } $url = $this->request->here(false); - return $this->_registry->getController()->redirect($url); + return $this->getController()->redirect($url); } } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 147dcfa98..e1a00c3f3 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -67,7 +67,7 @@ public function initialize(array $config) */ protected function _loadGoogleAuthenticator() { - $this->_registry->getController()->loadComponent('CakeDC/Users.GoogleAuthenticator'); + $this->getController()->loadComponent('CakeDC/Users.GoogleAuthenticator'); } /** @@ -77,7 +77,7 @@ protected function _loadGoogleAuthenticator() */ protected function _loadSocialLogin() { - $this->_registry->getController()->Auth->config('authenticate', [ + $this->getController()->Auth->config('authenticate', [ 'CakeDC/Users.Social' ], true); } @@ -89,7 +89,7 @@ protected function _loadSocialLogin() */ protected function _loadRememberMe() { - $this->_registry->getController()->loadComponent('CakeDC/Users.RememberMe'); + $this->getController()->loadComponent('CakeDC/Users.RememberMe'); } /** @@ -111,14 +111,14 @@ protected function _initAuth() { if (Configure::read('Users.auth')) { //initialize Auth - $this->_registry->getController()->loadComponent('Auth', Configure::read('Auth')); + $this->getController()->loadComponent('Auth', Configure::read('Auth')); } list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); if ($this->request->param('plugin') === $plugin && $this->request->param('controller') === $controller ) { - $this->_registry->getController()->Auth->allow([ + $this->getController()->Auth->allow([ // LoginTrait 'twitterLogin', 'login', @@ -178,15 +178,15 @@ public function isUrlAuthorized(Event $event) } // check we are logged in - $user = $this->_registry->getController()->Auth->user(); + $user = $this->getController()->Auth->user(); if (empty($user)) { return false; } - $request = new Request($requestUrl); - $request->params = $requestParams; + $request = new ServerRequest($requestUrl); + $request = $request->addParams($requestParams); - $isAuthorized = $this->_registry->getController()->Auth->isAuthorized(null, $request); + $isAuthorized = $this->getController()->Auth->isAuthorized(null, $request); return $isAuthorized; } @@ -216,7 +216,7 @@ protected function _isActionAllowed($requestParams = []) return false; } $action = strtolower($requestParams['action']); - if (in_array($action, array_map('strtolower', $this->_registry->getController()->Auth->allowedActions))) { + if (in_array($action, array_map('strtolower', $this->getController()->Auth->allowedActions))) { return true; } diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php index 38de9b23f..323154d3b 100644 --- a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use Cake\Http\ServerRequest; use CakeDC\Users\Auth\ApiKeyAuthenticate; use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; @@ -36,7 +37,7 @@ class ApiKeyAuthenticateTest extends TestCase */ public function setUp() { - $request = new Request(); + $request = new ServerRequest(); $response = new Response(); $controller = $this->getMockBuilder('Cake\Controller\Controller') @@ -63,7 +64,7 @@ public function tearDown() */ public function testAuthenticateHappy() { - $request = new Request('/?api_key=xxx'); + $request = new ServerRequest('/?api_key=xxx'); $result = $this->apiKey->authenticate($request, new Response()); $this->assertEquals('user-2', $result['username']); } @@ -75,19 +76,19 @@ public function testAuthenticateHappy() */ public function testAuthenticateFail() { - $request = new Request('/'); + $request = new ServerRequest('/'); $result = $this->apiKey->authenticate($request, new Response()); $this->assertFalse($result); - $request = new Request('/?api_key=none'); + $request = new ServerRequest('/?api_key=none'); $result = $this->apiKey->authenticate($request, new Response()); $this->assertFalse($result); - $request = new Request('/?api_key='); + $request = new ServerRequest('/?api_key='); $result = $this->apiKey->authenticate($request, new Response()); $this->assertFalse($result); - $request = new Request('/?api_key=yyy'); + $request = new ServerRequest('/?api_key=yyy'); $result = $this->apiKey->authenticate($request, new Response()); $this->assertFalse($result); } @@ -102,7 +103,7 @@ public function testAuthenticateFail() public function testAuthenticateWrongType() { $this->apiKey->config('type', 'wrong'); - $request = new Request('/'); + $request = new ServerRequest('/'); $this->apiKey->authenticate($request, new Response()); } @@ -116,7 +117,7 @@ public function testAuthenticateWrongType() public function testAuthenticateRequireSSL() { $this->apiKey->config('require_ssl', true); - $request = new Request('/?api_key=test'); + $request = new ServerRequest('/?api_key=test'); $this->apiKey->authenticate($request, new Response()); } @@ -127,7 +128,7 @@ public function testAuthenticateRequireSSL() public function testAuthenticateRequireSSLNoKey() { $this->apiKey->config('require_ssl', true); - $request = new Request('/'); + $request = new ServerRequest('/'); $this->assertFalse($this->apiKey->authenticate($request, new Response())); } @@ -138,14 +139,18 @@ public function testAuthenticateRequireSSLNoKey() */ public function testHeaderHappy() { - $request = $this->getMockBuilder('\Cake\Network\Request') - ->setMethods(['header']) + $request = $this->getMockBuilder('\Cake\Http\ServerRequest') + ->setMethods(['getHeader', 'getHeaderLine']) ->getMock(); - $request->expects($this->once()) - ->method('header') + $request->expects($this->at(0)) + ->method('getHeader') + ->with('api_key') + ->will($this->returnValue(['xxx'])); + $request->expects($this->at(1)) + ->method('getHeaderLine') ->with('api_key') ->will($this->returnValue('xxx')); - $this->apiKey->config('type', 'header'); + $this->apiKey->setConfig('type', 'header'); $result = $this->apiKey->authenticate($request, new Response()); $this->assertEquals('user-2', $result['username']); } @@ -157,14 +162,37 @@ public function testHeaderHappy() */ public function testAuthenticateHeaderFail() { - $request = $this->getMockBuilder('\Cake\Network\Request') - ->setMethods(['header']) + $request = $this->getMockBuilder('\Cake\Http\ServerRequest') + ->setMethods(['getHeader', 'getHeaderLine']) ->getMock(); - $request->expects($this->once()) - ->method('header') + $request->expects($this->at(0)) + ->method('getHeader') + ->with('api_key') + ->will($this->returnValue(['wrong'])); + $request->expects($this->at(1)) + ->method('getHeaderLine') ->with('api_key') ->will($this->returnValue('wrong')); - $this->apiKey->config('type', 'header'); + $this->apiKey->setConfig('type', 'header'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHeaderNotPresent() + { + $request = $this->getMockBuilder('\Cake\Http\ServerRequest') + ->setMethods(['getHeader']) + ->getMock(); + $request->expects($this->once()) + ->method('getHeader') + ->with('api_key') + ->will($this->returnValue([])); + $this->apiKey->setConfig('type', 'header'); $result = $this->apiKey->authenticate($request, new Response()); $this->assertFalse($result); } @@ -178,8 +206,8 @@ public function testAuthenticateHeaderFail() */ public function testAuthenticateFinderConfig() { - $this->apiKey->config('finder', 'undefinedInConfig'); - $request = new Request('/?api_key=xxx'); + $this->apiKey->setConfig('finder', 'undefinedInConfig'); + $request = new ServerRequest('/?api_key=xxx'); $result = $this->apiKey->authenticate($request, new Response()); } @@ -193,7 +221,7 @@ public function testAuthenticateFinderConfig() public function testAuthenticateFinderAuthConfig() { Configure::write('Auth.authenticate.all.finder', 'undefinedFinderInAuth'); - $request = new Request('/?api_key=xxx'); + $request = new ServerRequest('/?api_key=xxx'); $result = $this->apiKey->authenticate($request, new Response()); } @@ -205,7 +233,7 @@ public function testAuthenticateFinderAuthConfig() public function testAuthenticateDefaultAllFinder() { Configure::write('Auth.authenticate.all.finder', null); - $request = new Request('/?api_key=yyy'); + $request = new ServerRequest('/?api_key=yyy'); $result = $this->apiKey->authenticate($request, new Response()); $this->assertEquals('user-1', $result['username']); } diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php index a23b1f95f..f9f3f566c 100644 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use Cake\Http\ServerRequest; use CakeDC\Users\Auth\RememberMeAuthenticate; use CakeDC\Users\Auth\SuperuserAuthorize; use Cake\Controller\ComponentRegistry; @@ -38,7 +39,7 @@ class RememberMeAuthenticateTest extends TestCase */ public function setUp() { - $request = new Request(); + $request = new ServerRequest(); $response = new Response(); $this->controller = $this->getMockBuilder('Cake\Controller\Controller') @@ -65,8 +66,8 @@ public function tearDown() */ public function testAuthenticateHappy() { - $request = new Request('/'); - $request->env('HTTP_USER_AGENT', 'user-agent'); + $request = new ServerRequest('/'); + $request = $request->env('HTTP_USER_AGENT', 'user-agent'); $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') ->disableOriginalConstructor() ->setMethods(['check', 'read']) @@ -80,7 +81,7 @@ public function testAuthenticateHappy() 'user_agent' => 'user-agent' ])); $registry = new ComponentRegistry($this->controller); - $registry->set('Cookie', $mockCookie); + $this->controller->Cookie = $mockCookie; $this->rememberMe = new RememberMeAuthenticate($registry); $result = $this->rememberMe->authenticate($request, new Response()); $this->assertEquals('user-1', $result['username']); @@ -93,7 +94,7 @@ public function testAuthenticateHappy() */ public function testAuthenticateBadUser() { - $request = new Request('/'); + $request = new ServerRequest('/'); $request->env('HTTP_USER_AGENT', 'user-agent'); $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') ->disableOriginalConstructor() @@ -109,7 +110,7 @@ public function testAuthenticateBadUser() 'user_agent' => 'user-agent' ])); $registry = new ComponentRegistry($this->controller); - $registry->set('Cookie', $mockCookie); + $this->controller->Cookie = $mockCookie; $this->rememberMe = new RememberMeAuthenticate($registry); $result = $this->rememberMe->authenticate($request, new Response()); $this->assertFalse($result); @@ -122,7 +123,7 @@ public function testAuthenticateBadUser() */ public function testAuthenticateBadAgent() { - $request = new Request('/'); + $request = new ServerRequest('/'); $request->env('HTTP_USER_AGENT', 'user-agent'); $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') ->disableOriginalConstructor() @@ -137,7 +138,7 @@ public function testAuthenticateBadAgent() 'user_agent' => 'bad-agent' ])); $registry = new ComponentRegistry($this->controller); - $registry->set('Cookie', $mockCookie); + $this->controller->Cookie = $mockCookie; $this->rememberMe = new RememberMeAuthenticate($registry); $result = $this->rememberMe->authenticate($request, new Response()); $this->assertFalse($result); @@ -150,7 +151,7 @@ public function testAuthenticateBadAgent() */ public function testAuthenticateNoCookie() { - $request = new Request('/'); + $request = new ServerRequest('/'); $request->env('HTTP_USER_AGENT', 'user-agent'); $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') ->disableOriginalConstructor() @@ -163,7 +164,7 @@ public function testAuthenticateNoCookie() ->will($this->returnValue(null)); $registry = new ComponentRegistry($this->controller); - $registry->set('Cookie', $mockCookie); + $this->controller->Cookie = $mockCookie; $this->rememberMe = new RememberMeAuthenticate($registry); $result = $this->rememberMe->authenticate($request, new Response()); $this->assertFalse($result); diff --git a/tests/TestCase/Auth/Rules/OwnerTest.php b/tests/TestCase/Auth/Rules/OwnerTest.php index eac550ec8..cf6296766 100644 --- a/tests/TestCase/Auth/Rules/OwnerTest.php +++ b/tests/TestCase/Auth/Rules/OwnerTest.php @@ -10,13 +10,14 @@ */ namespace CakeDC\Users\Auth\Rules; +use Cake\Http\ServerRequest; use Cake\Network\Request; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; /** * @property Owner Owner - * @property Request request + * @property ServerRequest request */ class OwnerTest extends TestCase { @@ -34,8 +35,7 @@ class OwnerTest extends TestCase public function setUp() { $this->Owner = new Owner(); - $this->request = $this->getMockBuilder('\Cake\Network\Request') - ->getMock(); + $this->request = new ServerRequest(); } /** @@ -54,11 +54,10 @@ public function tearDown() */ public function testAllowed() { - $this->request->params = [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Posts', - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]; + $this->request = $this->request + ->withParam('plugin', 'CakeDC/Users') + ->withParam('controller', 'Posts') + ->withParam('pass', ['00000000-0000-0000-0000-000000000001']); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -75,9 +74,7 @@ public function testAllowedUsingTableAlias() $this->Owner = new Owner([ 'table' => 'Posts' ]); - $this->request->params = [ - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]; + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -94,9 +91,7 @@ public function testAllowedUsingTableInstance() $this->Owner = new Owner([ 'table' => TableRegistry::get('CakeDC/Users.Posts'), ]); - $this->request->params = [ - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]; + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -108,13 +103,11 @@ public function testAllowedUsingTableInstance() * * @return void * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Table alias is empty, please define a table alias, we could not extract a default table from the request + * @expectedExceptionMessage Missing Table alias, we could not extract a default table from the request */ public function testAllowedShouldThrowExceptionBecauseEmptyAliasFromRequest() { - $this->request->params = [ - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]; + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -134,9 +127,7 @@ public function testAllowedShouldThrowExceptionBecauseForeignKeyNotPresentInTabl 'table' => TableRegistry::get('CakeDC/Users.Posts'), 'ownerForeignKey' => 'column_not_found', ]); - $this->request->params = [ - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]; + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -150,11 +141,11 @@ public function testAllowedShouldThrowExceptionBecauseForeignKeyNotPresentInTabl */ public function testNotAllowedBecauseNotOwner() { - $this->request->params = [ + $this->request = $this->request->addParams([ 'plugin' => 'CakeDC/Users', 'controller' => 'Posts', 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]; + ]); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -168,11 +159,11 @@ public function testNotAllowedBecauseNotOwner() */ public function testNotAllowedBecauseUserNotFound() { - $this->request->params = [ + $this->request = $this->request->addParams([ 'plugin' => 'CakeDC/Users', 'controller' => 'Posts', 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]; + ]); $user = [ 'id' => '99999999-0000-0000-0000-000000000000', ]; @@ -186,11 +177,11 @@ public function testNotAllowedBecauseUserNotFound() */ public function testNotAllowedBecausePostNotFound() { - $this->request->params = [ + $this->request = $this->request->addParams([ 'plugin' => 'CakeDC/Users', 'controller' => 'Posts', 'pass' => ['99999999-0000-0000-0000-000000000000'] //not found - ]; + ]); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -206,11 +197,11 @@ public function testNotAllowedBecausePostNotFound() */ public function testNotAllowedBecauseNoDefaultTable() { - $this->request->params = [ + $this->request = $this->request->addParams([ 'plugin' => 'CakeDC/Users', 'controller' => 'NoDefaultTable', 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]; + ]); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -228,11 +219,11 @@ public function testAllowedBelongsToMany() 'table' => 'PostsUsers', 'id' => 'post_id', ]); - $this->request->params = [ + $this->request = $this->request->addParams([ 'plugin' => 'CakeDC/Users', 'controller' => 'IsNotUsed', 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]; + ]); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; @@ -250,11 +241,11 @@ public function testNotAllowedBelongsToMany() 'table' => 'PostsUsers', 'id' => 'post_id', ]); - $this->request->params = [ + $this->request = $this->request->addParams([ 'plugin' => 'CakeDC/Users', 'controller' => 'IsNotUsed', 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]; + ]); $user = [ 'id' => '00000000-0000-0000-0000-000000000001', ]; diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index d2cdf1167..230d0c326 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -11,6 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use Cake\Http\Server; +use Cake\Http\ServerRequest; use CakeDC\Users\Auth\Rules\Rule; use CakeDC\Users\Auth\SimpleRbacAuthorize; use Cake\Controller\ComponentRegistry; @@ -59,7 +61,7 @@ class SimpleRbacAuthorizeTest extends TestCase */ public function setUp() { - $request = new Request(); + $request = new ServerRequest(); $response = new Response(); $this->controller = $this->getMockBuilder('Cake\Controller\Controller') @@ -1185,24 +1187,17 @@ public function badPermissionProvider() /** * @param array $params - * @return \Cake\Network\Request + * @return ServerRequest */ protected function _requestFromArray($params) { - $request = new Request(); - $request->plugin = Hash::get($params, 'plugin'); - $request->controller = $params['controller']; - $request->action = $params['action']; - $prefix = Hash::get($params, 'prefix'); - $request->params = []; - if ($prefix) { - $request->params['prefix'] = $prefix; - } - $extension = Hash::get($params, '_ext'); - if ($extension) { - $request->params['_ext'] = $extension; - } + $request = new ServerRequest(); - return $request; + return $request + ->withParam('plugin', Hash::get($params, 'plugin')) + ->withParam('controller', Hash::get($params, 'controller')) + ->withParam('action', Hash::get($params, 'action')) + ->withParam('prefix', Hash::get($params, 'prefix')) + ->withParam('_ext', Hash::get($params, '_ext')); } } diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index 9a43e882c..86735668c 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -41,7 +42,7 @@ class SocialAuthenticateTest extends TestCase */ public function setUp() { - $request = new Request(); + $request = new ServerRequest(); $response = new Response(); $this->Table = TableRegistry::get('CakeDC/Users.Users'); diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php index 29d12d1b9..35ce1357e 100644 --- a/tests/TestCase/Auth/SuperuserAuthorizeTest.php +++ b/tests/TestCase/Auth/SuperuserAuthorizeTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use Cake\Http\ServerRequest; use CakeDC\Users\Auth\SuperuserAuthorize; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; @@ -33,7 +34,7 @@ class SuperuserAuthorizeTest extends TestCase */ public function setUp() { - $request = new Request(); + $request = new ServerRequest(); $response = new Response(); $this->controller = $this->getMockBuilder('Cake\Controller\Controller') @@ -61,7 +62,7 @@ public function testAuthorizeIsSuperuser() $user = [ 'is_superuser' => true, ]; - $request = new Request(); + $request = new ServerRequest(); $result = $this->superuserAuthorize->authorize($user, $request); $this->assertTrue($result); } @@ -74,7 +75,7 @@ public function testAuthorizeIsNotSuperuser() $user = [ 'is_superuser' => false, ]; - $request = new Request(); + $request = new ServerRequest(); $result = $this->superuserAuthorize->authorize($user, $request); $this->assertFalse($result); } @@ -84,7 +85,7 @@ public function testAuthorizeIsNotSuperuser() */ public function testAuthorizeWeirdUser() { - $request = new Request(); + $request = new ServerRequest(); $user = 'non array'; $result = $this->superuserAuthorize->authorize($user, $request); $this->assertFalse($result); diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index c2c53c21e..71d7c2f6b 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; +use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\RememberMeComponent; use Cake\Controller\ComponentRegistry; use Cake\Controller\Component\AuthComponent; @@ -42,7 +43,7 @@ public function setUp() { parent::setUp(); Security::salt('2a20bac195a9eb2e28f05b7ac7090afe599365a8fe480b7d8a5ce0f79687346e'); - $this->request = new Request('controller_posts/index'); + $this->request = new ServerRequest('controller_posts/index'); $this->request->params['pass'] = []; $this->controller = $this->getMockBuilder('Cake\Controller\Controller') ->setMethods(['redirect']) @@ -122,7 +123,7 @@ public function testSetLoginCookie() ->setMethods(['write']) ->disableOriginalConstructor() ->getMock(); - $this->rememberMeComponent->request = (new Request('/'))->env('HTTP_USER_AGENT', 'user-agent'); + $this->rememberMeComponent->request = (new ServerRequest('/'))->env('HTTP_USER_AGENT', 'user-agent'); $this->rememberMeComponent->Cookie->expects($this->once()) ->method('write') ->with('remember_me', ['id' => 1, 'user_agent' => 'user-agent']); diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 1b1d2cb1f..96978c345 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -249,10 +249,11 @@ public function testIsUrlAuthorizedUrlRelativeString() ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { return $subject->params === [ - 'pass' => [], 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword', + '_ext' => null, + 'pass' => [], '_matchedRoute' => '/route/*', ]; })) @@ -328,10 +329,11 @@ public function testIsUrlAuthorizedUrlAbsoluteForCurrentAppString() ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { return $subject->params === [ - 'pass' => [], 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword', + '_ext' => null, + 'pass' => [], '_matchedRoute' => '/route/*', ]; })) @@ -362,10 +364,11 @@ public function testIsUrlAuthorizedUrlRelativeForCurrentAppString() ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { return $subject->params === [ - 'pass' => [], 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword', + '_ext' => null, + 'pass' => [], '_matchedRoute' => '/route/*', ]; })) @@ -422,10 +425,11 @@ public function testIsUrlAuthorizedUrlArray() ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { return $subject->params === [ - 'pass' => ['pass-one'], 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword', + '_ext' => null, + 'pass' => ['pass-one'], '_matchedRoute' => '/route/*', ]; })) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index c85dc2e86..9d6982d34 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller; +use Cake\Http\ServerRequest; use CakeDC\Users\Controller\SocialAccountsController; use CakeDC\Users\Model\Behavior\SocialAccountBehavior; use CakeDC\Users\Model\Table\SocialAccountsTable; @@ -55,7 +56,7 @@ public function setUp() 'from' => 'cakedc@example.com' ]); - $request = new Request('/users/users/index'); + $request = new ServerRequest('/users/users/index'); $request->params['plugin'] = 'CakeDC/Users'; $this->Controller = $this->getMockBuilder('CakeDC\Users\Controller\SocialAccountsController') diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index f1fbc17a4..e10994e1a 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Exception\AccountNotActiveException; @@ -36,7 +37,7 @@ public function setUp() $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; parent::setUp(); - $request = new Request(); + $request = new ServerRequest(); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') ->setMethods(['dispatchEvent', 'redirect']) ->getMockForTrait(); diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 1c5292dcb..b6754bdc3 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\View\Helper; +use Cake\Http\ServerRequest; use CakeDC\Users\View\Helper\UserHelper; use Cake\Core\App; use Cake\Core\Configure; @@ -51,7 +52,7 @@ public function setUp() ->will($this->returnValue(true)); $this->User = new UserHelper($this->View); $this->User->AuthLink = $this->AuthLink; - $this->request = new Request(); + $this->request = new ServerRequest(); } /** From 14a9cd4776e983bd8f1eceac03ec5a869b0dbaaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 11 Mar 2017 16:52:25 +0000 Subject: [PATCH 0592/1476] refs #core34 WIP fixing deprecated methods and tests --- src/Auth/SocialAuthenticate.php | 3 +- src/Auth/SuperuserAuthorize.php | 2 +- src/Controller/AppController.php | 1 + .../GoogleAuthenticatorComponent.php | 6 +- .../Component/RememberMeComponent.php | 12 ++-- .../Component/UsersAuthComponent.php | 10 +-- src/Controller/SocialAccountsController.php | 8 +-- src/Controller/Traits/LoginTrait.php | 58 ++++++++++------ .../Traits/PasswordManagementTrait.php | 13 ++-- src/Controller/Traits/ProfileTrait.php | 1 + src/Controller/Traits/ReCaptchaTrait.php | 3 +- src/Controller/Traits/RegisterTrait.php | 7 +- src/Controller/Traits/SimpleCrudTrait.php | 9 +-- src/Controller/Traits/SocialTrait.php | 3 +- src/Controller/Traits/UserValidationTrait.php | 13 +++- src/Email/EmailSender.php | 15 +++-- src/Locale/sv/Users.po | 2 +- src/Mailer/UsersMailer.php | 25 ++++--- src/Model/Behavior/PasswordBehavior.php | 5 +- src/Model/Behavior/RegisterBehavior.php | 10 ++- src/Model/Behavior/SocialAccountBehavior.php | 12 ++-- src/Model/Behavior/SocialBehavior.php | 11 ++- src/Model/Table/SocialAccountsTable.php | 6 +- src/Model/Table/UsersTable.php | 6 +- src/Shell/UsersShell.php | 53 ++++++++------- src/Template/Email/html/reset_password.ctp | 8 ++- .../Email/html/social_account_validation.ctp | 32 +++++---- src/Template/Email/html/validation.ctp | 8 ++- src/Template/Email/text/reset_password.ctp | 8 ++- .../Email/text/social_account_validation.ctp | 24 ++++--- src/Template/Email/text/validation.ctp | 8 ++- src/Template/Layout/Email/text/default.ctp | 3 +- src/Template/Users/change_password.ctp | 6 +- src/Template/Users/edit.ctp | 67 ++++++++++--------- src/Template/Users/index.ctp | 36 +++++----- src/Template/Users/login.ctp | 20 +++--- src/Template/Users/profile.ctp | 19 +++--- src/Template/Users/register.ctp | 1 + src/Template/Users/verify.ctp | 6 +- src/Template/Users/view.ctp | 6 +- src/View/Helper/AuthLinkHelper.php | 4 +- src/View/Helper/UserHelper.php | 6 +- .../TestCase/Auth/ApiKeyAuthenticateTest.php | 6 +- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 6 +- .../Component/RememberMeComponentTest.php | 2 +- .../SocialAccountsControllerTest.php | 10 +-- .../Controller/Traits/BaseTraitTest.php | 12 ++-- .../Controller/Traits/LoginTraitTest.php | 6 +- .../Traits/PasswordManagementTraitTest.php | 22 +++--- .../Traits/UserValidationTraitTest.php | 6 +- tests/TestCase/Email/EmailSenderTest.php | 2 +- tests/TestCase/Mailer/UsersMailerTest.php | 26 +++---- .../Model/Behavior/RegisterBehaviorTest.php | 2 +- tests/TestCase/Model/Table/UsersTableTest.php | 8 +-- tests/TestCase/Shell/UsersShellTest.php | 2 +- tests/bootstrap.php | 4 +- 56 files changed, 393 insertions(+), 277 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index fe9f7abf8..6323adab0 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -32,6 +32,7 @@ use Cake\Network\Response; use Cake\ORM\TableRegistry; use Cake\Utility\Hash; +use League\OAuth2\Client\Provider\AbstractProvider; /** * Class SocialAuthenticate @@ -259,7 +260,7 @@ protected function _map($data) public function unauthenticated(ServerRequest $request, Response $response) { $provider = $this->provider($request); - if (empty($provider) || !empty($request->query['code'])) { + if (empty($provider) || !empty($request->getQuery('code'))) { return null; } diff --git a/src/Auth/SuperuserAuthorize.php b/src/Auth/SuperuserAuthorize.php index 0f38fb42c..bc1b83f9c 100644 --- a/src/Auth/SuperuserAuthorize.php +++ b/src/Auth/SuperuserAuthorize.php @@ -36,7 +36,7 @@ class SuperuserAuthorize extends BaseAuthorize /** * Check if the user is superuser * - * @param type $user User information object. + * @param array $user User information object. * @param \Cake\Http\ServerRequest $request Cake request object. * @return bool */ diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 6aa6f5872..473ba02dd 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -15,6 +15,7 @@ /** * AppController for Users Plugin + * */ class AppController extends BaseController { diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php index ddebb49f0..413a5a975 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -15,7 +15,7 @@ */ class GoogleAuthenticatorComponent extends Component { - /** @var RobThree\Auth\TwoFactorAuth $tfa */ + /** @var \RobThree\Auth\TwoFactorAuth $tfa */ public $tfa; /** @@ -41,7 +41,7 @@ public function initialize(array $config) /** * createSecret - * @return base32 shared secret stored in users table + * @return string base32 shared secret stored in users table */ public function createSecret() { @@ -62,6 +62,8 @@ public function verifyCode($secret, $code) /** * getQRCodeImageAsDataUri + * @param $issuer + * @param $secret * @return string base64 string containing QR code for shared secret */ public function getQRCodeImageAsDataUri($issuer, $secret) diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 396c1d8d5..71ae1bcfc 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -105,7 +105,7 @@ public function setLoginCookie(Event $event) if (empty($user)) { return; } - $user['user_agent'] = $this->request->header('User-Agent'); + $user['user_agent'] = $this->getController()->request->getHeaderLine('User-Agent'); $this->Cookie->write($this->_cookieName, $user); } @@ -131,12 +131,16 @@ public function destroy(Event $event) public function beforeFilter(Event $event) { $user = $this->Auth->user(); - if (!empty($user) || $this->request->is(['post', 'put']) || $this->request->action === 'logout' || $this->request->session()->check(Configure::read('Users.Key.Session.social')) || $this->request->param('provider')) { + if (!empty($user) || + $this->getController()->request->is(['post', 'put']) || + $this->getController()->request->getParam('action') === 'logout' || + $this->getController()->request->session()->check(Configure::read('Users.Key.Session.social')) || + $this->getController()->request->getParam('provider')) { return; } $user = $this->Auth->identify(); - //No user no cookies + // No user no cookies if (empty($user)) { return; } @@ -145,7 +149,7 @@ public function beforeFilter(Event $event) if (is_array($event->result)) { return $this->getController()->redirect($event->result); } - $url = $this->request->here(false); + $url = $this->getController()->request->getRequestTarget(); return $this->getController()->redirect($url); } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index e1a00c3f3..e521383c0 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -77,7 +77,7 @@ protected function _loadGoogleAuthenticator() */ protected function _loadSocialLogin() { - $this->getController()->Auth->config('authenticate', [ + $this->getController()->Auth->setConfig('authenticate', [ 'CakeDC/Users.Social' ], true); } @@ -115,8 +115,8 @@ protected function _initAuth() } list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); - if ($this->request->param('plugin') === $plugin && - $this->request->param('controller') === $controller + if ($this->getController()->request->getParam('plugin') === $plugin && + $this->getController()->request->getParam('controller') === $controller ) { $this->getController()->Auth->allow([ // LoginTrait @@ -156,12 +156,12 @@ public function isUrlAuthorized(Event $event) if (is_array($url)) { $requestUrl = Router::reverse($url); - $requestParams = Router::parse($requestUrl); + $requestParams = Router::parseRequest(new ServerRequest($requestUrl)); } else { try { //remove base from $url if exists $normalizedUrl = Router::normalize($url); - $requestParams = Router::parse($normalizedUrl); + $requestParams = Router::parseRequest(new ServerRequest($normalizedUrl)); } catch (MissingRouteException $ex) { //if it's a url pointing to our own app if (substr($normalizedUrl, 0, 1) === '/') { diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index b33b5574c..cbebf6348 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -57,7 +57,7 @@ public function validateAccount($provider, $reference, $token) $this->Flash->error(__d('CakeDC/Users', 'Invalid token and/or social account')); } catch (AccountAlreadyActiveException $exception) { $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); - } catch (Exception $exception) { + } catch (\Exception $exception) { $this->Flash->error(__d('CakeDC/Users', 'Social Account could not be validated')); } @@ -69,8 +69,8 @@ public function validateAccount($provider, $reference, $token) * * @param string $provider provider * @param string $reference reference - * @return Response|void - * @throws \Users\Model\Table\AccountAlreadyActiveException + * @return mixed + * @throws AccountAlreadyActiveException */ public function resendValidation($provider, $reference) { @@ -85,7 +85,7 @@ public function resendValidation($provider, $reference) $this->Flash->error(__d('CakeDC/Users', 'Invalid account')); } catch (AccountAlreadyActiveException $exception) { $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); - } catch (Exception $exception) { + } catch (\Exception $exception) { $this->Flash->error(__d('CakeDC/Users', 'Email could not be resent')); } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 57842b7ac..a51cd66e3 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -25,6 +25,8 @@ /** * Covers the login, logout and social login * + * @property \Cake\Controller\Component\AuthComponent $Auth + * @property \Cake\Http\ServerRequest $request */ trait LoginTrait { @@ -33,7 +35,7 @@ trait LoginTrait /** * Do twitter login * - * @return mixed|void + * @return mixed */ public function twitterLogin() { @@ -43,8 +45,8 @@ public function twitterLogin() 'secret' => Configure::read('OAuth.providers.twitter.options.clientSecret'), 'callbackUri' => Configure::read('OAuth.providers.twitter.options.redirectUri'), ]); - $oauthToken = $this->request->query('oauth_token'); - $oauthVerifier = $this->request->query('oauth_verifier'); + $oauthToken = $this->request->getQuery('oauth_token'); + $oauthVerifier = $this->request->getQuery('oauth_verifier'); if (!empty($oauthToken) && !empty($oauthVerifier)) { $temporaryCredentials = $this->request->session()->read('temporary_credentials'); $tokenCredentials = $server->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); @@ -66,7 +68,11 @@ public function twitterLogin() } if (!empty($exception)) { - return $this->failedSocialLogin($exception, $this->request->session()->read(Configure::read('Users.Key.Session.social')), true); + return $this->failedSocialLogin( + $exception, + $this->request->session()->read(Configure::read('Users.Key.Session.social')), + true + ); } } else { $temporaryCredentials = $server->getTemporaryCredentials(); @@ -79,7 +85,7 @@ public function twitterLogin() /** * @param Event $event event - * @return void + * @return mixed */ public function failedSocialLoginListener(Event $event) { @@ -103,17 +109,27 @@ public function failedSocialLogin($exception, $data, $flash = false) } $this->request->session()->write(Configure::read('Users.Key.Session.social'), $data); - return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); + return $this->redirect([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialEmail' + ]); } if ($exception instanceof UserNotActiveException) { - $msg = __d('CakeDC/Users', 'Your user has not been validated yet. Please check your inbox for instructions'); + $msg = __d( + 'CakeDC/Users', + 'Your user has not been validated yet. Please check your inbox for instructions' + ); } elseif ($exception instanceof AccountNotActiveException) { - $msg = __d('CakeDC/Users', 'Your social account has not been validated yet. Please check your inbox for instructions'); + $msg = __d( + 'CakeDC/Users', + 'Your social account has not been validated yet. Please check your inbox for instructions' + ); } } if ($flash) { - $this->Auth->config('authError', $msg); - $this->Auth->config('flash.params', ['class' => 'success']); + $this->Auth->setConfig('authError', $msg); + $this->Auth->setConfig('flash.params', ['class' => 'success']); $this->request->session()->delete(Configure::read('Users.Key.Session.social')); $this->Flash->success(__d('CakeDC/Users', $msg)); } @@ -129,7 +145,7 @@ public function failedSocialLogin($exception, $data, $flash = false) */ public function socialLogin() { - $socialProvider = $this->request->param('provider'); + $socialProvider = $this->request->getParam('provider'); $socialUser = $this->request->session()->read(Configure::read('Users.Key.Session.social')); if (empty($socialProvider) && empty($socialUser)) { @@ -187,7 +203,7 @@ public function login() * other URL's we store auth'ed used into temporary session * to perform code verification. * - * @return void + * @return mixed */ public function verify() { @@ -224,7 +240,7 @@ public function verify() $query->update() ->set(['secret' => $secret]) ->where(['id' => $temporarySession['id']]); - $executed = $query->execute(); + $query->execute(); } catch (\Exception $e) { $this->request->session()->destroy(); $message = __d('CakeDC/Users', $e->getMessage()); @@ -233,13 +249,16 @@ public function verify() return $this->redirect(Configure::read('Auth.loginAction')); } } - - $this->set('secretDataUri', $this->GoogleAuthenticator->getQRCodeImageAsDataUri($temporarySession['email'], $secret)); + $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( + $temporarySession['email'], + $secret + ); + $this->set(compact('secretDataUri')); } if ($this->request->is('post')) { $codeVerified = false; - $verificationCode = $this->request->data('code'); + $verificationCode = $this->request->getData('code'); $user = $this->request->session()->read('temporarySession'); $entity = $this->getUsersTable()->get($user['id']); @@ -284,7 +303,7 @@ protected function _checkReCaptcha() } return $this->validateReCaptcha( - $this->request->data('g-recaptcha-response'), + $this->request->getData('g-recaptcha-response'), $this->request->clientIp() ); } @@ -293,6 +312,7 @@ protected function _checkReCaptcha() * 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 * @return array */ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthenticatorLogin = false) @@ -327,7 +347,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen /** * Logout * - * @return type + * @return mixed */ public function logout() { @@ -356,7 +376,7 @@ public function logout() protected function _isSocialLogin() { return Configure::read('Users.Social.login') && - $this->request->session()->check(Configure::read('Users.Key.Session.social')); + $this->request->session()->check(Configure::read('Users.Key.Session.social')); } /** diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 450862c10..c8c39217f 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -21,6 +21,7 @@ /** * Covers the password management: reset, change * + * @property \Cake\Http\ServerRequest $request */ trait PasswordManagementTrait { @@ -29,7 +30,7 @@ trait PasswordManagementTrait /** * Change password * - * @return void|\Cake\Network\Response + * @return mixed */ public function changePassword() { @@ -59,7 +60,11 @@ public function changePassword() if (!empty($id)) { $validator = $this->getUsersTable()->validationCurrentPassword($validator); } - $user = $this->getUsersTable()->patchEntity($user, $this->request->data(), ['validate' => $validator]); + $user = $this->getUsersTable()->patchEntity( + $user, + $this->request->getData(), + ['validate' => $validator] + ); if ($user->errors()) { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); } else { @@ -108,7 +113,7 @@ public function requestResetPassword() return; } - $reference = $this->request->data('reference'); + $reference = $this->request->getData('reference'); try { $resetUser = $this->getUsersTable()->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -151,7 +156,7 @@ public function resetGoogleAuthenticator($id = null) $query->update() ->set(['secret_verified' => false, 'secret' => null]) ->where(['id' => $id]); - $executed = $query->execute(); + $query->execute(); $message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset'); $this->Flash->success($message, 'default'); diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 6796d2f9f..6f197dd99 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -19,6 +19,7 @@ /** * Covers the profile action * + * @property \Cake\Http\ServerRequest $request */ trait ProfileTrait { diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php index 394879d0e..650e9ada1 100644 --- a/src/Controller/Traits/ReCaptchaTrait.php +++ b/src/Controller/Traits/ReCaptchaTrait.php @@ -16,6 +16,7 @@ /** * Covers registration features and email token validation * + * @property \Cake\Http\ServerRequest $request */ trait ReCaptchaTrait { @@ -42,7 +43,7 @@ public function validateReCaptcha($recaptchaResponse, $clientIp) /** * Create reCaptcha instance if enabled in configuration * - * @return ReCaptcha + * @return \ReCaptcha\ReCaptcha */ protected function _getReCaptchaInstance() { diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 72661939e..4f8fead4b 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -20,6 +20,7 @@ /** * Covers registration features and email token validation * + * @property \Cake\Http\ServerRequest $request */ trait RegisterTrait { @@ -29,7 +30,7 @@ trait RegisterTrait * Register a new user * * @throws NotFoundException - * @return type + * @return mixed */ public function register() { @@ -54,7 +55,7 @@ public function register() 'validate_email' => $validateEmail, 'use_tos' => $useTos ]; - $requestData = $this->request->data; + $requestData = $this->request->getData(); $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_REGISTER, [ 'usersTable' => $usersTable, 'options' => $options, @@ -105,7 +106,7 @@ protected function _validateRegisterPost() } return $this->validateReCaptcha( - $this->request->data('g-recaptcha-response'), + $this->request->getData('g-recaptcha-response'), $this->request->clientIp() ); } diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index afbdc54d8..b7c630b92 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -18,6 +18,7 @@ /** * Covers the baked CRUD actions, note we could use Crud Plugin too * + * @property \Cake\Http\ServerRequest $request */ trait SimpleCrudTrait { @@ -57,7 +58,7 @@ public function view($id = null) /** * Add method * - * @return void Redirects on successful add, renders view otherwise. + * @return mixed Redirects on successful add, renders view otherwise. */ public function add() { @@ -70,7 +71,7 @@ public function add() if (!$this->request->is('post')) { return; } - $entity = $table->patchEntity($entity, $this->request->data); + $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)); @@ -84,7 +85,7 @@ public function add() * Edit method * * @param string|null $id User id. - * @return void Redirects on successful edit, renders view otherwise. + * @return mixed Redirects on successful edit, renders view otherwise. * @throws NotFoundException When record not found. */ public function edit($id = null) @@ -100,7 +101,7 @@ public function edit($id = null) if (!$this->request->is(['patch', 'post', 'put'])) { return; } - $entity = $table->patchEntity($entity, $this->request->data); + $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)); diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index e922651b5..97f9bb018 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -17,6 +17,7 @@ /** * Covers registration features and email token validation * + * @property \Cake\Http\ServerRequest $request */ trait SocialTrait { @@ -24,7 +25,7 @@ trait SocialTrait * Render the social email form * * @throws NotFoundException - * @return void + * @return mixed */ public function socialEmail() { diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 7be8e21bc..42273094a 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -21,6 +21,7 @@ /** * Covers the user validation * + * @property \Cake\Http\ServerRequest $request */ trait UserValidationTrait { @@ -51,7 +52,10 @@ public function validate($type = null, $token = null) $result = $this->getUsersTable()->validate($token); if (!empty($result)) { $this->Flash->success(__d('CakeDC/Users', 'Reset password token was validated successfully')); - $this->request->session()->write(Configure::read('Users.Key.Session.resetPasswordUserId'), $result->id); + $this->request->session()->write( + Configure::read('Users.Key.Session.resetPasswordUserId'), + $result->id + ); return $this->redirect(['action' => 'changePassword']); } else { @@ -82,7 +86,7 @@ public function resendTokenValidation() if (!$this->request->is('post')) { return; } - $reference = $this->request->data('reference'); + $reference = $this->request->getData('reference'); try { if ($this->getUsersTable()->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -90,7 +94,10 @@ public function resendTokenValidation() 'sendEmail' => true, 'emailTemplate' => 'CakeDC/Users.validation' ])) { - $this->Flash->success(__d('CakeDC/Users', 'Token has been reset successfully. Please check your email.')); + $this->Flash->success(__d( + 'CakeDC/Users', + 'Token has been reset successfully. Please check your email.' + )); } else { $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); } diff --git a/src/Email/EmailSender.php b/src/Email/EmailSender.php index 3b0fcb327..7d24a3add 100644 --- a/src/Email/EmailSender.php +++ b/src/Email/EmailSender.php @@ -49,9 +49,12 @@ public function sendValidationEmail(EntityInterface $user, Email $email = null) * instance * @return array email send result */ - public function sendResetPasswordEmail(EntityInterface $user, Email $email = null, $template = 'CakeDC/Users.reset_password') - { - $this + public function sendResetPasswordEmail( + EntityInterface $user, + Email $email = null, + $template = 'CakeDC/Users.reset_password' + ) { + return $this ->getMailer( 'CakeDC/Users.Users', $this->_getEmailInstance($email) @@ -72,9 +75,9 @@ public function sendSocialValidationEmail(EntityInterface $socialAccount, Entity if (empty($email)) { $template = 'CakeDC/Users.social_account_validation'; } else { - $template = $email->template()['template']; + $template = $email->getTemplate(); } - $this + return $this ->getMailer( 'CakeDC/Users.Users', $this->_getEmailInstance($email) @@ -92,7 +95,7 @@ protected function _getEmailInstance(Email $email = null) { if ($email === null) { $email = new Email('default'); - $email->emailFormat('both'); + $email->setEmailFormat('both'); } return $email; diff --git a/src/Locale/sv/Users.po b/src/Locale/sv/Users.po index 1f0d2f41f..8f27e7636 100644 --- a/src/Locale/sv/Users.po +++ b/src/Locale/sv/Users.po @@ -51,7 +51,7 @@ msgid "" "Missing column {0} in table {1} while checking ownership permissions for " "user {2}" msgstr "" -"Saknar kolumn {0} i tabell {1} ​​vid kontroll av ägarbehörigheter för " +"Saknar kolumn {0} i tabell {1} vid kontroll av ägarbehörigheter för " "användare {2}" #: Controller/SocialAccountsController.php:52 diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 3ef4c5c75..367e0a343 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -36,9 +36,9 @@ protected function validation(EntityInterface $user, $subject, $template = 'Cake $this ->to($user['email']) - ->subject($firstName . $subject) - ->viewVars($user->toArray()) - ->template($template); + ->setSubject($firstName . $subject) + ->setViewVars($user->toArray()) + ->setTemplate($template); } /** @@ -57,9 +57,9 @@ protected function resetPassword(EntityInterface $user, $template = 'CakeDC/User $this ->to($user['email']) - ->subject($subject) - ->viewVars($user->toArray()) - ->template($template); + ->setSubject($subject) + ->setViewVars($user->toArray()) + ->setTemplate($template); } /** @@ -71,15 +71,18 @@ protected function resetPassword(EntityInterface $user, $template = 'CakeDC/User * * @return array email send result */ - protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount, $template = 'CakeDC/Users.social_account_validation') - { + protected function socialAccountValidation( + EntityInterface $user, + EntityInterface $socialAccount, + $template = 'CakeDC/Users.social_account_validation' + ) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; //note: we control the space after the username in the previous line $subject = __d('CakeDC/Users', '{0}Your social account validation link', $firstName); $this ->to($user['email']) - ->subject($subject) - ->viewVars(compact('user', 'socialAccount')) - ->template($template); + ->setSubject($subject) + ->setViewVars(compact('user', 'socialAccount')) + ->setTemplate($template); } } diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 44c823c14..1966502fe 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -121,7 +121,10 @@ public function changePassword(EntityInterface $user) throw new WrongPasswordException(__d('CakeDC/Users', 'The current password does not match')); } if ($user->current_password === $user->password_confirm) { - throw new WrongPasswordException(__d('CakeDC/Users', 'You cannot use the current password as the new one')); + throw new WrongPasswordException(__d( + 'CakeDC/Users', + 'You cannot use the current password as the new one' + )); } } $user = $this->_table->save($user); diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 0a4cd21b3..d07edb9ce 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -57,7 +57,11 @@ public function register($user, $data, $options) $validateEmail = Hash::get($options, 'validate_email'); $tokenExpiration = Hash::get($options, 'token_expiration'); $emailClass = Hash::get($options, 'email_class'); - $user = $this->_table->patchEntity($user, $data, ['validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options)]); + $user = $this->_table->patchEntity( + $user, + $data, + ['validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options)] + ); $user->validated = false; //@todo move updateActive to afterSave? $user = $this->_updateActive($user, $validateEmail, $tokenExpiration); @@ -73,7 +77,7 @@ public function register($user, $data, $options) /** * Validates token and return user * - * @param type $token toke to be validated. + * @param string $token toke to be validated. * @param null $callback function that will be returned. * @throws TokenExpiredException when token has expired. * @throws UserNotFoundException when user isn't found. @@ -131,6 +135,8 @@ public function buildValidator(Event $event, Validator $validator, $name) if ($name === 'default') { return $this->_emailValidator($validator, $this->validateEmail); } + + return $validator; } /** diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 18f8e5229..591da7263 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -14,6 +14,7 @@ use ArrayObject; use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\AccountAlreadyActiveException; +use CakeDC\Users\Model\Entity\SocialAccount; use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; @@ -72,10 +73,13 @@ public function afterSave(Event $event, Entity $entity, $options) * @param EntityInterface $socialAccount social account * @param EntityInterface $user user * @param Email $email Email instance or null to use 'default' configuration - * @return mixed + * @return void */ - public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) - { + public function sendSocialValidationEmail( + EntityInterface $socialAccount, + EntityInterface $user, + Email $email = null + ) { $this->Email = new EmailSender(); $this->Email->sendSocialValidationEmail($socialAccount, $user, $email); } @@ -138,7 +142,7 @@ public function resendValidation($provider, $reference) /** * Activates an account * - * @param Account $socialAccount social account + * @param SocialAccount $socialAccount social account * @return EntityInterface */ protected function _activateAccount($socialAccount) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index d8b0816c3..cf1fe3e2b 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -44,7 +44,10 @@ public function socialLogin(array $data, array $options) { $reference = Hash::get($data, 'id'); $existingAccount = $this->_table->SocialAccounts->find() - ->where(['SocialAccounts.reference' => $reference, 'SocialAccounts.provider' => Hash::get($data, 'provider')]) + ->where([ + 'SocialAccounts.reference' => $reference, + 'SocialAccounts.provider' => Hash::get($data, 'provider') + ]) ->contain(['Users']) ->first(); if (empty($existingAccount->user)) { @@ -98,7 +101,7 @@ protected function _createSocialUser($data, $options = []) throw new MissingEmailException(__d('CakeDC/Users', 'Email not present')); } else { $existingUser = $this->_table->find() - ->where([$this->_table->alias() . '.email' => $email]) + ->where([$this->_table->aliasField('email') => $email]) ->first(); } @@ -211,7 +214,9 @@ public function generateUniqueUsername($username) { $i = 0; while (true) { - $existingUsername = $this->_table->find()->where([$this->_table->alias() . '.username' => $username])->count(); + $existingUsername = $this->_table->find() + ->where([$this->_table->aliasField('username') => $username]) + ->count(); if ($existingUsername > 0) { $username = $username . $i; $i++; diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 2596b4763..fe72a2525 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -41,9 +41,9 @@ public function initialize(array $config) { parent::initialize($config); - $this->table('social_accounts'); - $this->displayField('id'); - $this->primaryKey('id'); + $this->setTable('social_accounts'); + $this->setDisplayField('id'); + $this->setPrimaryKey('id'); $this->addBehavior('Timestamp'); $this->addBehavior('CakeDC/Users.SocialAccount'); } diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 2c221fe2b..087ea5d87 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -46,9 +46,9 @@ public function initialize(array $config) { parent::initialize($config); - $this->table('users'); - $this->displayField('username'); - $this->primaryKey('id'); + $this->setTable('users'); + $this->setDisplayField('username'); + $this->setPrimaryKey('id'); $this->addBehavior('Timestamp'); $this->addBehavior('CakeDC/Users.Register'); $this->addBehavior('CakeDC/Users.Password'); diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 2c5ef1895..d8620765b 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -11,17 +11,19 @@ namespace CakeDC\Users\Shell; +use Cake\Console\ConsoleOptionParser; use CakeDC\Users\Model\Entity\User; use Cake\Auth\DefaultPasswordHasher; use Cake\Console\Shell; use Cake\Core\Configure; use Cake\Utility\Hash; use Cake\Utility\Text; +use CakeDC\Users\Model\Table\UsersTable; /** * Shell with utilities for the Users Plugin * - * @property \Users\Model\Table\Users Users + * @property UsersTable Users */ class UsersShell extends Shell { @@ -31,7 +33,10 @@ class UsersShell extends Shell * * @var array */ - protected $_usernameSeed = ['aayla', 'admiral', 'anakin', 'chewbacca', 'darthvader', 'hansolo', 'luke', 'obiwan', 'leia', 'r2d2']; + protected $_usernameSeed = [ + 'aayla', 'admiral', 'anakin', 'chewbacca', + 'darthvader', 'hansolo', 'luke', 'obiwan', 'leia', 'r2d2' + ]; /** * initialize callback @@ -46,21 +51,21 @@ public function initialize() /** * - * @return OptionParser + * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); - $parser->description(__d('CakeDC/Users', 'Utilities for CakeDC Users Plugin')) - ->addSubcommand('activateUser')->description(__d('CakeDC/Users', 'Activate an specific user')) - ->addSubcommand('addSuperuser')->description(__d('CakeDC/Users', 'Add a new superadmin user for testing purposes')) - ->addSubcommand('addUser')->description(__d('CakeDC/Users', 'Add a new user')) - ->addSubcommand('changeRole')->description(__d('CakeDC/Users', 'Change the role for an specific user')) - ->addSubcommand('deactivateUser')->description(__d('CakeDC/Users', 'Deactivate an specific user')) - ->addSubcommand('deleteUser')->description(__d('CakeDC/Users', 'Delete an specific user')) - ->addSubcommand('passwordEmail')->description(__d('CakeDC/Users', 'Reset the password via email')) - ->addSubcommand('resetAllPasswords')->description(__d('CakeDC/Users', 'Reset the password for all users')) - ->addSubcommand('resetPassword')->description(__d('CakeDC/Users', 'Reset the password for an specific user')) + $parser->setDescription(__d('CakeDC/Users', 'Utilities for CakeDC Users Plugin')) + ->addSubcommand('activateUser')->setDescription(__d('CakeDC/Users', 'Activate an specific user')) + ->addSubcommand('addSuperuser')->setDescription(__d('CakeDC/Users', 'Add a new superadmin user for testing purposes')) + ->addSubcommand('addUser')->setDescription(__d('CakeDC/Users', 'Add a new user')) + ->addSubcommand('changeRole')->setDescription(__d('CakeDC/Users', 'Change the role for an specific user')) + ->addSubcommand('deactivateUser')->setDescription(__d('CakeDC/Users', 'Deactivate an specific user')) + ->addSubcommand('deleteUser')->setDescription(__d('CakeDC/Users', 'Delete an specific user')) + ->addSubcommand('passwordEmail')->setDescription(__d('CakeDC/Users', 'Reset the password via email')) + ->addSubcommand('resetAllPasswords')->setDescription(__d('CakeDC/Users', 'Reset the password for all users')) + ->addSubcommand('resetPassword')->setDescription(__d('CakeDC/Users', 'Reset the password for an specific user')) ->addOptions([ 'username' => ['short' => 'u', 'help' => 'The username for the new user'], 'password' => ['short' => 'p', 'help' => 'The password for the new user'], @@ -108,7 +113,7 @@ public function resetAllPasswords() { $password = Hash::get($this->args, 0); if (empty($password)) { - $this->error(__d('CakeDC/Users', 'Please enter a password.')); + $this->setError(__d('CakeDC/Users', 'Please enter a password.')); } $hashedPassword = $this->_generatedHashedPassword($password); $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); @@ -131,10 +136,10 @@ public function resetPassword() $username = Hash::get($this->args, 0); $password = Hash::get($this->args, 1); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($password)) { - $this->error(__d('CakeDC/Users', 'Please enter a password.')); + $this->setError(__d('CakeDC/Users', 'Please enter a password.')); } $data = [ 'password' => $password @@ -159,10 +164,10 @@ public function changeRole() $username = Hash::get($this->args, 0); $role = Hash::get($this->args, 1); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($role)) { - $this->error(__d('CakeDC/Users', 'Please enter a role.')); + $this->setError(__d('CakeDC/Users', 'Please enter a role.')); } $data = [ 'role' => $role @@ -211,7 +216,7 @@ public function passwordEmail() { $reference = Hash::get($this->args, 0); if (empty($reference)) { - $this->error(__d('CakeDC/Users', 'Please enter a username or email.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username or email.')); } $resetUser = $this->Users->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -223,7 +228,7 @@ public function passwordEmail() $this->out($msg); } else { $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); - $this->error($msg); + $this->setError($msg); } } @@ -237,7 +242,7 @@ protected function _changeUserActive($active) { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } $data = [ 'active' => $active @@ -312,7 +317,7 @@ protected function _updateUser($username, $data) { $user = $this->Users->find()->where(['username' => $username])->first(); if (empty($user)) { - $this->error(__d('CakeDC/Users', 'The user was not found.')); + $this->setError(__d('CakeDC/Users', 'The user was not found.')); } $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { @@ -334,7 +339,7 @@ public function deleteUser() { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } $user = $this->Users->find()->where(['username' => $username])->first(); if (isset($this->Users->SocialAccounts)) { @@ -342,7 +347,7 @@ public function deleteUser() } $deleteUser = $this->Users->delete($user); if (!$deleteUser) { - $this->error(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); + $this->setError(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); } $this->out(__d('CakeDC/Users', 'The user {0} was deleted successfully', $username)); } diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp index 307c9c3cf..a0c766f45 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -18,13 +18,17 @@ $activationUrl = [ ]; ?>

-, + ,

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

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

, diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp index 5dcd6dc71..f8a3aa27f 100644 --- a/src/Template/Email/html/social_account_validation.ctp +++ b/src/Template/Email/html/social_account_validation.ctp @@ -11,25 +11,29 @@ ?>

-, + ,

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

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

, diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index 0e722b118..de4c4360e 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -18,13 +18,17 @@ $activationUrl = [ ]; ?>

-, + ,

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

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

, diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp index 49018fb92..edd6d607f 100644 --- a/src/Template/Email/text/reset_password.ctp +++ b/src/Template/Email/text/reset_password.ctp @@ -17,9 +17,13 @@ $activationUrl = [ isset($token) ? $token : '' ]; ?> -, +, -Url->build($activationUrl)) ?> +Url->build($activationUrl) +) ?> , diff --git a/src/Template/Email/text/social_account_validation.ctp b/src/Template/Email/text/social_account_validation.ctp index 72b1f1279..9da21fa36 100644 --- a/src/Template/Email/text/social_account_validation.ctp +++ b/src/Template/Email/text/social_account_validation.ctp @@ -9,19 +9,23 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - $activationUrl = [ - '_full' => true, - 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'validateAccount', - $socialAccount['provider'], - $socialAccount['reference'], - $socialAccount['token'], - ]; +$activationUrl = [ + '_full' => true, + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validateAccount', + $socialAccount['provider'], + $socialAccount['reference'], + $socialAccount['token'], +]; ?> , -Url->build($activationUrl)) ?> +Url->build($activationUrl) +) ?> , diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp index a423ee9ea..4f40f1342 100644 --- a/src/Template/Email/text/validation.ctp +++ b/src/Template/Email/text/validation.ctp @@ -17,9 +17,13 @@ $activationUrl = [ isset($token) ? $token : '' ]; ?> -, +, -Url->build($activationUrl)) ?> +Url->build($activationUrl) +) ?> , diff --git a/src/Template/Layout/Email/text/default.ctp b/src/Template/Layout/Email/text/default.ctp index 871dcfb48..eef4d035e 100644 --- a/src/Template/Layout/Email/text/default.ctp +++ b/src/Template/Layout/Email/text/default.ctp @@ -13,4 +13,5 @@ * @license http://www.opensource.org/licenses/mit-license.php MIT License */ ?> -fetch('content') ?> +fetch('content'); diff --git a/src/Template/Users/change_password.ctp b/src/Template/Users/change_password.ctp index 3a7530451..4c6f5bec0 100644 --- a/src/Template/Users/change_password.ctp +++ b/src/Template/Users/change_password.ctp @@ -5,9 +5,9 @@ Form->input('current_password', [ - 'type' => 'password', - 'required' => true, - 'label' => __d('CakeDC/Users', 'Current password')]); + 'type' => 'password', + 'required' => true, + 'label' => __d('CakeDC/Users', 'Current password')]); ?> Form->input('password', [ diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index e85c53d36..7c482a959 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -32,43 +32,46 @@ $Users = ${$tableAlias};

Form->input('username', ['label' => __d('CakeDC/Users', 'Username')]); - echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); - echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); - echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - echo $this->Form->input('token', ['label' => __d('CakeDC/Users', 'Token')]); - echo $this->Form->input('token_expires', [ - 'label' => __d('CakeDC/Users', 'Token expires') - ]); - echo $this->Form->input('api_token', [ - 'label' => __d('CakeDC/Users', 'API token') - ]); - echo $this->Form->input('activation_date', [ - 'label' => __d('CakeDC/Users', 'Activation date') - ]); - echo $this->Form->input('tos_date', [ - 'label' => __d('CakeDC/Users', 'TOS date') - ]); - echo $this->Form->input('active', [ - 'label' => __d('CakeDC/Users', 'Active') - ]); + echo $this->Form->input('username', ['label' => __d('CakeDC/Users', 'Username')]); + echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); + echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->input('token', ['label' => __d('CakeDC/Users', 'Token')]); + echo $this->Form->input('token_expires', [ + 'label' => __d('CakeDC/Users', 'Token expires') + ]); + echo $this->Form->input('api_token', [ + 'label' => __d('CakeDC/Users', 'API token') + ]); + echo $this->Form->input('activation_date', [ + 'label' => __d('CakeDC/Users', 'Activation date') + ]); + echo $this->Form->input('tos_date', [ + 'label' => __d('CakeDC/Users', 'TOS date') + ]); + echo $this->Form->input('active', [ + 'label' => __d('CakeDC/Users', 'Active') + ]); ?>
Form->button(__d('CakeDC/Users', 'Submit')) ?> Form->end() ?> - -
- Reset Google Authenticator - Form->postLink( - __d('CakeDC/Users', 'Reset Google Authenticator Token'), [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetGoogleAuthenticator', $Users->id - ], [ + +
+ Reset Google Authenticator + Form->postLink( + __d('CakeDC/Users', 'Reset Google Authenticator Token'), [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetGoogleAuthenticator', $Users->id + ], [ 'class' => 'btn btn-danger', - 'confirm' => __d('CakeDC/Users', 'Are you sure you want to reset token for user "{0}"?', $Users->username) + 'confirm' => __d( + 'CakeDC/Users', + 'Are you sure you want to reset token for user "{0}"?', $Users->username + ) ]); - ?> -
+ ?> +
diff --git a/src/Template/Users/index.ctp b/src/Template/Users/index.ctp index 2b224b85d..112687b10 100644 --- a/src/Template/Users/index.ctp +++ b/src/Template/Users/index.ctp @@ -17,7 +17,7 @@
- + @@ -25,24 +25,24 @@ - - - - - - - - - - + + + + + + + + + + - - + +
Paginator->sort('username', __d('CakeDC/Users', 'Username')) ?> Paginator->sort('email', __d('CakeDC/Users', 'Email')) ?>Paginator->sort('last_name', __d('CakeDC/Users', 'Last name')) ?>
username) ?>email) ?>first_name) ?>last_name) ?> - Html->link(__d('CakeDC/Users', 'View'), ['action' => 'view', $user->id]) ?> - Html->link(__d('CakeDC/Users', 'Change password'), ['action' => 'changePassword', $user->id]) ?> - Html->link(__d('CakeDC/Users', 'Edit'), ['action' => 'edit', $user->id]) ?> - Form->postLink(__d('CakeDC/Users', 'Delete'), ['action' => 'delete', $user->id], ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $user->id)]) ?> -
username) ?>email) ?>first_name) ?>last_name) ?> + Html->link(__d('CakeDC/Users', 'View'), ['action' => 'view', $user->id]) ?> + Html->link(__d('CakeDC/Users', 'Change password'), ['action' => 'changePassword', $user->id]) ?> + Html->link(__d('CakeDC/Users', 'Edit'), ['action' => 'edit', $user->id]) ?> + Form->postLink(__d('CakeDC/Users', 'Delete'), ['action' => 'delete', $user->id], ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $user->id)]) ?> +
    diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 60b36c2af..b6ce0a0c0 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -31,18 +31,18 @@ use Cake\Core\Configure; ]); } ?> - Html->link(__d('CakeDC/Users', 'Register'), ['action' => 'register']); + } + if (Configure::read('Users.Email.required')) { if ($registrationActive) { - echo $this->Html->link(__d('CakeDC/Users', 'Register'), ['action' => 'register']); - } - if (Configure::read('Users.Email.required')) { - if ($registrationActive) { - echo ' | '; - } - echo $this->Html->link(__d('CakeDC/Users', 'Reset Password'), ['action' => 'requestResetPassword']); + echo ' | '; } - ?> + echo $this->Html->link(__d('CakeDC/Users', 'Reset Password'), ['action' => 'requestResetPassword']); + } + ?> User->socialLoginList()); ?> Form->button(__d('CakeDC/Users', 'Login')); ?> diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index 65f09904a..efebde7f6 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -10,7 +10,10 @@ */ ?>
    -

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

    +

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

    Html->tag( @@ -34,11 +37,11 @@

    - - - - - + + + + + '_blank'] ) ?> -
    -
    diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index 4238cd603..bd4a0588a 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -9,6 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ use Cake\Core\Configure; + ?>
    Form->create($user); ?> diff --git a/src/Template/Users/verify.ctp b/src/Template/Users/verify.ctp index 087fdaa6e..450480906 100644 --- a/src/Template/Users/verify.ctp +++ b/src/Template/Users/verify.ctp @@ -7,9 +7,9 @@ Flash->render('auth') ?> Flash->render() ?>
    - -

    - + +

    + Form->input('code', ['required' => true, 'label' => __d('CakeDC/Users', 'Verification Code')]) ?>
    Form->button(__d('CakeDC/Users', ' Verify'), ['class' => 'btn btn-primary']); ?> diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp index b9d513959..c38fa0c1a 100644 --- a/src/Template/Users/view.ctp +++ b/src/Template/Users/view.ctp @@ -15,7 +15,11 @@ $Users = ${$tableAlias};

    • Html->link(__d('CakeDC/Users', 'Edit User'), ['action' => 'edit', $Users->id]) ?>
    • -
    • Form->postLink(__d('CakeDC/Users', 'Delete User'), ['action' => 'delete', $Users->id], ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)]) ?>
    • +
    • Form->postLink( + __d('CakeDC/Users', 'Delete User'), + ['action' => 'delete', $Users->id], + ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] + ) ?>
    • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
    • Html->link(__d('CakeDC/Users', 'New User'), ['action' => 'add']) ?>
    diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index 69eed8070..07a8cd90c 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -34,7 +34,9 @@ public function link($title, $url = null, array $options = []) return false; } if ($allowed === true || $this->isAuthorized($url)) { - return Hash::get($options, 'before') . parent::link($title, $url, $linkOptions) . Hash::get($options, 'after'); + return Hash::get($options, 'before') . + parent::link($title, $url, $linkOptions) . + Hash::get($options, 'after'); } return false; diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index fdefd4431..bd3754410 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -55,7 +55,11 @@ public function socialLogin($name, $options = []) $providerTitle = __d('CakeDC/Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)); } - $providerClass = __d('CakeDC/Users', 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', strtolower($name)); + $providerClass = __d( + 'CakeDC/Users', + 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', + strtolower($name) + ); return $this->Html->link($icon . $providerTitle, "/auth/$name", [ 'escape' => false, 'class' => $providerClass diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php index 323154d3b..21f01cec3 100644 --- a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -102,7 +102,7 @@ public function testAuthenticateFail() */ public function testAuthenticateWrongType() { - $this->apiKey->config('type', 'wrong'); + $this->apiKey->setConfig('type', 'wrong'); $request = new ServerRequest('/'); $this->apiKey->authenticate($request, new Response()); } @@ -116,7 +116,7 @@ public function testAuthenticateWrongType() */ public function testAuthenticateRequireSSL() { - $this->apiKey->config('require_ssl', true); + $this->apiKey->setConfig('require_ssl', true); $request = new ServerRequest('/?api_key=test'); $this->apiKey->authenticate($request, new Response()); } @@ -127,7 +127,7 @@ public function testAuthenticateRequireSSL() */ public function testAuthenticateRequireSSLNoKey() { - $this->apiKey->config('require_ssl', true); + $this->apiKey->setConfig('require_ssl', true); $request = new ServerRequest('/'); $this->assertFalse($this->apiKey->authenticate($request, new Response())); } diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php index 230d0c326..537a291fc 100644 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -87,7 +87,7 @@ public function testConstruct() { //don't autoload config $this->simpleRbacAuthorize = new SimpleRbacAuthorize($this->registry, ['autoload_config' => false]); - $this->assertEmpty($this->simpleRbacAuthorize->config('permissions')); + $this->assertEmpty($this->simpleRbacAuthorize->getConfig('permissions')); } /** @@ -117,7 +117,7 @@ public function testConstructMissingPermissionsFile() ->setConstructorArgs([$this->registry, ['autoload_config' => 'does-not-exist']]) ->getMock(); //we should have the default permissions - $this->assertEquals($this->defaultPermissions, $this->simpleRbacAuthorize->config('permissions')); + $this->assertEquals($this->defaultPermissions, $this->simpleRbacAuthorize->getConfig('permissions')); } protected function assertConstructorPermissions($instance, $config, $permissions) @@ -127,7 +127,7 @@ protected function assertConstructorPermissions($instance, $config, $permissions $constructor->invoke($this->simpleRbacAuthorize, $this->registry, $config); //we should have the default permissions - $resultPermissions = $this->simpleRbacAuthorize->config('permissions'); + $resultPermissions = $this->simpleRbacAuthorize->getConfig('permissions'); $this->assertEquals($permissions, $resultPermissions); } diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 71d7c2f6b..137548971 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -44,7 +44,7 @@ public function setUp() parent::setUp(); Security::salt('2a20bac195a9eb2e28f05b7ac7090afe599365a8fe480b7d8a5ce0f79687346e'); $this->request = new ServerRequest('controller_posts/index'); - $this->request->params['pass'] = []; + $this->request = $this->request->withParam('pass', []); $this->controller = $this->getMockBuilder('Cake\Controller\Controller') ->setMethods(['redirect']) ->setConstructorArgs([$this->request]) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 9d6982d34..38cc9331b 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -47,17 +47,17 @@ public function setUp() Configure::write('Opauth', null); Configure::write('Users.RememberMe.active', false); - Email::configTransport('test', [ + Email::setConfigTransport('test', [ 'className' => 'Debug' ]); - $this->configEmail = Email::config('default'); - Email::config('default', [ + $this->configEmail = Email::getConfig('default'); + Email::setConfig('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' ]); $request = new ServerRequest('/users/users/index'); - $request->params['plugin'] = 'CakeDC/Users'; + $request = $request->withParam('plugin', 'CakeDC/Users'); $this->Controller = $this->getMockBuilder('CakeDC\Users\Controller\SocialAccountsController') ->setMethods(['redirect', 'render']) @@ -77,7 +77,7 @@ public function tearDown() { Email::drop('default'); Email::dropTransport('test'); - Email::config('default', $this->configEmail); + //Email::setConfig('default', $this->configEmail); Configure::write('Opauth', $this->configOpauth); Configure::write('Users.RememberMe.active', $this->configRememberMe); diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 299de8ba5..6ad00d84e 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -60,11 +60,11 @@ public function setUp() } if ($this->mockDefaultEmail) { - Email::configTransport('test', [ + Email::setConfigTransport('test', [ 'className' => 'Debug' ]); - $this->configEmail = Email::config('default'); - Email::config('default', [ + $this->configEmail = Email::getConfig('default'); + Email::setConfig('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' ]); @@ -82,7 +82,7 @@ public function tearDown() if ($this->mockDefaultEmail) { Email::drop('default'); Email::dropTransport('test'); - Email::config('default', $this->configEmail); + //Email::setConfig('default', $this->setConfigEmail); } parent::tearDown(); } @@ -113,7 +113,7 @@ protected function _mockSession($attributes) */ protected function _mockRequestGet($withSession = false) { - $methods = ['is', 'referer', 'data']; + $methods = ['is', 'referer', 'getData']; if ($withSession) { $methods[] = 'session'; @@ -150,7 +150,7 @@ protected function _mockFlash() protected function _mockRequestPost($with = 'post') { $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'data', 'allow']) + ->setMethods(['is', 'getData', 'allow']) ->getMock(); $this->Trait->request->expects($this->any()) ->method('is') diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index e10994e1a..11ab5483e 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -43,7 +43,7 @@ public function setUp() ->getMockForTrait(); $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['config']) + ->setMethods(['setConfig']) ->disableOriginalConstructor() ->getMock(); @@ -326,11 +326,11 @@ public function testFailedSocialUserNotActive() ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Trait->Auth->expects($this->at(0)) - ->method('config') + ->method('setConfig') ->with('authError', 'Your user has not been validated yet. Please check your inbox for instructions'); $this->Trait->Auth->expects($this->at(1)) - ->method('config') + ->method('setConfig') ->with('flash.params', ['class' => 'success']); $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 681c4ef33..115f0db0c 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -54,7 +54,7 @@ public function testChangePasswordHappy() $this->_mockAuthLoggedIn(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->will($this->returnValue([ 'password' => 'new', 'password_confirm' => 'new', @@ -82,7 +82,7 @@ public function testChangePasswordWithError() $this->_mockAuthLoggedIn(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->will($this->returnValue([ 'password' => 'new', 'password_confirm' => 'wrong_new', @@ -108,7 +108,7 @@ public function testChangePasswordWithSamePassword() $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->will($this->returnValue([ 'current_password' => '12345', 'password' => '12345', @@ -131,7 +131,7 @@ public function testChangePasswordWithEmptyCurrentPassword() $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->will($this->returnValue([ 'current_password' => '', 'password' => '54321', @@ -158,7 +158,7 @@ public function testChangePasswordWithWrongCurrentPassword() $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->will($this->returnValue([ 'current_password' => 'wrong-password', 'password' => '12345', @@ -181,7 +181,7 @@ public function testChangePasswordWithInvalidUser() $this->_mockAuthLoggedIn(['id' => '12312312-0000-0000-0000-000000000002', 'password' => 'invalid-pass']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->will($this->returnValue([ 'password' => 'new', 'password_confirm' => 'new', @@ -275,7 +275,7 @@ public function testRequestResetPasswordGet() $this->_mockRequestGet(); $this->_mockFlash(); $this->Trait->request->expects($this->never()) - ->method('data'); + ->method('getData'); $this->Trait->requestResetPassword(); } @@ -292,7 +292,7 @@ public function testRequestPasswordHappy() $this->_mockFlash(); $reference = 'user-2'; $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->with('reference') ->will($this->returnValue($reference)); $this->Trait->Flash->expects($this->any()) @@ -314,7 +314,7 @@ public function testRequestPasswordInvalidUser() $this->_mockFlash(); $reference = '12312312-0000-0000-0000-000000000002'; $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->with('reference') ->will($this->returnValue($reference)); $this->Trait->Flash->expects($this->any()) @@ -335,7 +335,7 @@ public function testRequestPasswordEmptyReference() $this->_mockFlash(); $reference = ''; $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->with('reference') ->will($this->returnValue($reference)); $this->Trait->Flash->expects($this->any()) @@ -363,7 +363,7 @@ public function testEnsureUserActiveForResetPasswordFeature($ensureActive) $this->_mockFlash(); $reference = 'user-1'; $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->with('reference') ->will($this->returnValue($reference)); $this->Trait->Flash->expects($expectError) diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 1a9d18a9b..86bbe65b8 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -133,7 +133,7 @@ public function testResendTokenValidationHappy() $this->_mockRequestPost(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->with('reference') ->will($this->returnValue('user-3')); @@ -156,7 +156,7 @@ public function testResendTokenValidationAlreadyActive() $this->_mockRequestPost(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->with('reference') ->will($this->returnValue('user-4')); @@ -179,7 +179,7 @@ public function testResendTokenValidationNotFound() $this->_mockRequestPost(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) - ->method('data') + ->method('getData') ->with('reference') ->will($this->returnValue('not-found')); diff --git a/tests/TestCase/Email/EmailSenderTest.php b/tests/TestCase/Email/EmailSenderTest.php index 5044a7c7a..bd73022a1 100644 --- a/tests/TestCase/Email/EmailSenderTest.php +++ b/tests/TestCase/Email/EmailSenderTest.php @@ -49,7 +49,7 @@ public function setUp() $this->fullBaseBackup = Router::fullBaseUrl(); Router::fullBaseUrl('http://users.test'); - Email::configTransport('test', [ + Email::setConfigTransport('test', [ 'className' => 'Debug' ]); } diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 9b1e18606..ebf59d69a 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -39,12 +39,12 @@ public function setUp() { parent::setUp(); $this->Email = $this->getMockBuilder('Cake\Mailer\Email') - ->setMethods(['to', 'subject', 'viewVars', 'template']) + ->setMethods(['to', 'setSubject', 'setViewVars', 'setTemplate']) ->getMock(); $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') ->setConstructorArgs([$this->Email]) - ->setMethods(['to', 'subject', 'viewVars', 'template']) + ->setMethods(['to', 'setSubject', 'setViewVars', 'setTemplate']) ->getMock(); } @@ -80,17 +80,17 @@ public function testValidation() ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('subject') + ->method('setSubject') ->with('FirstName, Validate your Account') ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('viewVars') + ->method('setViewVars') ->with($data) ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('template') + ->method('setTemplate') ->with('CakeDC/Users.validation') ->will($this->returnValue($this->Email)); @@ -117,17 +117,17 @@ public function testValidationWithTemplate() ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('subject') + ->method('setSubject') ->with('FirstName, Validate your Account') ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('viewVars') + ->method('setViewVars') ->with($data) ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('template') + ->method('setTemplate') ->with('myTemplate') ->will($this->returnValue($this->Email)); @@ -150,12 +150,12 @@ public function testSocialAccountValidation() ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('subject') + ->method('setSubject') ->with('first1, Your social account validation link') ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('viewVars') + ->method('setViewVars') ->with(['user' => $social->user, 'socialAccount' => $social]) ->will($this->returnValue($this->Email)); @@ -182,17 +182,17 @@ public function testResetPassword() ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('subject') + ->method('setSubject') ->with('FirstName, Your reset password link') ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('viewVars') + ->method('setViewVars') ->with($data) ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) - ->method('template') + ->method('setTemplate') ->with('myTemplate') ->will($this->returnValue($this->Email)); diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index e6d3657b3..73255e507 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -44,7 +44,7 @@ public function setUp() $table->addBehavior('CakeDC/Users/Register.Register'); $this->Table = $table; $this->Behavior = $table->behaviors()->Register; - Email::configTransport('test', [ + Email::setConfigTransport('test', [ 'className' => 'Debug' ]); $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index b7f4459f3..50f9cf851 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -49,11 +49,11 @@ public function setUp() $this->Users = TableRegistry::get('CakeDC/Users.Users'); $this->fullBaseBackup = Router::fullBaseUrl(); Router::fullBaseUrl('http://users.test'); - Email::configTransport('test', [ + Email::setConfigTransport('test', [ 'className' => 'Debug' ]); - $this->configEmail = Email::config('default'); - Email::config('default', [ + //$this->configEmail = Email::getConfig('default'); + Email::setConfig('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' ]); @@ -72,7 +72,7 @@ public function tearDown() Router::fullBaseUrl($this->fullBaseBackup); Email::drop('default'); Email::dropTransport('test'); - Email::config('default', $this->configEmail); + //Email::setConfig('default', $this->configEmail); parent::tearDown(); } diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 1159fe3aa..346417015 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -278,7 +278,7 @@ public function testResetAllPasswords() public function testResetAllPasswordsNoPassingParams() { $this->Shell->expects($this->once()) - ->method('error') + ->method('setError') ->with('Please enter a password.'); $this->Shell->runCommand(['resetAllPasswords']); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 4ec62c563..0b23a7fde 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -72,7 +72,7 @@ ], ]; -Cake\Cache\Cache::config($cache); +Cake\Cache\Cache::setConfig($cache); Cake\Core\Configure::write('Session', [ 'defaults' => 'php' ]); @@ -98,7 +98,7 @@ class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\Ap putenv('db_dsn=sqlite:///:memory:'); } -Cake\Datasource\ConnectionManager::config('test', [ +Cake\Datasource\ConnectionManager::setConfig('test', [ 'url' => getenv('db_dsn'), 'timezone' => 'UTC' ]); From 1981949e10437ca82747346fbd96579aea6bbb7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 13 Mar 2017 15:43:00 +0000 Subject: [PATCH 0593/1476] refs #core34 fix unit tests for 3.4 --- config/permissions.php | 6 +- config/routes.php | 22 +- config/users.php | 56 ++--- src/Controller/Traits/LoginTrait.php | 5 +- src/Email/EmailSender.php | 1 + .../Controller/Traits/LoginTraitTest.php | 89 +++++++- .../Controller/Traits/RegisterTraitTest.php | 198 +++++++++--------- .../Controller/Traits/SimpleCrudTraitTest.php | 85 +++++--- tests/TestCase/Shell/UsersShellTest.php | 2 +- 9 files changed, 290 insertions(+), 174 deletions(-) diff --git a/config/permissions.php b/config/permissions.php index a0525fa5b..17229a6d7 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -68,8 +68,8 @@ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetGoogleAuthenticator', - 'allowed' => function (array $user, $role, \Cake\Network\Request $request) { - $userId = \Cake\Utility\Hash::get($request->params, 'pass.0'); + 'allowed' => function (array $user, $role, \Cake\Http\ServerRequest $request) { + $userId = \Cake\Utility\Hash::get($request->getAttribute('params'), 'pass.0'); if (!empty($userId) && !empty($user)) { return $userId === $user['id']; } @@ -90,4 +90,4 @@ 'action' => ['other', 'display'], 'allowed' => true, ], - ]]; + ]]; diff --git a/config/routes.php b/config/routes.php index 4968e02fc..e4e370b5e 100644 --- a/config/routes.php +++ b/config/routes.php @@ -12,20 +12,20 @@ use Cake\Routing\Router; Router::plugin('CakeDC/Users', ['path' => '/users'], function ($routes) { - $routes->fallbacks('DashedRoute'); - }); + $routes->fallbacks('DashedRoute'); +}); Router::connect('/auth/twitter', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'twitterLogin', - 'provider' => 'twitter' - ]); + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'twitterLogin', + 'provider' => 'twitter' +]); Router::connect('/accounts/validate/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'validate' - ]); + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validate' +]); // Google Authenticator related routes if (Configure::read('Users.GoogleAuthenticator.login')) { Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); diff --git a/config/users.php b/config/users.php index b5e95a17f..b3993f291 100644 --- a/config/users.php +++ b/config/users.php @@ -14,52 +14,52 @@ $config = [ 'Users' => [ - //Table used to manage users + // Table used to manage users 'table' => 'CakeDC/Users.Users', - //Controller used to manage users + // Controller used to manage users plugin features & actions 'controller' => 'CakeDC/Users.Users', - //configure Auth component + // configure Auth component 'auth' => true, - //Password Hasher + // Password Hasher 'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher', - //token expiration, 1 hour + // token expiration, 1 hour 'Token' => ['expiration' => 3600], 'Email' => [ - //determines if the user should include email + // determines if the user should include email 'required' => true, - //determines if registration workflow includes email validation + // determines if registration workflow includes email validation 'validate' => true, ], 'Registration' => [ - //determines if the register is enabled + // determines if the register is enabled 'active' => true, - //determines if the reCaptcha is enabled for registration + // determines if the reCaptcha is enabled for registration 'reCaptcha' => true, - //allow a logged in user to access the registration form + // allow a logged in user to access the registration form 'allowLoggedIn' => false, - //ensure user is active (confirmed email) to reset his password + // ensure user is active (confirmed email) to reset his password 'ensureActive' => false ], 'reCaptcha' => [ - //reCaptcha key goes here + // reCaptcha key goes here 'key' => null, - //reCaptcha secret + // reCaptcha secret 'secret' => null, - //use reCaptcha in registration + // use reCaptcha in registration 'registration' => false, - //use reCaptcha in login, valid values are false, true + // use reCaptcha in login, valid values are false, true 'login' => false, ], 'Tos' => [ - //determines if the user should include tos accepted + // determines if the user should include tos accepted 'required' => true, ], 'Social' => [ - //enable social login + // enable social login 'login' => false, ], 'GoogleAuthenticator' => [ - //enable Google Authenticator + // enable Google Authenticator 'login' => false, 'issuer' => null, // The number of digits the resulting codes will be @@ -74,34 +74,34 @@ 'rngprovider' => null ], 'Profile' => [ - //Allow view other users profiles + // Allow view other users profiles 'viewOthers' => true, 'route' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], ], 'Key' => [ 'Session' => [ - //session key to store the social auth data + // session key to store the social auth data 'social' => 'Users.social', - //userId key used in reset password workflow + // userId key used in reset password workflow 'resetPasswordUserId' => 'Users.resetPasswordUserId', ], - //form key to store the social auth data + // form key to store the social auth data 'Form' => [ 'social' => 'social' ], 'Data' => [ - //data key to store the users email + // data key to store the users email 'email' => 'email', - //data key to store email coming from social networks + // data key to store email coming from social networks 'socialEmail' => 'info.email', - //data key to check if the remember me option is enabled + // data key to check if the remember me option is enabled 'rememberMe' => 'remember_me', ], ], - //Avatar placeholder + // Avatar placeholder 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], 'RememberMe' => [ - //configure Remember Me component + // configure Remember Me component 'active' => true, 'Cookie' => [ 'name' => 'remember_me', @@ -120,7 +120,7 @@ 'prefix' => false, ], ], - //default configuration used to auto-load the Auth Component, override to change the way Auth works + // default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ 'loginAction' => [ 'plugin' => 'CakeDC/Users', diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index a51cd66e3..488eeec15 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use Cake\Utility\Hash; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -211,7 +212,7 @@ public function verify() $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); - $this->redirect(Configure::read('Auth.loginAction')); + return $this->redirect(Configure::read('Auth.loginAction')); } // storing user's session in the temporary one @@ -250,7 +251,7 @@ public function verify() } } $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( - $temporarySession['email'], + Hash::get($temporarySession, 'email'), $secret ); $this->set(compact('secretDataUri')); diff --git a/src/Email/EmailSender.php b/src/Email/EmailSender.php index 7d24a3add..be79d0ba5 100644 --- a/src/Email/EmailSender.php +++ b/src/Email/EmailSender.php @@ -77,6 +77,7 @@ public function sendSocialValidationEmail(EntityInterface $socialAccount, Entity } else { $template = $email->getTemplate(); } + return $this ->getMailer( 'CakeDC/Users.Users', diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 11ab5483e..528d60762 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Http\ServerRequest; +use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Exception\AccountNotActiveException; @@ -39,7 +40,7 @@ public function setUp() parent::setUp(); $request = new ServerRequest(); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') - ->setMethods(['dispatchEvent', 'redirect']) + ->setMethods(['dispatchEvent', 'redirect', 'set']) ->getMockForTrait(); $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') @@ -390,4 +391,90 @@ public function testFailedSocialUserAccount() $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' => 1, + '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(); + } } diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 54e8b6659..39b879817 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -53,8 +53,8 @@ public function testValidateEmail() { $token = 'token'; $this->Trait->expects($this->once()) - ->method('validate') - ->with('email', $token); + ->method('validate') + ->with('email', $token); $this->Trait->validateEmail($token); } @@ -71,18 +71,20 @@ public function testRegister() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); + ->method('success') + ->with('Please validate your account before log in'); $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ]; + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); $this->Trait->register(); @@ -103,26 +105,28 @@ public function testRegisterReCaptcha() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); + ->method('success') + ->with('Please validate your account before log in'); $this->Trait->expects($this->once()) - ->method('validateRecaptcha') - ->will($this->returnValue(true)); + ->method('validateRecaptcha') + ->will($this->returnValue(true)); $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ]; + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); $this->Trait->register(); $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - Configure::write('Users.reCaptcha.registration', false); } /** @@ -139,25 +143,27 @@ public function testRegisterValidationErrors() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The user could not be saved'); + ->method('error') + ->with('The user could not be saved'); $this->Trait->expects($this->once()) - ->method('validateRecaptcha') - ->will($this->returnValue(true)); + ->method('validateRecaptcha') + ->will($this->returnValue(true)); $this->Trait->expects($this->never()) - ->method('redirect'); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'not-matching', - 'tos' => 1 - ]; + ->method('redirect'); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'not-matching', + 'tos' => 1 + ])); $this->Trait->register(); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - Configure::write('Users.reCaptcha.registration', false); } /** @@ -174,23 +180,25 @@ public function testRegisterRecaptchaNotValid() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Invalid reCaptcha'); + ->method('error') + ->with('Invalid reCaptcha'); $this->Trait->expects($this->once()) - ->method('validateRecaptcha') - ->will($this->returnValue(false)); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ]; + ->method('validateRecaptcha') + ->will($this->returnValue(false)); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); $this->Trait->register(); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - Configure::write('Users.reCaptcha.registration', false); } /** @@ -206,11 +214,11 @@ public function testRegisterGet() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->never()) - ->method('success'); + ->method('success'); $this->Trait->expects($this->never()) - ->method('validateRecaptcha'); + ->method('validateRecaptcha'); $this->Trait->expects($this->never()) - ->method('redirect'); + ->method('redirect'); $this->Trait->register(); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); @@ -223,7 +231,6 @@ public function testRegisterGet() */ public function testRegisterRecaptchaDisabled() { - $recaptcha = Configure::read('Users.Registration.reCaptcha'); Configure::write('Users.Registration.reCaptcha', false); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); @@ -231,25 +238,27 @@ public function testRegisterRecaptchaDisabled() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); + ->method('success') + ->with('Please validate your account before log in'); $this->Trait->expects($this->never()) - ->method('validateRecaptcha'); + ->method('validateRecaptcha'); $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ]; + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); $this->Trait->register(); $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - Configure::write('Users.Registration.reCaptcha', $recaptcha); } /** @@ -260,14 +269,12 @@ public function testRegisterRecaptchaDisabled() */ public function testRegisterNotEnabled() { - $active = Configure::read('Users.Registration.active'); Configure::write('Users.Registration.active', false); $this->_mockRequestPost(); $this->_mockAuth(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->register(); - Configure::write('Users.Registration.active', $active); } /** @@ -277,7 +284,6 @@ public function testRegisterNotEnabled() */ public function testRegisterLoggedInUserAllowed() { - $allowLoggedIn = Configure::read('Users.Registration.allowLoggedIn'); Configure::write('Users.Registration.allowLoggedIn', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); @@ -285,23 +291,25 @@ public function testRegisterLoggedInUserAllowed() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); + ->method('success') + ->with('Please validate your account before log in'); $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ]; + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); $this->Trait->register(); $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - Configure::write('Users.Registration.allowLoggedIn', $allowLoggedIn); } /** @@ -311,7 +319,6 @@ public function testRegisterLoggedInUserAllowed() */ public function testRegisterLoggedInUserNotAllowed() { - $allowLoggedIn = Configure::read('Users.Registration.allowLoggedIn'); Configure::write('Users.Registration.allowLoggedIn', false); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); @@ -319,22 +326,15 @@ public function testRegisterLoggedInUserNotAllowed() $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('You must log out to register a new user account'); + ->method('error') + ->with('You must log out to register a new user account'); $this->Trait->expects($this->once()) - ->method('redirect') - ->with(Configure::read('Users.Profile.route')); - $this->Trait->request->data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ]; + ->method('redirect') + ->with(Configure::read('Users.Profile.route')); + $this->Trait->request->expects($this->never()) + ->method('getData') + ->with(); $this->Trait->register(); - - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - Configure::write('Users.Registration.allowLoggedIn', $allowLoggedIn); } } diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 2e807ebda..e3e2dfcab 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -30,13 +30,13 @@ public function setUp() parent::setUp(); $viewVarsContainer = $this; $this->Trait->expects($this->any()) - ->method('set') - ->will($this->returnCallback(function ($param1, $param2 = null) use ($viewVarsContainer) { - $viewVarsContainer->viewVars[$param1] = $param2; - })); + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) use ($viewVarsContainer) { + $viewVarsContainer->viewVars[$param1] = $param2; + })); $this->Trait->expects($this->once()) - ->method('loadModel') - ->will($this->returnValue($this->table)); + ->method('loadModel') + ->will($this->returnValue($this->table)); } /** @@ -58,9 +58,9 @@ public function tearDown() public function testIndex() { $this->Trait->expects($this->once()) - ->method('paginate') - ->with($this->table) - ->will($this->returnValue([])); + ->method('paginate') + ->with($this->table) + ->will($this->returnValue([])); $this->Trait->index(); $expected = [ 'Users' => [], @@ -145,14 +145,20 @@ public function testAddPostHappy() $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); $this->_mockRequestPost(); $this->_mockFlash(); - $this->Trait->request->data = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ]; - + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ])); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('The User has been saved'); @@ -172,12 +178,19 @@ public function testAddPostErrors() $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); $this->_mockRequestPost(); $this->_mockFlash(); - $this->Trait->request->data = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'first_name' => 'test', - 'last_name' => 'user', - ]; + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'first_name' => 'test', + 'last_name' => 'user', + ])); $this->Trait->Flash->expects($this->once()) ->method('error') @@ -198,9 +211,16 @@ public function testEditPostHappy() $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); $this->_mockRequestPost(['patch', 'post', 'put']); $this->_mockFlash(); - $this->Trait->request->data = [ - 'email' => 'newtestuser@test.com', - ]; + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with(['patch', 'post', 'put']) + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'email' => 'newtestuser@test.com', + ])); $this->Trait->Flash->expects($this->once()) ->method('success') @@ -221,9 +241,16 @@ public function testEditPostErrors() $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); $this->_mockRequestPost(['patch', 'post', 'put']); $this->_mockFlash(); - $this->Trait->request->data = [ - 'email' => 'not-an-email', - ]; + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with(['patch', 'post', 'put']) + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'email' => 'not-an-email', + ])); $this->Trait->Flash->expects($this->once()) ->method('error') diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 346417015..f09b95502 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -43,7 +43,7 @@ public function setUp() $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', - '_generateRandomUsername', '_generatedHashedPassword', 'error', '_updateUser']) + '_generateRandomUsername', '_generatedHashedPassword', 'setError', '_updateUser']) ->setConstructorArgs([$this->io]) ->getMock(); From 14e40934e7420d58b614e0add22d4edbee12315c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 13 Mar 2017 15:46:56 +0000 Subject: [PATCH 0594/1476] refs #core34 refactor to Form::control --- Docs/Documentation/Configuration.md | 30 +++++++++---------- src/Template/Users/add.ctp | 12 ++++---- src/Template/Users/change_password.ctp | 6 ++-- src/Template/Users/edit.ctp | 20 ++++++------- src/Template/Users/login.ctp | 6 ++-- src/Template/Users/register.ctp | 14 ++++----- src/Template/Users/request_reset_password.ctp | 2 +- .../Users/resend_token_validation.ctp | 2 +- src/Template/Users/social_email.ctp | 2 +- src/Template/Users/verify.ctp | 2 +- 10 files changed, 48 insertions(+), 48 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 1f05b7262..640602293 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -69,40 +69,40 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use ``` 'Users' => [ - //Table used to manage users + // Table used to manage users 'table' => 'CakeDC/Users.Users', - //configure Auth component + // configure Auth component 'auth' => true, 'Email' => [ - //determines if the user should include email + // determines if the user should include email 'required' => true, - //determines if registration workflow includes email validation + // determines if registration workflow includes email validation 'validate' => true, ], 'Registration' => [ - //determines if the register is enabled + // determines if the register is enabled 'active' => true, - //determines if the reCaptcha is enabled for registration + // determines if the reCaptcha is enabled for registration 'reCaptcha' => true, - //ensure user is active (confirmed email) to reset his password + // ensure user is active (confirmed email) to reset his password 'ensureActive' => false ], 'Tos' => [ - //determines if the user should include tos accepted + // determines if the user should include tos accepted 'required' => true, ], 'Social' => [ - //enable social login + // enable social login 'login' => false, ], - //Avatar placeholder + // Avatar placeholder 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], 'RememberMe' => [ - //configure Remember Me component + // configure Remember Me component 'active' => true, ], ], -//default configuration used to auto-load the Auth Component, override to change the way Auth works +// default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ 'authenticate' => [ 'all' => [ @@ -141,12 +141,12 @@ You need to configure 2 things: Configure::write('Auth.authenticate.Form.fields.username', 'email'); ``` -* Override the login.ctp template to change the Form->input 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.ctp template to change the Form->control to "email". Add (or copy from the https://github.com/CakeDC/users/blob/master/src/Template/Users/login.ctp) the file login.ctp to path /src/Template/Plugin/CakeDC/Users/Users/login.ctp and ensure it has the following content ```php // ... inside the Form - Form->input('email', ['required' => true]) ?> - Form->input('password', ['required' => true]) ?> + Form->control('email', ['required' => true]) ?> + Form->control('password', ['required' => true]) ?> // ... rest of your login.ctp code ``` diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp index 6e4e213ce..23a14fe26 100644 --- a/src/Template/Users/add.ctp +++ b/src/Template/Users/add.ctp @@ -20,12 +20,12 @@
    Form->input('username', ['label' => __d('CakeDC/Users', 'Username')]); - echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); - echo $this->Form->input('password', ['label' => __d('CakeDC/Users', 'Password')]); - echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); - echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - echo $this->Form->input('active', [ + echo $this->Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('CakeDC/Users', 'Password')]); + echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->control('active', [ 'type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Active') ]); diff --git a/src/Template/Users/change_password.ctp b/src/Template/Users/change_password.ctp index 4c6f5bec0..339f2fc65 100644 --- a/src/Template/Users/change_password.ctp +++ b/src/Template/Users/change_password.ctp @@ -4,18 +4,18 @@
    - Form->input('current_password', [ + Form->control('current_password', [ 'type' => 'password', 'required' => true, 'label' => __d('CakeDC/Users', 'Current password')]); ?> - Form->input('password', [ + Form->control('password', [ 'type' => 'password', 'required' => true, 'label' => __d('CakeDC/Users', 'New password')]); ?> - Form->input('password_confirm', [ + Form->control('password_confirm', [ 'type' => 'password', 'required' => true, 'label' => __d('CakeDC/Users', 'Confirm password')]); diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index 7c482a959..fb99776fa 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -32,24 +32,24 @@ $Users = ${$tableAlias};
    Form->input('username', ['label' => __d('CakeDC/Users', 'Username')]); - echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); - echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); - echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - echo $this->Form->input('token', ['label' => __d('CakeDC/Users', 'Token')]); - echo $this->Form->input('token_expires', [ + echo $this->Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->control('token', ['label' => __d('CakeDC/Users', 'Token')]); + echo $this->Form->control('token_expires', [ 'label' => __d('CakeDC/Users', 'Token expires') ]); - echo $this->Form->input('api_token', [ + echo $this->Form->control('api_token', [ 'label' => __d('CakeDC/Users', 'API token') ]); - echo $this->Form->input('activation_date', [ + echo $this->Form->control('activation_date', [ 'label' => __d('CakeDC/Users', 'Activation date') ]); - echo $this->Form->input('tos_date', [ + echo $this->Form->control('tos_date', [ 'label' => __d('CakeDC/Users', 'TOS date') ]); - echo $this->Form->input('active', [ + echo $this->Form->control('active', [ 'label' => __d('CakeDC/Users', 'Active') ]); ?> diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index b6ce0a0c0..1f4123f59 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -17,14 +17,14 @@ use Cake\Core\Configure; Form->create() ?>
    - Form->input('username', ['required' => true]) ?> - Form->input('password', ['required' => true]) ?> + Form->control('username', ['required' => true]) ?> + Form->control('password', ['required' => true]) ?> User->addReCaptcha(); } if (Configure::read('Users.RememberMe.active')) { - echo $this->Form->input(Configure::read('Users.Key.Data.rememberMe'), [ + echo $this->Form->control(Configure::read('Users.Key.Data.rememberMe'), [ 'type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Remember me'), 'checked' => 'checked' diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index bd4a0588a..a87dfc86f 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -16,17 +16,17 @@ use Cake\Core\Configure;
    Form->input('username', ['label' => __d('CakeDC/Users', 'Username')]); - echo $this->Form->input('email', ['label' => __d('CakeDC/Users', 'Email')]); - echo $this->Form->input('password', ['label' => __d('CakeDC/Users', 'Password')]); - echo $this->Form->input('password_confirm', [ + echo $this->Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('CakeDC/Users', 'Password')]); + echo $this->Form->control('password_confirm', [ 'type' => 'password', 'label' => __d('CakeDC/Users', 'Confirm password') ]); - echo $this->Form->input('first_name', ['label' => __d('CakeDC/Users', 'First name')]); - echo $this->Form->input('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); if (Configure::read('Users.Tos.required')) { - echo $this->Form->input('tos', ['type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Accept TOS conditions?'), 'required' => true]); + echo $this->Form->control('tos', ['type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Accept TOS conditions?'), 'required' => true]); } if (Configure::read('Users.reCaptcha.registration')) { echo $this->User->addReCaptcha(); diff --git a/src/Template/Users/request_reset_password.ctp b/src/Template/Users/request_reset_password.ctp index 462e29bc6..e406ff573 100644 --- a/src/Template/Users/request_reset_password.ctp +++ b/src/Template/Users/request_reset_password.ctp @@ -3,7 +3,7 @@ Form->create('User') ?>
    - Form->input('reference') ?> + Form->control('reference') ?>
    Form->button(__d('CakeDC/Users', 'Submit')); ?> Form->end() ?> diff --git a/src/Template/Users/resend_token_validation.ctp b/src/Template/Users/resend_token_validation.ctp index 90b8aa9d7..87dff835d 100644 --- a/src/Template/Users/resend_token_validation.ctp +++ b/src/Template/Users/resend_token_validation.ctp @@ -14,7 +14,7 @@
    Form->input('reference', ['label' => __d('CakeDC/Users', 'Email or username')]); + echo $this->Form->control('reference', ['label' => __d('CakeDC/Users', 'Email or username')]); ?>
    Form->button(__d('CakeDC/Users', 'Submit')) ?> diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp index 7fb86c250..1cad21655 100644 --- a/src/Template/Users/social_email.ctp +++ b/src/Template/Users/social_email.ctp @@ -14,7 +14,7 @@ Form->create('User') ?>
    - Form->input('email') ?> + Form->control('email') ?>
    Form->button(__d('CakeDC/Users', 'Submit')); ?> Form->end() ?> diff --git a/src/Template/Users/verify.ctp b/src/Template/Users/verify.ctp index 450480906..f1f7d2524 100644 --- a/src/Template/Users/verify.ctp +++ b/src/Template/Users/verify.ctp @@ -10,7 +10,7 @@

    - Form->input('code', ['required' => true, 'label' => __d('CakeDC/Users', 'Verification Code')]) ?> + Form->control('code', ['required' => true, 'label' => __d('CakeDC/Users', 'Verification Code')]) ?>
    Form->button(__d('CakeDC/Users', ' Verify'), ['class' => 'btn btn-primary']); ?> Form->end() ?> From cca2f739b0a8aabeadd08b64e0cbd941c10e34e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 13 Mar 2017 15:55:00 +0000 Subject: [PATCH 0595/1476] refs #core34 fix controller docs --- Docs/Documentation/Configuration.md | 2 ++ Docs/Documentation/Extending-the-Plugin.md | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 640602293..897af3381 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -71,6 +71,8 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'Users' => [ // Table used to manage users 'table' => 'CakeDC/Users.Users', + // Controller used to manage users plugin features & actions + 'controller' => 'CakeDC/Users.Users', // configure Auth component 'auth' => true, 'Email' => [ diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index fcaf6a626..6a05b9014 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -83,6 +83,8 @@ Extending the Controller You want to use one of your controllers to handle all the users features in your app, and keep the login/register/etc actions from Users Plugin, +First create a new controller class: + ```php [ + // ... + // Controller used to manage users plugin features & actions + 'controller' => 'MyUsers', + // ... +``` + Note you'll need to **copy the Plugin templates** you need into your project src/Template/MyUsers/[action].ctp Extending the Features in your controller From 10b953e78f6bf58a2eecf07bf938a2642bf21836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 14 Mar 2017 12:27:23 +0000 Subject: [PATCH 0596/1476] refs #core34 add CakeDC/Auth and fix config/docblocks --- .semver | 6 +- CHANGELOG.md | 4 + CONTRIBUTING.md | 2 +- Docs/Documentation/ApiKeyAuthenticate.md | 37 - Docs/Documentation/Configuration.md | 13 +- Docs/Documentation/Migration/4.1.x-5.0.md | 30 + Docs/Documentation/OwnerRule.md | 86 -- Docs/Documentation/SimpleRbacAuthorize.md | 141 -- Docs/Documentation/SuperuserAuthorize.md | 18 - Docs/Home.md | 18 +- README.md | 10 +- composer.json | 3 +- config/Migrations/20150513201111_initial.php | 4 +- .../20161031101316_AddSecretToUsers.php | 10 + config/bootstrap.php | 4 +- config/permissions.php | 4 +- config/routes.php | 4 +- config/users.php | 12 +- src/Auth/ApiKeyAuthenticate.php | 4 +- .../Exception/InvalidProviderException.php | 10 + .../Exception/InvalidSettingsException.php | 10 + .../MissingEventListenerException.php | 10 + .../MissingProviderConfigurationException.php | 10 + src/Auth/RememberMeAuthenticate.php | 4 +- src/Auth/Rules/AbstractRule.php | 4 +- src/Auth/Rules/Owner.php | 4 +- src/Auth/Rules/Rule.php | 4 +- src/Auth/SimpleRbacAuthorize.php | 4 +- src/Auth/Social/Mapper/AbstractMapper.php | 4 +- src/Auth/Social/Mapper/Facebook.php | 4 +- src/Auth/Social/Mapper/Google.php | 4 +- src/Auth/Social/Mapper/Instagram.php | 4 +- src/Auth/Social/Mapper/LinkedIn.php | 4 +- src/Auth/Social/Mapper/Twitter.php | 4 +- src/Auth/Social/Util/SocialUtils.php | 4 +- src/Auth/SocialAuthenticate.php | 4 +- src/Auth/SuperuserAuthorize.php | 4 +- src/Controller/AppController.php | 4 +- .../GoogleAuthenticatorComponent.php | 10 + .../Component/RememberMeComponent.php | 4 +- .../Component/UsersAuthComponent.php | 4 +- src/Controller/SocialAccountsController.php | 4 +- .../Traits/CustomUsersTableTrait.php | 4 +- src/Controller/Traits/LoginTrait.php | 4 +- .../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/Email/EmailSender.php | 4 +- .../AccountAlreadyActiveException.php | 4 +- src/Exception/AccountNotActiveException.php | 4 +- src/Exception/BadConfigurationException.php | 4 +- src/Exception/MissingEmailException.php | 4 +- src/Exception/MissingProviderException.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 | 9 + src/Mailer/UsersMailer.php | 4 +- src/Model/Behavior/Behavior.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/Shell/UsersShell.php | 4 +- src/Template/Email/html/reset_password.ctp | 4 +- .../Email/html/social_account_validation.ctp | 4 +- src/Template/Email/html/validation.ctp | 4 +- src/Template/Email/text/reset_password.ctp | 4 +- .../Email/text/social_account_validation.ctp | 4 +- src/Template/Email/text/validation.ctp | 4 +- src/Template/Layout/Email/html/default.ctp | 10 +- src/Template/Layout/Email/text/default.ctp | 10 +- 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 +- .../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/AuthLinkHelper.php | 10 + src/View/Helper/UserHelper.php | 4 +- tests/App/Controller/AppController.php | 10 + tests/Fixture/PostsFixture.php | 4 +- tests/Fixture/PostsUsersFixture.php | 4 +- tests/Fixture/SocialAccountsFixture.php | 10 + tests/Fixture/UsersFixture.php | 4 +- .../TestCase/Auth/ApiKeyAuthenticateTest.php | 240 ---- .../Auth/RememberMeAuthenticateTest.php | 172 --- tests/TestCase/Auth/Rules/OwnerTest.php | 254 ---- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 1203 ----------------- .../TestCase/Auth/SocialAuthenticateTest.php | 4 +- .../TestCase/Auth/SuperuserAuthorizeTest.php | 93 -- .../GoogleAuthenticatorComponentTest.php | 10 + .../Component/RememberMeComponentTest.php | 4 +- .../Component/UsersAuthComponentTest.php | 4 +- .../SocialAccountsControllerTest.php | 4 +- .../Controller/Traits/BaseTraitTest.php | 4 +- .../Traits/CustomUsersTableTraitTest.php | 4 +- .../Controller/Traits/LoginTraitTest.php | 4 +- .../Traits/PasswordManagementTraitTest.php | 4 +- .../Controller/Traits/ProfileTraitTest.php | 4 +- .../Controller/Traits/RecaptchaTraitTest.php | 4 +- .../Controller/Traits/RegisterTraitTest.php | 4 +- .../Controller/Traits/SimpleCrudTraitTest.php | 4 +- .../Controller/Traits/SocialTraitTest.php | 4 +- .../Traits/UserValidationTraitTest.php | 4 +- tests/TestCase/Email/EmailSenderTest.php | 4 +- tests/TestCase/Mailer/UsersMailerTest.php | 4 +- .../Model/Behavior/PasswordBehaviorTest.php | 4 +- .../Model/Behavior/RegisterBehaviorTest.php | 4 +- .../Behavior/SocialAccountBehaviorTest.php | 4 +- .../Model/Behavior/SocialBehaviorTest.php | 4 +- tests/TestCase/Model/Entity/UserTest.php | 10 + .../Model/Table/SocialAccountsTableTest.php | 4 +- tests/TestCase/Model/Table/UsersTableTest.php | 4 +- tests/TestCase/Shell/UsersShellTest.php | 4 +- .../TestCase/Traits/RandomStringTraitTest.php | 4 +- .../View/Helper/AuthLinkHelperTest.php | 10 + tests/TestCase/View/Helper/UserHelperTest.php | 4 +- tests/bootstrap.php | 10 + tests/config/routes.php | 4 +- 134 files changed, 413 insertions(+), 2488 deletions(-) delete mode 100644 Docs/Documentation/ApiKeyAuthenticate.md create mode 100644 Docs/Documentation/Migration/4.1.x-5.0.md delete mode 100644 Docs/Documentation/OwnerRule.md delete mode 100644 Docs/Documentation/SimpleRbacAuthorize.md delete mode 100644 Docs/Documentation/SuperuserAuthorize.md delete mode 100644 tests/TestCase/Auth/ApiKeyAuthenticateTest.php delete mode 100644 tests/TestCase/Auth/RememberMeAuthenticateTest.php delete mode 100644 tests/TestCase/Auth/Rules/OwnerTest.php delete mode 100644 tests/TestCase/Auth/SimpleRbacAuthorizeTest.php delete mode 100644 tests/TestCase/Auth/SuperuserAuthorizeTest.php diff --git a/.semver b/.semver index 0dd3d3dd5..d6dac21e0 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- -:major: 4 -:minor: 1 -:patch: 2 +:major: 5 +:minor: 0 +:patch: 0 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b541f59c..d68029b82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Changelog Releases for CakePHP 3 ------------- +* 5.0.0 + * Some Auth objects refactored into https://github.com/CakeDC/auth + * Upgrade to CakePHP 3.4 + * 4.1.2 * Fix RememberMe redirect * Fix AuthLink rendering inside Cells diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 26f53081b..653b64f7c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ Contributing ============ -This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/contribution-guidelines) for detailed instructions. +This repository follows the [CakeDC Plugin Standard](https://www.cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](https://www.cakedc.com/contribution-guidelines) for detailed instructions. diff --git a/Docs/Documentation/ApiKeyAuthenticate.md b/Docs/Documentation/ApiKeyAuthenticate.md deleted file mode 100644 index 80f331c4c..000000000 --- a/Docs/Documentation/ApiKeyAuthenticate.md +++ /dev/null @@ -1,37 +0,0 @@ -ApiKeyAuthenticate -============= - -Setup ---------------- - -ApiKeyAuthenticate default configuration is -```php - protected $_defaultConfig = [ - //type, can be either querystring or header - 'type' => self::TYPE_QUERYSTRING, - //name to retrieve the api key value from - 'name' => 'api_key', - //db field where the key is stored - 'field' => 'api_token', - //require SSL to pass the token. You should always require SSL to use tokens for Auth - 'require_ssl' => true, - ]; -``` - -We are using query strings for passing the api_key token. And we require SSL by default. -Note you can override these options using - -```php -$config['Auth']['authenticate']['CakeDC/Users.ApiKey'] = [ - 'type' => 'header', - ]; -``` - -In order to allow stateless authentication, enable these configuration: - -```php - $this->Auth->config('storage', 'Memory'); - $this->Auth->config('unauthorizedRedirect', 'false'); - $this->Auth->config('checkAuthIn', 'Controller.initialize'); - $this->Auth->config('loginAction', false); -``` \ No newline at end of file diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 897af3381..6293d166a 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -114,8 +114,8 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'Form', ], 'authorize' => [ - 'CakeDC/Users.Superuser', - 'CakeDC/Users.SimpleRbac', + 'CakeDC/Auth.Superuser', + 'CakeDC/Auth.SimpleRbac', ], ], ]; @@ -128,11 +128,12 @@ Default Authenticate and Authorize Objects used Using the UsersAuthComponent default initialization, the component will load the following objects into AuthComponent: * Authenticate * 'Form' - * 'Social' check [SocialAuthenticate](SocialAuthenticate.md) for configuration options - * 'RememberMe' check [SocialAuthenticate](RememberMeAuthenticate.md) for configuration options + * '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 * Authorize - * 'Users.Superuser' check [SuperuserAuthorize](SuperuserAuthorize.md) for configuration options - * 'Users.SimpleRbac' check [SimpleRbacAuthorize](SimpleRbacAuthorize.md) for configuration options + * '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 + * 'CakeDC/Auth.ApiKey' check [ApiKeyAuthenticate](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/ApiKeyAuthenticate.md) for configuration options ## Using the user's email to login diff --git a/Docs/Documentation/Migration/4.1.x-5.0.md b/Docs/Documentation/Migration/4.1.x-5.0.md new file mode 100644 index 000000000..091141f1a --- /dev/null +++ b/Docs/Documentation/Migration/4.1.x-5.0.md @@ -0,0 +1,30 @@ +Migration 4.1.x to 5.0 +====================== + +5.0 is compatible with CakePHP ^3.4 and refactored some Auth objects into a new plugin +* Fix your Users configuration file for Auth object references + +in `users.php` + +```php +$config = [ + // ... + 'Auth' => [ + // ... + + // ... +``` + +* Add a new configuration key to specify the controller name you are using to handle auth in your project + +in `users.php` + +```php +$config = [ + 'Users' => [ + // ... + // Controller used to manage users plugin features & actions + 'controller' => 'CakeDC/Users.Users', + // ... +``` + diff --git a/Docs/Documentation/OwnerRule.md b/Docs/Documentation/OwnerRule.md deleted file mode 100644 index db98eb455..000000000 --- a/Docs/Documentation/OwnerRule.md +++ /dev/null @@ -1,86 +0,0 @@ -Owner Rule -============= - -Setup ---------------- - -SimpleRbacAuthorize will pick and use specific Rule classes (implementing the \CakeDC\Users\Auth\Rules\Rule interface). -You only need to create your own permission rules, implement the required interface and pass the instance in the -'allowed' param. - -We provide an AbstractRule you could extend too, in case you want to use rules accessing the database and using the -default table associated to the current controller. - -Owner rule configuration ------------------ - -The Owner rule can be configured to use the following options -```php - //field in the owned table matching the user_id - 'ownerForeignKey' => 'user_id', - /* - * request key type to retrieve the table id, could be "params", "query", "data" to locate the table id - * example: - * yoursite.com/controller/action/XXX would be - * tableKeyType => 'params', 'tableIdParamsKey' => 'pass.0' - * yoursite.com/controlerr/action?post_id=XXX would be - * tableKeyType => 'query', 'tableIdParamsKey' => 'post_id' - * yoursite.com/controller/action [posted form with a field named post_id] would be - * tableKeyType => 'data', 'tableIdParamsKey' => 'post_id' - */ - 'tableKeyType' => 'params', - // request->params key path to retrieve the owned table id - 'tableIdParamsKey' => 'pass.0', - /* define table to use or pick it from controller name defaults if null - * if null, table used will be based on current controller's default table - * if string, TableRegistry::get will be used - * if Table, the table object will be used - */ - 'table' => null, - 'conditions' => [], -``` - -Example: - -(in your permissions.php file) -```php -[ - 'role' => ['user'], - 'controller' => ['Posts'], - 'action' => ['edit'], - 'allowed' => new Owner([ - 'ownerForeignKey' => 'owner_id', - ]), -], -``` - -In this example, action `/posts/edit/55` will be allowed if: - * The user is logged in - * The user role is 'user' - * There is a post in posts table with id 55 - * The 'owner_id' field in the post matches the user id - -Checking ownership in belongsToMany associations ------------------ - -Let's say you have users, posts, posts_users tables, and Posts belongsToMany Users, -you could check the ownership configuring the Owner rule: -```php -[ - 'role' => ['user'], - 'controller' => ['Posts'], - 'action' => ['edit'], - 'allowed' => new Owner([ - 'table' => 'PostsUsers', - 'id' => 'post_id', - 'ownerForeignKey' => 'owner_id' - ]), -], -``` - -In this example, action `/posts/edit/55` will be allowed if: - * The user is logged in - * The user role is 'user' - * There is a row in posts_users table matching - * 'owner_id' = user id - * 'post_id' = 55 diff --git a/Docs/Documentation/SimpleRbacAuthorize.md b/Docs/Documentation/SimpleRbacAuthorize.md deleted file mode 100644 index 8a45eac61..000000000 --- a/Docs/Documentation/SimpleRbacAuthorize.md +++ /dev/null @@ -1,141 +0,0 @@ -SimpleRbacAuthorize -============= - -Setup ---------------- - -SimpleRbacAuthorize is configured by default, but you can customize the way it works easily - -Example, in your AppController, you can configure the way the SimpleRbac works by setting the options: - -```php -$config['Auth']['authorize']['CakeDC/Users.SimpleRbac'] = [ - //autoload permissions.php - 'autoload_config' => 'permissions', - //role field in the Users table - 'role_field' => 'role', - //default role, used in new users registered and also as role matcher when no role is available - 'default_role' => 'user', - /* - * This is a quick roles-permissions implementation - * Rules are evaluated top-down, first matching rule will apply - * Each line define - * [ - * 'role' => 'admin', - * 'plugin', (optional, default = null) - * 'prefix', (optional, default = null) - * 'extension', (optional, default = null) - * 'controller', - * 'action', - * 'allowed' (optional, default = true) - * ] - * You could use '*' to match anything - * Suggestion: put your rules into a specific config file - */ - 'permissions' => [], // you could set an array of permissions or load them using a file 'autoload_config' - ]; -``` - -This is the default configuration, based on it the Authorize object will first check your ```config/permissions.php``` -file and load the permissions using the configuration key ```Users.SimpleRbac.permissions```, there is an -example file you can copy into your ```config/permissions.php``` under the Plugin's config directory. - -If you don't want to use a file for configuring the permissions, you just need to tweak the configuration and set -```'autoload_config' => false,``` then define all your rules in AppController (not a good practice as the rules -tend to grow over time). - -The Users Plugin will use the field ```role_field``` in the Users Table to match the role of the user and -check if there is a rule allowing him to access the url. - -The ```default_role``` will be used to set the role of the registered users by default. - -Permission rules syntax ------------------ - -* Permissions are evaluated top-down, first matching permission will apply -* Each permission is an associative array of rules with following structure: `'value_to_check' => 'expected_value'` -* `value_to_check` can be any key from user array or one of special keys: - * Routing params: - * `prefix` - * `plugin` - * `extension` - * `controller` - * `action` - * `role` - Alias/shortcut to field defined in `role_field` config value - * `allowed` - see below -* If you have a user field that overlaps with special keys (eg. `$user->allowed`) you can prepend `user.` to key to force matching from user array (eg. `user.allowed`) -* The keys can be placed in any order with exception of `allowed` which must be last one (see below) -* `value_to_check` can be prepended with `*` to match everything except `expected_value` -* `expected_value` can be one of following things: - * `*` will match absolutely everything - * A _string_/_integer_/_boolean_/etc - will match only the specified value - * An _array_ of strings/integers/booleans/etc (can be mixed). The rule will match if real value is equal to any of expected ones - * A callable/object (see below) -* If any of rules fail, the permission is discarded and the next one is evaluated -* A very special key `allowed` exists which has completely different behaviour: - * If `expected_value` is a callable/object then it's executed and the result is casted to boolean - * If `expected_value` is **not** a callable/object then it's simply casted to boolean - * The `*` is checked and if found the result is inverted - * The final boolean value is **the result of permission** checker. This means if it is `false` then no other permissions are checked and the user is denied access. - For this reason the `allowed` key must be placed at the end of permission since no other rules are executed after it - -**Notes**: - -* For Superadmin access (permission to access ALL THE THINGS in your app) there is a specific Authorize Object provided -* Permissions that do not have `controller` and/or `action` keys (or the inverted versions) are automatically discarded in order to prevent errors. -If you need to match all controllers/actions you can explicitly do `'contoller' => '*'` -* Key `user` (or the inverted version) is illegal (as it's impossible to match an array) and any permission containing it will be discarded -* If the permission is discarded for the reasons stated above, a debug message will be logged - -**Permission Callbacks**: you could use a callback in your 'allowed' to process complex authentication, like - - ownership - - permissions stored in your database - - permission based on an external service API call - -Example *ownership* callback, to allow users to edit their own Posts: - -```php - 'allowed' => function (array $user, $role, \Cake\Network\Request $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; - } -``` - -**Permission Rules**: If you see that you are duplicating logic in your callables, you can create rule class to re-use the logic. -For example, the above ownership callback is included in CakeDC\Users as `Owner` rule -```php -'allowed' => new \CakeDC\Users\Auth\Rules\Owner() //will pick by default the post id from the first pass param -``` -Check the [Owner Rule](OwnerRule.md) documentation for more details - -Creating rule classes ---------------------- - -The only requirement is to implement `\CakeDC\Users\Auth\Rules\Rule` interface which has one method: - -```php -class YourRule implements \CakeDC\Users\Auth\Rules\Rule -{ - /** - * Check the current entity is owned by the logged in user - * - * @param array $user Auth array with the logged in data - * @param string $role role of the user - * @param Request $request current request, used to get a default table if not provided - * @return bool - */ - public function allowed(array $user, $role, Request $request) - { - // Your logic here - } -} -``` - -This logic can be anything: database, external auth, etc. - -Also, if you are using DB, you can choose to extend `\CakeDC\Users\Auth\Rules\AbstractRule` since it provides convenience methods for reading from DB \ No newline at end of file diff --git a/Docs/Documentation/SuperuserAuthorize.md b/Docs/Documentation/SuperuserAuthorize.md deleted file mode 100644 index 7db2cb042..000000000 --- a/Docs/Documentation/SuperuserAuthorize.md +++ /dev/null @@ -1,18 +0,0 @@ -SuperuserAuthorize -============= - -Setup ---------------- - -SuperuserAuthorize is here to provide full permissions to specific "SUPER" users in your app. - -```php -$config['Auth']['authorize']['Users.Superuser'] = [ - //superuser field in the Users table - 'superuser_field' => 'is_superuser', - ]; -``` - -If the current user 'superuser_field' is true, he'll get full permissions in your app. - -Note if you don't have superusers, you can disable the SuperuserAuthorize in AuthComponent initialization \ No newline at end of file diff --git a/Docs/Home.md b/Docs/Home.md index a67b3107b..bce0a151c 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -7,22 +7,24 @@ The plugin is thought as a base to extend your app specific users controller and That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. -Requirements ------------- - -* CakePHP 3.1.* -* PHP 5.4.16+ - Documentation ------------- * [Overview](Documentation/Overview.md) * [Installation](Documentation/Installation.md) * [Configuration](Documentation/Configuration.md) -* [SimpleRbacAuthorize](Documentation/SimpleRbacAuthorize.md) -* [SuperuserAuthorize](Documentation/SuperuserAuthorize.md) +* [SimpleRbacAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SimpleRbacAuthorize.md) +* [SuperuserAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SuperuserAuthorize.md) +* [ApiKeyAuthenticate](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/ApiKeyAuthenticate.md) * [SocialAuthenticate](Documentation/SocialAuthenticate.md) * [UserHelper](Documentation/UserHelper.md) * [Events](Documentation/Events.md) * [Extending the Plugin](Documentation/Extending-the-Plugin.md) * [Translations](Documentation/Translations.md) + +Migration guides +---------------- + +* [4.1.x to 5.0](Documentation/Migration/4.1.x-5.0.md) + + diff --git a/README.md b/README.md index 307a25719..6116369be 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ It covers the following features: * User registration * Login/logout * Social login (Facebook, Twitter, Instagram, Google, Linkedin, etc) -* Simple RBAC -* Remember me (Cookie) +* Simple RBAC via https://github.com/CakeDC/auth +* Remember me (Cookie) via https://github.com/CakeDC/auth * Manage user's profile * Admin management @@ -44,7 +44,7 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.2.9+ +* CakePHP 3.4.0+ * PHP 5.6+ Documentation @@ -57,12 +57,12 @@ Support For bugs and feature requests, please use the [issues](https://github.com/CakeDC/users/issues) section of this repository. -Commercial support is also available, [contact us](http://cakedc.com/contact) for more information. +Commercial support is also available, [contact us](https://www.cakedc.com/contact) for more information. Contributing ------------ -This repository follows the [CakeDC Plugin Standard](http://cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](http://cakedc.com/contribution-guidelines) for detailed instructions. +This repository follows the [CakeDC Plugin Standard](https://www.cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](https://www.cakedc.com/contribution-guidelines) for detailed instructions. License ------- diff --git a/composer.json b/composer.json index d6059f4a6..28e363873 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "~3.4.0" + "cakephp/cakephp": "~3.4.0", + "cakedc/auth": "^1.0" }, "require-dev": { "phpunit/phpunit": "^5.0", diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php index b9e09fc69..1fc12e917 100644 --- a/config/Migrations/20150513201111_initial.php +++ b/config/Migrations/20150513201111_initial.php @@ -1,11 +1,11 @@ [ 'finder' => 'auth', ], - 'CakeDC/Users.ApiKey', - 'CakeDC/Users.RememberMe', + 'CakeDC/Auth.ApiKey', + 'CakeDC/Auth.RememberMe', 'Form', ], 'authorize' => [ - 'CakeDC/Users.Superuser', - 'CakeDC/Users.SimpleRbac', + 'CakeDC/Auth.Superuser', + 'CakeDC/Auth.SimpleRbac', ], ], 'OAuth' => [ diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 56921b71b..cebc65626 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -1,11 +1,11 @@ diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index de4c4360e..8a1840468 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 eef4d035e..686aa84ab 100644 --- a/src/Template/Layout/Email/text/default.ctp +++ b/src/Template/Layout/Email/text/default.ctp @@ -1,16 +1,12 @@ diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index fb99776fa..91794b822 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 1f4123f59..7905537d7 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 a87dfc86f..5a62448a0 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 1cad21655..b0a272b6d 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 c38fa0c1a..d2e21bf7a 100644 --- a/src/Template/Users/view.ctp +++ b/src/Template/Users/view.ctp @@ -1,11 +1,11 @@ getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $registry = new ComponentRegistry($controller); - $this->apiKey = new ApiKeyAuthenticate($registry, ['require_ssl' => false]); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->apiKey, $this->controller); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHappy() - { - $request = new ServerRequest('/?api_key=xxx'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-2', $result['username']); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateFail() - { - $request = new ServerRequest('/'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - - $request = new ServerRequest('/?api_key=none'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - - $request = new ServerRequest('/?api_key='); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - - $request = new ServerRequest('/?api_key=yyy'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Type wrong is not valid - * - */ - public function testAuthenticateWrongType() - { - $this->apiKey->setConfig('type', 'wrong'); - $request = new ServerRequest('/'); - $this->apiKey->authenticate($request, new Response()); - } - - /** - * test - * - * @expectedException \Cake\Network\Exception\ForbiddenException - * @expectedExceptionMessage SSL is required for ApiKey Authentication - * - */ - public function testAuthenticateRequireSSL() - { - $this->apiKey->setConfig('require_ssl', true); - $request = new ServerRequest('/?api_key=test'); - $this->apiKey->authenticate($request, new Response()); - } - - /** - * test - * - */ - public function testAuthenticateRequireSSLNoKey() - { - $this->apiKey->setConfig('require_ssl', true); - $request = new ServerRequest('/'); - $this->assertFalse($this->apiKey->authenticate($request, new Response())); - } - - /** - * test - * - * @return void - */ - public function testHeaderHappy() - { - $request = $this->getMockBuilder('\Cake\Http\ServerRequest') - ->setMethods(['getHeader', 'getHeaderLine']) - ->getMock(); - $request->expects($this->at(0)) - ->method('getHeader') - ->with('api_key') - ->will($this->returnValue(['xxx'])); - $request->expects($this->at(1)) - ->method('getHeaderLine') - ->with('api_key') - ->will($this->returnValue('xxx')); - $this->apiKey->setConfig('type', 'header'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-2', $result['username']); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHeaderFail() - { - $request = $this->getMockBuilder('\Cake\Http\ServerRequest') - ->setMethods(['getHeader', 'getHeaderLine']) - ->getMock(); - $request->expects($this->at(0)) - ->method('getHeader') - ->with('api_key') - ->will($this->returnValue(['wrong'])); - $request->expects($this->at(1)) - ->method('getHeaderLine') - ->with('api_key') - ->will($this->returnValue('wrong')); - $this->apiKey->setConfig('type', 'header'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHeaderNotPresent() - { - $request = $this->getMockBuilder('\Cake\Http\ServerRequest') - ->setMethods(['getHeader']) - ->getMock(); - $request->expects($this->once()) - ->method('getHeader') - ->with('api_key') - ->will($this->returnValue([])); - $this->apiKey->setConfig('type', 'header'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - * @expectedException \BadMethodCallException - * @expectedExceptionMessage Unknown finder method "undefinedInConfig" - */ - public function testAuthenticateFinderConfig() - { - $this->apiKey->setConfig('finder', 'undefinedInConfig'); - $request = new ServerRequest('/?api_key=xxx'); - $result = $this->apiKey->authenticate($request, new Response()); - } - - /** - * test - * - * @return void - * @expectedException \BadMethodCallException - * @expectedExceptionMessage Unknown finder method "undefinedFinderInAuth" - */ - public function testAuthenticateFinderAuthConfig() - { - Configure::write('Auth.authenticate.all.finder', 'undefinedFinderInAuth'); - $request = new ServerRequest('/?api_key=xxx'); - $result = $this->apiKey->authenticate($request, new Response()); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateDefaultAllFinder() - { - Configure::write('Auth.authenticate.all.finder', null); - $request = new ServerRequest('/?api_key=yyy'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-1', $result['username']); - } -} diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php deleted file mode 100644 index f9f3f566c..000000000 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ /dev/null @@ -1,172 +0,0 @@ -controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $registry = new ComponentRegistry($this->controller); - $this->rememberMe = new RememberMeAuthenticate($registry); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->rememberMe, $this->controller); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHappy() - { - $request = new ServerRequest('/'); - $request = $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_agent' => 'user-agent' - ])); - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertEquals('user-1', $result['username']); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateBadUser() - { - $request = new ServerRequest('/'); - $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue([ - //bad-user - 'id' => '00000000-0000-0000-0000-000000000000', - 'user_agent' => 'user-agent' - ])); - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateBadAgent() - { - $request = new ServerRequest('/'); - $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_agent' => 'bad-agent' - ])); - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateNoCookie() - { - $request = new ServerRequest('/'); - $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue(null)); - - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertFalse($result); - } -} diff --git a/tests/TestCase/Auth/Rules/OwnerTest.php b/tests/TestCase/Auth/Rules/OwnerTest.php deleted file mode 100644 index cf6296766..000000000 --- a/tests/TestCase/Auth/Rules/OwnerTest.php +++ /dev/null @@ -1,254 +0,0 @@ -Owner = new Owner(); - $this->request = new ServerRequest(); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->Owner); - } - - /** - * test - * - * @return void - */ - public function testAllowed() - { - $this->request = $this->request - ->withParam('plugin', 'CakeDC/Users') - ->withParam('controller', 'Posts') - ->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testAllowedUsingTableAlias() - { - $this->Owner = new Owner([ - 'table' => 'Posts' - ]); - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testAllowedUsingTableInstance() - { - $this->Owner = new Owner([ - 'table' => TableRegistry::get('CakeDC/Users.Posts'), - ]); - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Missing Table alias, we could not extract a default table from the request - */ - public function testAllowedShouldThrowExceptionBecauseEmptyAliasFromRequest() - { - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->Owner->allowed($user, 'user', $this->request); - } - - /** - * test - * - * @return void - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Missing column column_not_found in table Posts while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 - */ - public function testAllowedShouldThrowExceptionBecauseForeignKeyNotPresentInTable() - { - $this->Owner = new Owner([ - 'table' => TableRegistry::get('CakeDC/Users.Posts'), - 'ownerForeignKey' => 'column_not_found', - ]); - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->Owner->allowed($user, 'user', $this->request); - } - - /** - * test - * - * @return void - */ - public function testNotAllowedBecauseNotOwner() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Posts', - 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testNotAllowedBecauseUserNotFound() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Posts', - 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]); - $user = [ - 'id' => '99999999-0000-0000-0000-000000000000', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testNotAllowedBecausePostNotFound() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Posts', - 'pass' => ['99999999-0000-0000-0000-000000000000'] //not found - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Missing column user_id in table NoDefaultTable while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 - */ - public function testNotAllowedBecauseNoDefaultTable() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'NoDefaultTable', - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * Test using the Owner rule in a belongsToMany association - * Posts belongsToMany Users - * @return void - */ - public function testAllowedBelongsToMany() - { - $this->Owner = new Owner([ - 'table' => 'PostsUsers', - 'id' => 'post_id', - ]); - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'IsNotUsed', - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * Test using the Owner rule in a belongsToMany association - * Posts belongsToMany Users - * @return void - */ - public function testNotAllowedBelongsToMany() - { - $this->Owner = new Owner([ - 'table' => 'PostsUsers', - 'id' => 'post_id', - ]); - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'IsNotUsed', - 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } -} diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php deleted file mode 100644 index 537a291fc..000000000 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ /dev/null @@ -1,1203 +0,0 @@ - 'admin', - 'plugin' => '*', - 'controller' => '*', - 'action' => '*', - ], - //specific actions allowed for the user role in Users plugin - [ - 'role' => 'user', - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => ['profile', 'logout'], - ], - //all roles allowed to Pages/display - [ - 'role' => '*', - 'plugin' => null, - 'controller' => ['Pages'], - 'action' => ['display'], - ], - ]; - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - public function setUp() - { - $request = new ServerRequest(); - $response = new Response(); - - $this->controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $this->registry = new ComponentRegistry($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->simpleRbacAuthorize, $this->controller); - } - - /** - * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct - */ - public function testConstruct() - { - //don't autoload config - $this->simpleRbacAuthorize = new SimpleRbacAuthorize($this->registry, ['autoload_config' => false]); - $this->assertEmpty($this->simpleRbacAuthorize->getConfig('permissions')); - } - - /** - * test - * - * @return void - */ - public function testLoadPermissions() - { - $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') - ->disableOriginalConstructor() - ->getMock(); - $reflectedClass = new ReflectionClass($this->simpleRbacAuthorize); - $loadPermissions = $reflectedClass->getMethod('_loadPermissions'); - $loadPermissions->setAccessible(true); - $permissions = $loadPermissions->invoke($this->simpleRbacAuthorize, 'missing'); - $this->assertEquals($this->defaultPermissions, $permissions); - } - - /** - * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct - */ - public function testConstructMissingPermissionsFile() - { - $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') - ->setMethods(null) - ->setConstructorArgs([$this->registry, ['autoload_config' => 'does-not-exist']]) - ->getMock(); - //we should have the default permissions - $this->assertEquals($this->defaultPermissions, $this->simpleRbacAuthorize->getConfig('permissions')); - } - - protected function assertConstructorPermissions($instance, $config, $permissions) - { - $reflectedClass = new ReflectionClass($instance); - $constructor = $reflectedClass->getConstructor(); - $constructor->invoke($this->simpleRbacAuthorize, $this->registry, $config); - - //we should have the default permissions - $resultPermissions = $this->simpleRbacAuthorize->getConfig('permissions'); - $this->assertEquals($permissions, $resultPermissions); - } - - /** - * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct - */ - public function testConstructPermissionsFileHappy() - { - $permissions = [ - [ - 'controller' => 'Test', - 'action' => 'test' - ] - ]; - $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; - $this->simpleRbacAuthorize = $this->getMockBuilder($className) - ->setMethods(['_loadPermissions']) - ->disableOriginalConstructor() - ->getMock(); - $this->simpleRbacAuthorize - ->expects($this->once()) - ->method('_loadPermissions') - ->with('permissions-happy') - ->will($this->returnValue($permissions)); - $this->assertConstructorPermissions($className, ['autoload_config' => 'permissions-happy'], $permissions); - } - - protected function preparePermissions($permissions) - { - $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; - $simpleRbacAuthorize = $this->getMockBuilder($className) - ->setMethods(['_loadPermissions']) - ->disableOriginalConstructor() - ->getMock(); - $simpleRbacAuthorize->config('permissions', $permissions); - - return $simpleRbacAuthorize; - } - - /** - * @dataProvider providerAuthorize - */ - public function testAuthorize($permissions, $user, $requestParams, $expected, $msg = null) - { - $this->simpleRbacAuthorize = $this->preparePermissions($permissions); - $request = $this->_requestFromArray($requestParams); - - $result = $this->simpleRbacAuthorize->authorize($user, $request); - $this->assertSame($expected, $result, $msg); - } - - public function providerAuthorize() - { - $trueRuleMock = $this->getMockBuilder(Rule::class) - ->setMethods(['allowed']) - ->getMock(); - $trueRuleMock->expects($this->any()) - ->method('allowed') - ->willReturn(true); - - return [ - 'discard-first' => [ - //permissions - [ - [ - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'three', // Discard here - function () { - throw new \Exception(); - } - ], - [ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'deny-first-discard-after' => [ - //permissions - [ - [ - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'one', - 'allowed' => function () { - return false; // Deny here since under 'allowed' key - } - ], - [ - // This permission isn't evaluated - function () { - throw new \Exception(); - }, - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'star-invert' => [ - //permissions - [[ - '*plugin' => 'Tests', - '*role' => 'test', - '*controller' => 'Tests', - '*action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'something', - ], - //request - [ - 'plugin' => 'something', - 'controller' => 'something', - 'action' => 'something' - ], - //expected - true - ], - 'star-invert-deny' => [ - //permissions - [[ - '*plugin' => 'Tests', - '*role' => 'test', - '*controller' => 'Tests', - '*action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'something', - ], - //request - [ - 'plugin' => 'something', - 'controller' => 'something', - 'action' => 'test' - ], - //expected - false - ], - 'user-arr' => [ - //permissions - [ - [ - 'username' => 'luke', - 'user.id' => 1, - 'profile.id' => 256, - 'user.profile.signature' => "Hi I'm luke", - 'user.allowed' => false, - 'controller' => 'Tests', - 'action' => 'one' - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - 'profile' => [ - 'id' => 256, - 'signature' => "Hi I'm luke" - ], - 'allowed' => false - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'evaluate-order' => [ - //permissions - [ - [ - 'allowed' => false, - function () { - throw new \Exception(); - }, - 'controller' => 'Tests', - 'action' => 'one' - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'multiple-callables' => [ - //permissions - [ - [ - function () { - return true; - }, - clone $trueRuleMock, - function () { - return true; - }, - 'controller' => 'Tests', - 'action' => 'one' - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'happy-strict-all' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-strict-all-deny' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - false - ], - 'happy-plugin-null-allowed-null' => [ - //permissions - [[ - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => null, - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-plugin-asterisk' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Any', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-plugin-asterisk-main-app' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => null, - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-role-asterisk' => [ - //permissions - [[ - 'role' => '*', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'any-role', - ], - //request - [ - 'plugin' => null, - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-controller-asterisk' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => '*', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-action-asterisk' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'any' - ], - //expected - true - ], - 'happy-some-asterisk-allowed' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => '*', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'any' - ], - //expected - true - ], - 'happy-some-asterisk-deny' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => '*', - 'action' => '*', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'any' - ], - //expected - false - ], - 'all-deny' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => '*', - 'controller' => '*', - 'action' => '*', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Any', - 'controller' => 'Any', - 'action' => 'any' - ], - //expected - false - ], - 'dasherized' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'TestTests', - 'action' => 'TestAction', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'tests', - 'controller' => 'test-tests', - 'action' => 'test-action' - ], - //expected - true - ], - 'happy-array' => [ - //permissions - [[ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'happy-array-deny' => [ - //permissions - [[ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'three' - ], - //expected - false - ], - 'happy-callback-check-params' => [ - //permissions - [[ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - 'allowed' => function ($user, $role, $request) { - return $user['id'] === 1 && $role = 'test' && $request->plugin == 'Tests'; - } - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'happy-callback-deny' => [ - //permissions - [[ - 'plugin' => ['*'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - 'allowed' => function ($user, $role, $request) { - return false; - } - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'happy-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['admin'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'deny-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['admin'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'star-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => '*', - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['one', 'admin'], - 'controller' => '*', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-prefix-deny' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['one', 'admin'], - 'controller' => '*', - 'action' => 'one', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'happy-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['admin'], - 'extension' => ['csv'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - '_ext' => 'csv', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'deny-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'extension' => ['csv'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - '_ext' => 'csv', - 'action' => 'one' - ], - //expected - false - ], - 'star-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => '*', - 'extension' => '*', - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - '_ext' => 'other', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'extension' => ['csv', 'pdf'], - 'controller' => '*', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - '_ext' => 'csv', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-ext-deny' => [ - //permissions - [[ - 'role' => ['test'], - 'extension' => ['csv', 'docx'], - 'controller' => '*', - 'action' => 'one', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'csv', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'rule-class' => [ - //permissions - [ - [ - 'role' => ['test'], - 'controller' => '*', - 'action' => 'one', - 'allowed' => $trueRuleMock, - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - ]; - } - - /** - * @dataProvider badPermissionProvider - * - * @param array $permissions - * @param array $user - * @param array $requestParams - * @param string $expectedMsg - */ - public function testBadPermission($permissions, $user, $requestParams, $expectedMsg) - { - $simpleRbacAuthorize = $this->getMockBuilder(SimpleRbacAuthorize::class) - ->setMethods(['_loadPermissions', 'log']) - ->disableOriginalConstructor() - ->getMock(); - $simpleRbacAuthorize - ->expects($this->once()) - ->method('log') - ->with($expectedMsg, LogLevel::DEBUG); - - $simpleRbacAuthorize->config('permissions', $permissions); - $request = $this->_requestFromArray($requestParams); - - $simpleRbacAuthorize->authorize($user, $request); - } - - public function badPermissionProvider() - { - return [ - 'no-controller' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - //'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'no-action' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - //'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'no-controller-and-action' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - //'controller' => 'Tests', - //'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'no-controller and user-key' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - //'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - 'user' => 'something', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'user-key' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - 'user' => 'something', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Permission key 'user' is illegal, cannot evaluate the permission"), - ], - ]; - } - - /** - * @param array $params - * @return ServerRequest - */ - protected function _requestFromArray($params) - { - $request = new ServerRequest(); - - return $request - ->withParam('plugin', Hash::get($params, 'plugin')) - ->withParam('controller', Hash::get($params, 'controller')) - ->withParam('action', Hash::get($params, 'action')) - ->withParam('prefix', Hash::get($params, 'prefix')) - ->withParam('_ext', Hash::get($params, '_ext')); - } -} diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index 86735668c..6832c4ec5 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -1,11 +1,11 @@ controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $registry = new ComponentRegistry($this->controller); - $this->superuserAuthorize = new SuperuserAuthorize($registry); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->superuserAuthorize, $this->controller); - } - - /** - * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize - */ - public function testAuthorizeIsSuperuser() - { - $user = [ - 'is_superuser' => true, - ]; - $request = new ServerRequest(); - $result = $this->superuserAuthorize->authorize($user, $request); - $this->assertTrue($result); - } - - /** - * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize - */ - public function testAuthorizeIsNotSuperuser() - { - $user = [ - 'is_superuser' => false, - ]; - $request = new ServerRequest(); - $result = $this->superuserAuthorize->authorize($user, $request); - $this->assertFalse($result); - } - - /** - * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize - */ - public function testAuthorizeWeirdUser() - { - $request = new ServerRequest(); - $user = 'non array'; - $result = $this->superuserAuthorize->authorize($user, $request); - $this->assertFalse($result); - } -} diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index 5a0d094d4..e66faaeef 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -1,4 +1,14 @@ Date: Tue, 14 Mar 2017 12:34:31 +0000 Subject: [PATCH 0597/1476] refs #core34 improve docs --- Docs/Documentation/Migration/4.1.x-5.0.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Migration/4.1.x-5.0.md b/Docs/Documentation/Migration/4.1.x-5.0.md index 091141f1a..9f92b805e 100644 --- a/Docs/Documentation/Migration/4.1.x-5.0.md +++ b/Docs/Documentation/Migration/4.1.x-5.0.md @@ -11,7 +11,18 @@ $config = [ // ... 'Auth' => [ // ... - + 'authenticate' => [ + 'all' => [ + 'finder' => 'auth', + ], + 'CakeDC/Auth.ApiKey', + 'CakeDC/Auth.RememberMe', + 'Form', + ], + 'authorize' => [ + 'CakeDC/Auth.Superuser', + 'CakeDC/Auth.SimpleRbac', + ], // ... ``` From 4bd9f72ec55d94ce4bd75959021197333bd3bccf Mon Sep 17 00:00:00 2001 From: Ahmed omar Date: Tue, 14 Mar 2017 15:10:41 +0200 Subject: [PATCH 0598/1476] add config for remember me initial check status adds a configuration for the "checked status" of the remember me field --- config/users.php | 1 + 1 file changed, 1 insertion(+) diff --git a/config/users.php b/config/users.php index 0b8627148..d470ec1a2 100644 --- a/config/users.php +++ b/config/users.php @@ -103,6 +103,7 @@ 'RememberMe' => [ //configure Remember Me component 'active' => true, + 'checked' => true, 'Cookie' => [ 'name' => 'remember_me', 'Config' => [ From f2f3cdd4b161611e661080f51fd9612d1bc5d174 Mon Sep 17 00:00:00 2001 From: Ahmed omar Date: Tue, 14 Mar 2017 15:15:25 +0200 Subject: [PATCH 0599/1476] read "checked" status of "Remember me" read the configuration of the initial checked status for the remember me check box --- src/Template/Users/login.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 60b36c2af..c7f444b35 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -27,7 +27,7 @@ use Cake\Core\Configure; echo $this->Form->input(Configure::read('Users.Key.Data.rememberMe'), [ 'type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Remember me'), - 'checked' => 'checked' + 'checked' => Configure::read('Users.RememberMe.checked') ]); } ?> From 4e8fb8891bff2ee321bb4d427bdd9c2e98a057c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 15 Mar 2017 16:29:03 +0000 Subject: [PATCH 0600/1476] refs #core34 fix facebook login config issue --- src/Auth/SocialAuthenticate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index b25b3f941..0e42e0a6c 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -304,7 +304,7 @@ protected function _getProvider($alias) return false; } - $this->getConfig($config); + $this->setConfig($config); if (is_object($config) && $config instanceof AbstractProvider) { return $config; From b9c280a3c0999c694c1bc7f5fb208c261b62b2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 15 Mar 2017 18:04:40 +0000 Subject: [PATCH 0601/1476] refs #core34 cs fixes and refactor auth related finders into behavior --- src/Auth/SimpleRbacAuthorize.php | 2 +- src/Auth/SocialAuthenticate.php | 2 +- .../GoogleAuthenticatorComponent.php | 4 +- src/Controller/Traits/LoginTrait.php | 4 +- src/Model/Behavior/AuthFinderBehavior.php | 60 ++++++++++ src/Model/Table/UsersTable.php | 37 +------ src/Shell/UsersShell.php | 5 +- .../TestCase/Auth/SocialAuthenticateTest.php | 2 +- .../Component/RememberMeComponentTest.php | 3 +- .../SocialAccountsControllerTest.php | 2 +- .../Controller/Traits/LoginTraitTest.php | 2 +- .../Model/Behavior/AuthFinderBehaviorTest.php | 104 ++++++++++++++++++ tests/TestCase/Model/Table/UsersTableTest.php | 44 -------- tests/TestCase/View/Helper/UserHelperTest.php | 2 +- 14 files changed, 178 insertions(+), 95 deletions(-) create mode 100644 src/Model/Behavior/AuthFinderBehavior.php create mode 100644 tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php diff --git a/src/Auth/SimpleRbacAuthorize.php b/src/Auth/SimpleRbacAuthorize.php index 87064ec7a..06cbeb9fd 100644 --- a/src/Auth/SimpleRbacAuthorize.php +++ b/src/Auth/SimpleRbacAuthorize.php @@ -16,8 +16,8 @@ use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; use Cake\Core\Exception\Exception; -use Cake\Log\LogTrait; use Cake\Http\ServerRequest; +use Cake\Log\LogTrait; use Cake\Utility\Hash; use Cake\Utility\Inflector; use Psr\Log\LogLevel; diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 0e42e0a6c..619575efb 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -27,8 +27,8 @@ use Cake\Event\Event; use Cake\Event\EventDispatcherTrait; use Cake\Event\EventManager; -use Cake\Log\LogTrait; use Cake\Http\ServerRequest; +use Cake\Log\LogTrait; use Cake\Network\Response; use Cake\ORM\TableRegistry; use Cake\Utility\Hash; diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php index b43826e96..71fab3cb6 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -72,8 +72,8 @@ public function verifyCode($secret, $code) /** * getQRCodeImageAsDataUri - * @param $issuer - * @param $secret + * @param string $issuer issuer + * @param string $secret secret * @return string base64 string containing QR code for shared secret */ public function getQRCodeImageAsDataUri($issuer, $secret) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 5112dd793..3a813c5cc 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Utility\Hash; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -21,6 +20,7 @@ use Cake\Core\Exception\Exception; use Cake\Event\Event; use Cake\Network\Exception\NotFoundException; +use Cake\Utility\Hash; use League\OAuth1\Client\Server\Twitter; /** @@ -313,7 +313,7 @@ protected function _checkReCaptcha() * 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 + * @param bool $googleAuthenticatorLogin googleAuthenticatorLogin * @return array */ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthenticatorLogin = false) diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php new file mode 100644 index 000000000..531693bcb --- /dev/null +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -0,0 +1,60 @@ +where([$this->getTable()->aliasField('active') => 1]); + + return $query; + } + + /** + * Custom finder to log in users + * + * @param Query $query Query object to modify + * @param array $options Query options + * @return Query + * @throws \BadMethodCallException + */ + public function findAuth(Query $query, array $options = []) + { + $identifier = Hash::get($options, 'username'); + if (empty($identifier)) { + throw new \BadMethodCallException(__d('CakeDC/Users', 'Missing \'username\' in options data')); + } + + $query + ->orWhere([$this->getTable()->aliasField('email') => $identifier]) + ->find('active', $options); + + return $query; + } +} diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 6ed996a83..b0ce416c0 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -53,6 +53,7 @@ public function initialize(array $config) $this->addBehavior('CakeDC/Users.Register'); $this->addBehavior('CakeDC/Users.Password'); $this->addBehavior('CakeDC/Users.Social'); + $this->addBehavior('CakeDC/Users.AuthFinder'); $this->hasMany('SocialAccounts', [ 'foreignKey' => 'user_id', 'className' => 'CakeDC/Users.SocialAccounts' @@ -184,40 +185,4 @@ public function buildRules(RulesChecker $rules) return $rules; } - - /** - * 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 = []) - { - $query->where([$this->aliasField('active') => 1]); - - return $query; - } - - /** - * Custom finder to log in users - * - * @param Query $query Query object to modify - * @param array $options Query options - * @return Query - * @throws \BadMethodCallException - */ - public function findAuth(Query $query, array $options = []) - { - $identifier = Hash::get($options, 'username'); - if (empty($identifier)) { - throw new \BadMethodCallException(__d('CakeDC/Users', 'Missing \'username\' in options data')); - } - - $query - ->orWhere([$this->aliasField('email') => $identifier]) - ->find('active', $options); - - return $query; - } } diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 26c4bea3e..01565c76b 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -11,14 +11,13 @@ namespace CakeDC\Users\Shell; -use Cake\Console\ConsoleOptionParser; use CakeDC\Users\Model\Entity\User; -use Cake\Auth\DefaultPasswordHasher; +use CakeDC\Users\Model\Table\UsersTable; +use Cake\Console\ConsoleOptionParser; use Cake\Console\Shell; use Cake\Core\Configure; use Cake\Utility\Hash; use Cake\Utility\Text; -use CakeDC\Users\Model\Table\UsersTable; /** * Shell with utilities for the Users Plugin diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index 6832c4ec5..be7ad5cd7 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Test\TestCase\Auth; -use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; use Cake\Controller\ComponentRegistry; use Cake\Event\Event; +use Cake\Http\ServerRequest; use Cake\Network\Request; use Cake\Network\Response; use Cake\ORM\TableRegistry; diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 6b7bb4900..95e6e756e 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; -use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\RememberMeComponent; use Cake\Controller\ComponentRegistry; use Cake\Controller\Component\AuthComponent; @@ -19,7 +18,7 @@ use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Event\Event; -use Cake\Network\Request; +use Cake\Http\ServerRequest; 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 b43073f79..15140b028 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Test\TestCase\Controller; -use Cake\Http\ServerRequest; 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\Network\Request; use Cake\TestSuite\TestCase; diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index da26eba33..ff7cc177e 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\LoginTrait; @@ -21,6 +20,7 @@ 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; diff --git a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php new file mode 100644 index 000000000..59e51de37 --- /dev/null +++ b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php @@ -0,0 +1,104 @@ +table = TableRegistry::get('CakeDC/Users.Users'); + $this->Behavior = new AuthFinderBehavior($this->table); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->table, $this->Behavior); + parent::tearDown(); + } + + /** + * Test findActive method. + * + */ + public function testFindActive() + { + $actual = $this->table->find('active')->toArray(); + $this->assertCount(8, $actual); + $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); + $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); + } + + /** + * Test findAuth method. + * + * @expectedException \BadMethodCallException + * @expectedExceptionMessage Missing 'username' in options data + */ + public function testFindAuthBadMethodCallException() + { + $user = $this->table->find('auth'); + } + + /** + * Test findAuth method. + * + * @expected + */ + public function testFindAuth() + { + $user = $this->table + ->find('auth', ['username' => 'not-exist@email.com']) + ->toArray(); + $this->assertEmpty($user); + + $user = $this->table + ->find('auth', ['username' => 'user-2@test.com']) + ->first() + ->toArray(); + + $this->assertSame('00000000-0000-0000-0000-000000000002', Hash::get($user, 'id')); + $this->assertSame('user-2', Hash::get($user, 'username')); + } +} diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index c4fa987e3..d21f75d22 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -312,48 +312,4 @@ public function testSocialLoginCreateNewAccount() $this->assertEquals('First Name', $result->first_name); $this->assertEquals('Last Name', $result->last_name); } - - /** - * Test findActive method. - * - */ - public function testFindActive() - { - $actual = $this->Users->find('active')->toArray(); - $this->assertCount(8, $actual); - $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); - $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); - } - - /** - * Test findAuth method. - * - * @expectedException \BadMethodCallException - * @expectedExceptionMessage Missing 'username' in options data - */ - public function testFindAuthBadMethodCallException() - { - $user = $this->Users->find('auth'); - } - - /** - * Test findAuth method. - * - * @expected - */ - public function testFindAuth() - { - $user = $this->Users - ->find('auth', ['username' => 'not-exist@email.com']) - ->toArray(); - $this->assertEmpty($user); - - $user = $this->Users - ->find('auth', ['username' => 'user-2@test.com']) - ->first() - ->toArray(); - - $this->assertSame('00000000-0000-0000-0000-000000000002', Hash::get($user, 'id')); - $this->assertSame('user-2', Hash::get($user, 'username')); - } } diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index c1d1e783c..e777b74f5 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Test\TestCase\View\Helper; -use Cake\Http\ServerRequest; 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; From 27c6e95de64fd077f60440b9906fed447fd13e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 15 Mar 2017 18:14:45 +0000 Subject: [PATCH 0602/1476] refs #core34 rename Behavior Behavior --- src/Model/Behavior/AuthFinderBehavior.php | 2 -- src/Model/Behavior/{Behavior.php => BaseTokenBehavior.php} | 4 ++-- src/Model/Behavior/PasswordBehavior.php | 4 +--- src/Model/Behavior/RegisterBehavior.php | 2 +- src/Model/Behavior/SocialAccountBehavior.php | 1 + src/Model/Behavior/SocialBehavior.php | 2 +- 6 files changed, 6 insertions(+), 9 deletions(-) rename src/Model/Behavior/{Behavior.php => BaseTokenBehavior.php} (95%) diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index 531693bcb..f886c0a1b 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -11,8 +11,6 @@ namespace CakeDC\Users\Model\Behavior; -use Cake\Datasource\EntityInterface; -use Cake\I18n\Time; use Cake\ORM\Behavior; use Cake\ORM\Query; use Cake\Utility\Hash; diff --git a/src/Model/Behavior/Behavior.php b/src/Model/Behavior/BaseTokenBehavior.php similarity index 95% rename from src/Model/Behavior/Behavior.php rename to src/Model/Behavior/BaseTokenBehavior.php index 7bb95f64c..1e6207159 100644 --- a/src/Model/Behavior/Behavior.php +++ b/src/Model/Behavior/BaseTokenBehavior.php @@ -13,12 +13,12 @@ use Cake\Datasource\EntityInterface; use Cake\I18n\Time; -use Cake\ORM\Behavior as BaseBehavior; +use Cake\ORM\Behavior; /** * Covers the user registration */ -class Behavior extends BaseBehavior +class BaseTokenBehavior extends Behavior { /** * DRY for update active and token based on validateEmail flag diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 5658f6aef..5e6caf98f 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -16,17 +16,15 @@ use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; -use CakeDC\Users\Model\Behavior\Behavior; use Cake\Datasource\EntityInterface; use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\Mailer\Email; use Cake\Utility\Hash; use InvalidArgumentException; /** * Covers the password management features */ -class PasswordBehavior extends Behavior +class PasswordBehavior extends BaseTokenBehavior { /** * Constructor hook method. diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 370fddf45..e74f547f0 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -27,7 +27,7 @@ /** * Covers the user registration */ -class RegisterBehavior extends Behavior +class RegisterBehavior extends BaseTokenBehavior { /** * Constructor hook method. diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 5890be762..2210d1ee4 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -21,6 +21,7 @@ use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Event\Event; use Cake\Mailer\Email; +use Cake\ORM\Behavior; use Cake\ORM\Entity; /** diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index c30e5411c..6ce16f8b1 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -25,7 +25,7 @@ * Covers social features * */ -class SocialBehavior extends Behavior +class SocialBehavior extends BaseTokenBehavior { use EventDispatcherTrait; use RandomStringTrait; From b69d5ebb7b0df3c026cb665181898e5f0e05c452 Mon Sep 17 00:00:00 2001 From: Roger Campanera Date: Wed, 15 Mar 2017 18:20:24 +0000 Subject: [PATCH 0603/1476] Fix Requirements version numbers not matching with README --- Docs/Home.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/Home.md b/Docs/Home.md index a67b3107b..969d51fb6 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -10,8 +10,8 @@ That it works out of the box doesn't mean it is thought to be used exactly like Requirements ------------ -* CakePHP 3.1.* -* PHP 5.4.16+ +* CakePHP 3.2.9+ +* PHP 5.5.9+ Documentation ------------- From 71fab5eb4ba34c1815966265f79d5a31be81d26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 16 Mar 2017 10:33:36 +0000 Subject: [PATCH 0604/1476] fix postgre failing test --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 2 +- tests/bootstrap.php | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index ff7cc177e..97031f7a3 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -446,7 +446,7 @@ public function testVerifyGetShowQR() ->disableOriginalConstructor() ->getMock(); $user = [ - 'id' => 1, + 'id' => '00000000-0000-0000-0000-000000000001', 'email' => 'email@example.com', 'secret_verified' => 0, ]; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index d189dd81b..fe9ee7352 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -110,5 +110,17 @@ class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\Ap Cake\Datasource\ConnectionManager::setConfig('test', [ 'url' => getenv('db_dsn'), +// 'className' => 'Cake\Database\Connection', +// 'driver' => 'Cake\Database\Driver\Postgres', +// 'persistent' => true, +// 'host' => 'localhost', +// 'username' => 'my_app', +// 'password' => null, +// 'database' => 'test', +// 'schema' => 'public', +// 'port' => 5432, +// 'encoding' => 'utf8', +// 'flags' => [], +// 'init' => [], 'timezone' => 'UTC' ]); From 916d05e3c2453253e54101a548c5a45be56ff494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 16 Mar 2017 10:46:48 +0000 Subject: [PATCH 0605/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 0dd3d3dd5..7626a355f 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 4 :minor: 1 -:patch: 2 +:patch: 3 :special: '' From 985cf93c497f24f899f93a086eba8ed678714be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 16 Mar 2017 10:47:34 +0000 Subject: [PATCH 0606/1476] Update CHANGELOG.md --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b541f59c..d560919b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ Changelog Releases for CakePHP 3 ------------- + +* 4.1.3 + * Configurable rememberMe checkbox status + * Update brazilian portuguese translations + * Add active finder to SocialAccountsTable + * Improvements in UsersShell for superuser add options + * Update to robthree/twofactorauth 1.6 + * UserHelper improvements + * 4.1.2 * Fix RememberMe redirect * Fix AuthLink rendering inside Cells From 7cfc11fe136cf91a8a6e35583461d929169d34c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 16 Mar 2017 10:54:20 +0000 Subject: [PATCH 0607/1476] refs #core34 fix versions in readme --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6116369be..181067946 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,11 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | | 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | -| 3.2+ | [master](https://github.com/cakedc/users/tree/master) | 3.x | stable | -| 3.2+ | [develop](https://github.com/cakedc/users/tree/develop) | 3.x | unstable | -| 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stability is beta, but pretty stable now | -| 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stability is beta, but pretty stable now | +| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.0.0 | stable | +| 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | 5.0.0 | unstable | +| 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stable | +| 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stable | +| 3.3 | [3.3.x](https://github.com/cakedc/users/tree/3.3.x) | 4.1.3 | stable | The **Users** plugin is back! From a54e6977e53988235115861d2e1a515cec4d1c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 16 Mar 2017 10:56:09 +0000 Subject: [PATCH 0608/1476] refs #core34 fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 181067946..e96231fb9 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Versions and branches | 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | 5.0.0 | unstable | | 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stable | | 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stable | -| 3.3 | [3.3.x](https://github.com/cakedc/users/tree/3.3.x) | 4.1.3 | stable | +| 3.3 | [4.1.x](https://github.com/cakedc/users/tree/4.1.x) | 4.1.3 | stable | The **Users** plugin is back! From 35e2d4bdf5843ca5f679bdb1b291c8ab24c7e437 Mon Sep 17 00:00:00 2001 From: Lorenzo Maieru Date: Thu, 16 Mar 2017 17:26:37 -0300 Subject: [PATCH 0609/1476] Drop default config before defining test config --- tests/TestCase/Controller/SocialAccountsControllerTest.php | 1 + tests/TestCase/Controller/Traits/BaseTraitTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index c85dc2e86..064716369 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -50,6 +50,7 @@ public function setUp() 'className' => 'Debug' ]); $this->configEmail = Email::config('default'); + Email::drop(); Email::config('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 299de8ba5..354a96768 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -64,6 +64,7 @@ public function setUp() 'className' => 'Debug' ]); $this->configEmail = Email::config('default'); + Email::drop(); Email::config('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' From c17e7216feb60ccfa0b2f80b42805de5e6017384 Mon Sep 17 00:00:00 2001 From: Lorenzo Maieru Date: Thu, 16 Mar 2017 17:31:18 -0300 Subject: [PATCH 0610/1476] specifying default config --- tests/TestCase/Controller/SocialAccountsControllerTest.php | 2 +- tests/TestCase/Controller/Traits/BaseTraitTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 064716369..f1468eb6f 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -50,7 +50,7 @@ public function setUp() 'className' => 'Debug' ]); $this->configEmail = Email::config('default'); - Email::drop(); + Email::drop('default'); Email::config('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 354a96768..e7c898c3d 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -64,7 +64,7 @@ public function setUp() 'className' => 'Debug' ]); $this->configEmail = Email::config('default'); - Email::drop(); + Email::drop('default'); Email::config('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' From f3bd5f644500c078c3b748e43f6dddefcbcd05e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 17 Mar 2017 09:34:42 +0000 Subject: [PATCH 0611/1476] refs # add custom registration role --- Docs/Documentation/Configuration.md | 4 +- config/users.php | 4 +- src/Model/Behavior/RegisterBehavior.php | 5 +- src/Shell/UsersShell.php | 2 +- .../Model/Behavior/RegisterBehaviorTest.php | 55 +++++++++++++++- tests/TestCase/Shell/UsersShellTest.php | 65 ++++++++++++++++++- 6 files changed, 128 insertions(+), 7 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 1f05b7262..7df437bed 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -85,7 +85,9 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use //determines if the reCaptcha is enabled for registration 'reCaptcha' => true, //ensure user is active (confirmed email) to reset his password - 'ensureActive' => false + 'ensureActive' => false, + // default role name used in registration + 'defaultRole' => 'user', ], 'Tos' => [ //determines if the user should include tos accepted diff --git a/config/users.php b/config/users.php index 9697b56b4..f05d5b20d 100644 --- a/config/users.php +++ b/config/users.php @@ -36,7 +36,9 @@ //allow a logged in user to access the registration form 'allowLoggedIn' => false, //ensure user is active (confirmed email) to reset his password - 'ensureActive' => false + 'ensureActive' => false, + // default role name used in registration + 'defaultRole' => 'user', ], 'reCaptcha' => [ //reCaptcha key goes here diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 0a4cd21b3..d2560c4ab 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -57,7 +57,10 @@ public function register($user, $data, $options) $validateEmail = Hash::get($options, 'validate_email'); $tokenExpiration = Hash::get($options, 'token_expiration'); $emailClass = Hash::get($options, 'email_class'); - $user = $this->_table->patchEntity($user, $data, ['validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options)]); + $user = $this->_table->patchEntity($user, $data, [ + 'validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options) + ]); + $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; $user->validated = false; //@todo move updateActive to afterSave? $user = $this->_updateActive($user, $validateEmail, $tokenExpiration); diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 2c5ef1895..56e37479c 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -78,7 +78,7 @@ public function getOptionParser() */ public function addUser() { - $this->_createUser(['role' => 'user']); + $this->_createUser(['role' => Configure::read('Users.Registration.defaultRole') ?: 'user']); } /** diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index e6d3657b3..d53d4db59 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; +use Cake\Core\Configure; use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; @@ -228,7 +229,7 @@ public function testValidate() * Test Validate method * * @return void - * @expectedException CakeDC\Users\Exception\TokenExpiredException + * @expectedException \CakeDC\Users\Exception\TokenExpiredException */ public function testValidateUserWithExpiredToken() { @@ -239,7 +240,7 @@ public function testValidateUserWithExpiredToken() * Test Validate method * * @return void - * @expectedException CakeDC\Users\Exception\UserNotFoundException + * @expectedException \CakeDC\Users\Exception\UserNotFoundException */ public function testValidateNotExistingUser() { @@ -264,4 +265,54 @@ public function testActiveUserRemoveValidationToken() $this->Behavior->activateUser($user); } + + /** + * Test register default role + * + * @return void + */ + public function testRegisterUsingDefaultRole() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + Configure::write('Users.Registration.defaultRole', false); + $result = $this->Table->register($this->Table->newEntity(), $user, [ + 'token_expiration' => 3600, + 'validate_email' => 0, + 'email_class' => $this->Email + ]); + $this->assertSame('user', $result['role']); + } + + /** + * Test register not default role + * + * @return void + */ + public function testRegisterUsingCustomRole() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + Configure::write('Users.Registration.defaultRole', 'emperor'); + $result = $this->Table->register($this->Table->newEntity(), $user, [ + 'token_expiration' => 3600, + 'validate_email' => 0, + 'email_class' => $this->Email + ]); + $this->assertSame('emperor', $result['role']); + } } diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 1159fe3aa..20caf7ef0 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -12,8 +12,8 @@ namespace CakeDC\Users\Test\TestCase\Shell; use CakeDC\Users\Shell\UsersShell; -use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOutput; +use Cake\Core\Configure; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; @@ -355,4 +355,67 @@ public function testDeleteUser() $this->Shell->runCommand(['deleteUser', 'user-5']); $this->assertEmpty($this->Users->findById('00000000-0000-0000-0000-000000000005')->first()); } + + /** + * test + * + * @return void + */ + public function testAddUserCustomRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $this->assertEmpty($this->Users->findByUsername('custom')->first()); + $this->Shell->runCommand([ + 'addUser', + '--username=custom', + '--password=12345678', + '--email=custom@example.com', + '--role=custom' + ]); + $user = $this->Users->findByUsername('custom')->first(); + $this->assertSame('custom', $user['role']); + } + + /** + * test + * + * @return void + */ + public function testAddUserDefaultRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $this->assertEmpty($this->Users->findByUsername('custom')->first()); + Configure::write('Users.Registration.defaultRole', false); + $this->Shell->runCommand([ + 'addUser', + '--username=custom', + '--password=12345678', + '--email=custom@example.com', + ]); + $user = $this->Users->findByUsername('custom')->first(); + $this->assertSame('user', $user['role']); + } + + /** + * test + * + * @return void + */ + public function testAddUserCustomDefaultRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $this->assertEmpty($this->Users->findByUsername('custom')->first()); + Configure::write('Users.Registration.defaultRole', 'emperor'); + $this->Shell->runCommand([ + 'addUser', + '--username=custom', + '--password=12345678', + '--email=custom@example.com', + ]); + $user = $this->Users->findByUsername('custom')->first(); + $this->assertSame('emperor', $user['role']); + } } From fb08258e55ccba0a7b1f65ac9bb3d359e75c21c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 17 Mar 2017 09:48:32 +0000 Subject: [PATCH 0612/1476] Update .semver --- .semver | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.semver b/.semver index 0dd3d3dd5..d95380d2c 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 4 -:minor: 1 -:patch: 2 +:minor: 2 +:patch: 0 :special: '' From de4ba0c5d90af6c82c6f5ac54ccdb69c5d82881d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 17 Mar 2017 09:50:46 +0000 Subject: [PATCH 0613/1476] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b541f59c..fe5f40b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Changelog Releases for CakePHP 3 ------------- + +* 4.2.0 + * New configuration param `Users.Registration.defaultRole` to set the default role on user registration or addUser Shell action + * 4.1.2 * Fix RememberMe redirect * Fix AuthLink rendering inside Cells From 08c86e53f0d7586bd13462b74fb67da5e5d65910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 17 Mar 2017 09:54:15 +0000 Subject: [PATCH 0614/1476] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 307a25719..c1b22b0c4 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Versions and branches | 3.2+ | [develop](https://github.com/cakedc/users/tree/develop) | 3.x | unstable | | 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stability is beta, but pretty stable now | | 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stability is beta, but pretty stable now | +| 3.3 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.0 | stable | The **Users** plugin is back! From cc79c9fa5e1c06f1f7aa2a2a7465b8f912dd9a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Sat, 18 Mar 2017 17:13:54 +0100 Subject: [PATCH 0615/1476] Removing duplicated message to avoid gettext errors --- src/Locale/Users.pot | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index 170beecb5..e34d1e324 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -468,6 +468,7 @@ 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 correcly displayed, please copy the following address in your web browser {0}" msgstr "" @@ -488,10 +489,6 @@ msgstr "" msgid "Activate your account here" msgstr "" -#: Template/Email/html/validation.ctp:27 -msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" -msgstr "" - #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" From 4d21a164a32d96fc738c8108f9c51fbb0e6f4180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Sat, 18 Mar 2017 17:14:10 +0100 Subject: [PATCH 0616/1476] Updating French translation --- src/Locale/fr_FR/Users.mo | Bin 15733 -> 16147 bytes src/Locale/fr_FR/Users.po | 369 ++++++++++++++++++++++---------------- 2 files changed, 214 insertions(+), 155 deletions(-) diff --git a/src/Locale/fr_FR/Users.mo b/src/Locale/fr_FR/Users.mo index 7c9623937dc01be42a976d7f47c81bbf478174f2..fc623371daeb2249909fa3fc2f7b26a62cfd7179 100644 GIT binary patch delta 4499 zcmZA23vf+$0>|vsSkz7fTo4C0_(cHGG*j0<8 zlzNr*N?*8M(^_L@+wPXBc6D~t?Ao27Wx8Em`?7ZIto{CS4`X{Kzw`N@|2_Ad|MTXb zE39V!AL2saFdSz|GWmU5V;Noo+gi&z}Bk&CN#|zj2|AK13f3Y`4#0KvlfO=5AZ3(7xJq@|l ztVA_rgMGafL%BYPN!Ws6#&6806x7+zF#)fkZu~3i#rKdwF(%HKP7sFbSrY30JmeNr zYCG4iUxJa;ugA`~)xK`AJ%wSs-&~*&g1B zLw-OPhS5qjyufw@szc*Y9WBFXoQ;09a3KZtun9F4D=`&c!AW=!N8`UxQ#73J$T1j& zlTZztgL-fSsw2&)=e&lx|0rtBoUr{(XU4xf6?du7+;(7v=>d5-0gG`sZo%nz1qWka zx|@hqNSn-y*b}$d^(Rr!{T%r--*eKMYQvW@FbDhM%tXdtEn7o{9=MT{hVHO^eH``q zMbx7D3N?h^pdNe|wMZja5dAO#H6_L9#75K$x1x5}Ipizm8fsVk%}=2Zg=nrclm)1k zkHTI!AGHS7p{C|dR73Wn?mLER;AO1AtEdhXvBb4T#^Mn4U^=!Sf94BL45smaPeDBi zp?P{?H`GuSp;}zeiD#M(sFoi_eer_rRn*$~0X231KxWf~&^q0ph)&E#eO``F;XE9| z`_1bV)Pv7ZExv+!z&+H^MX_SEmeUqZ%PZGaYHWsYl(n71f~K_Vr2BbAOS+_)|7lIq3@zQ6rL0_tfG-+Zm|E zv=lW0YcL%5*d9Xl?0wr0QNM_v;$r+7)zN4A&`F$%8qw>13hJqTj&h+tYVPLaJZwhI z?H_G#Vkp|VP@erz^*HPd5&c2Sx4z7_TjHG@fMq??q z?*Ca7H1{6VzO=9ePvBVmHx}Ti9AlowRmkX>k5DhVjar1!%pbF924XDEL4DqU>d-cf z!Aq#M^E*t^{=Z3q&Y6c8fdjaE4GzM#cpf#hALAIjgL-g&Uhu!zY}8_1i|WWhr1Rz? zs=*JiCl)eHX*e6Th+jg#hI9vocsz-E;jiuM%cv>2foi~iP;=Xh;n4l%s2453iMSor zf!j!5%w5!r(gy{nY8WPPy%NVk*oiS=~@QbOaFATArj73~8LiOZb z)c3x$ukWL_RdQjlemH6>s!{bXAcJ9cp`LrC(BA)lqC(p$j-Nm6^91A{ndyyHSd683 z1o<=fIE}-cp}{$CM!nz&&c;i)4l`MyOYu1Bg_+DpJ1j!2fw6uHTD9eV31cf=I@ll1XMtKI=MxyLG;eVf#R{K2iGs5pk>!NuB zHAgQI9olL-c90a(k(3c9(PFJ96UcO;Dm4@SBaCBM3XjyhZc_ z^d|WUd34OD&_LLwt^Yn%-$b&BM(`ksC$%JxEGIe+lYJ_1>?JFRn`96jG5Yq~6xI{% z+aDjRsHpi-WgD)WNfmjHB#>u_j?tvJwG{kC9BG$haT%FR7TI;XaH)FGg-jufNiunv zOe1}Wjt_JiQTD9USHH;Z32f>R?+CB()z*8QRo2d!FJtOG3u?V}&W4J{#%1;1sz6Q0 zzK-ycT5qGz>9ID(E)Ueib#Sz;&}Cprd>4ncqSKVXC!LbogjLrz`rKaYdcx4~vf#I^ zVTlQW%)|qZ@QIV1RTVzB^;y?lfi>N3Il|q`8*07o#z0kabepWo3XiAW=WJ?pJAE~7 zXJwPu>-P8_x4~J_*jn##FLTy=4lGIuv8sEnE-c7$cU(QJw_O9Q%ek@Erh4^pfo+~^PVnq$B{U6qi8#4d^ delta 3997 zcmYk<3vgA%9mny#c@RkCkqftZ5fe!uktC8E0_Ft-Nkdc;1XL_ROiB`oNDxFoG+dz( zs3j0`5J6s+N2G|T9APNxjMGx;*eRvMXfvIXDfHnh=xAGN%Z&E>J7?*5Cjax<-FqIp z|J^+d&f0&iiSz|yo;Mt?5+jL@SYtlH{&-FtT|%zx zsOw5G73W|EwjqCJ3#S3N4+k0(F^4JKM#FLBS>_TB!hRfs*HAa45Az?8Z7s%Z+N)46 zZbkmgGEOnL9@B6m>i&b6fJZS2Phkx2H|Htng%^>*n@czX|AHFH*QgtUiN^3}##$>- z?RBVRwO|OB+4@G*i@PxjccD7E2OIDZHu8QG8}vu^Fji4th5TmT#wd5i3csT;9dBXS%!z5WE=P6bDbxcy zQ6t!mdcZ-{S~zF@8>Ul_Aq``26zaY^u@2|r6zsvd`1cU`FQqV<6_$*vk!P4~cnkK} z_V-W^zKqJix2QFfL?s8SaV)l>2CxhDyaT8Vy=CjaLT1zSp)&PF68WcWu5-%6;oPNE zPr*!Fih4m8YImGQ{>%rQw7NgXTX7HzS!g7#s$dwH65tbZ%1`tH|n}$5ekba zypQVXc%G^`pM)9Mh~>Brwc6i7t?DaC63jQK0fcDO3ky)0nS<)^dgKzbAJy?QsQWHj zBcD>x;s|iH<|+=E9uq>{kcXLAh56Ww<=Bl%^?6i>|A4yhIx1s{3{PvN6tzaCqONPO zb|6y_F-It{{>+=GRK17#4)kIHeuUl#d5T6-fNTU)W9#*(5v@dZs1tSl4%8YtjvCkn zTkk{d7Nz$l?f+N`WZwj_67x}OV2O1va*z2fGC0$Z+NOgtjd=j;P^wMqaO5U`}@bJ zDNA6Xp4_MuOWRk+3ZdJOf4sMWDTyvPF#pXx%d%$94oO8Gcl6E*FveU#A2L>Oqbb; zWXYUFb?6e_fnVb!ET=aU@kva;*HQPqZR=N%Su&sFU<|Ra)Uhno)K0`|?f-fTchPVF zZ^x@R8ApfxPjVCL!Cj~aoepr#!Z%|*-KbDgJCJO(iL0`7{WsDMcqUQLos22|5$N3n>O}GVDVp4_w zqAfUxdJo3o>!?L}8a0(?ZTn!-#I&0bD#JCC$bW#sY(jH5j9_PY$3AN-ZX@kD$)5Kh2i`POnt(r=$KX3If!Ffb3p+&NRSVk-&bUZ+;_DcSj zOegoy|n#Ax@gZYC?-m$4kWH#J$9g;}C^3 z;$_?LBdez2yGQbODnGPkrCf(rz2;xX6rYG$MS+FueTM7(M(>=;xtq{@YEh*S@x=ED z9qW9&^8wC{w*D~cgEPn0^Q>Yk(N63kN{G9?{8MNq4if3aEQ0mn{f~%s>1~;3QHK^; zl~?i?W+mlJTaUpU;%4F)v71;x=(DS1q>nj*yZ;P1F!;iS5K4L>uuSF`dv6BxVwP6up1zUqO9Eb^L_b<(1fMw^A74SB!(@ z#8F${VSOI!2)BFa@PKo2*stBr#N2@MZg7QjF_;`!;eHmJ8*pcgNDMfSgr>V^LcwU~ zgXB_YdD=*4ZECzbEoF1S=}mnxdg-H0?tN*|QEp56fM|Dr=6?gu-cgZZ6AKDU3c@9s z;i9sllDxtqCqFAW`2WV@vO+Z$7CM`<@}09;djciS{aNJ$%Q9P*KU6(C-d&nq7;sOF zE)JZ?=?OT;b6;?Ka}%Q6kH$IyXKVgK_uKqwF-~o`+C33&k8(RJZgVbF dWVrpsEm6*ui79U6_S<6I>*cRSImahA{||5ksT%+Q diff --git a/src/Locale/fr_FR/Users.po b/src/Locale/fr_FR/Users.po index e26968b85..6a88a9bdf 100644 --- a/src/Locale/fr_FR/Users.po +++ b/src/Locale/fr_FR/Users.po @@ -4,41 +4,41 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2016-08-18 12:28+0200\n" -"PO-Revision-Date: 2016-08-18 14:08+0200\n" +"POT-Creation-Date: 2017-03-18 16:49+0100\n" +"PO-Revision-Date: 2017-03-18 16:52+0100\n" +"Last-Translator: Jean Traullé \n" "Language-Team: CakeDC \n" +"Language: fr_FR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 1.8.8\n" -"Last-Translator: Jean Traullé \n" -"Language: fr_FR\n" +"X-Generator: Poedit 1.8.11\n" -#: Auth/ApiKeyAuthenticate.php:55 +#: Auth/ApiKeyAuthenticate.php:73 msgid "Type {0} is not valid" msgstr "Le type {0} est invalide" -#: Auth/ApiKeyAuthenticate.php:59 +#: Auth/ApiKeyAuthenticate.php:77 msgid "Type {0} has no associated callable" msgstr "Le type {0} n'a aucune fonction de rappel associée" -#: Auth/ApiKeyAuthenticate.php:68 +#: Auth/ApiKeyAuthenticate.php:86 msgid "SSL is required for ApiKey Authentication" msgstr "SSL est requis pour ApiKey Authentication" -#: Auth/SimpleRbacAuthorize.php:141 +#: Auth/SimpleRbacAuthorize.php:142 msgid "" "Missing configuration file: \"config/{0}.php\". Using default permissions" msgstr "" "Fichier de configuration manquant : \"config/{0}.php\". Utilisation des " "permissions par défaut" -#: Auth/SocialAuthenticate.php:410 +#: Auth/SocialAuthenticate.php:432 msgid "Provider cannot be empty" msgstr "Le fournisseur ne peut pas être vide" -#: Auth/Rules/AbstractRule.php:77 +#: Auth/Rules/AbstractRule.php:78 msgid "" "Table alias is empty, please define a table alias, we could not extract a " "default table from the request" @@ -66,7 +66,7 @@ msgstr "Le compte n'a pas pu être validé" msgid "Invalid token and/or social account" msgstr "Jeton et/ou compte de réseau social invalide" -#: Controller/SocialAccountsController.php:59;86 +#: Controller/SocialAccountsController.php:59;87 msgid "Social Account already active" msgstr "Compte de réseau social déjà actif" @@ -74,19 +74,19 @@ msgstr "Compte de réseau social déjà actif" msgid "Social Account could not be validated" msgstr "Le compte de réseau social n'a pas pu être validé" -#: Controller/SocialAccountsController.php:79 +#: Controller/SocialAccountsController.php:80 msgid "Email sent successfully" msgstr "Courriel envoyé avec succès" -#: Controller/SocialAccountsController.php:81 +#: Controller/SocialAccountsController.php:82 msgid "Email could not be sent" msgstr "Le courriel n'a pas pu être envoyé" -#: Controller/SocialAccountsController.php:84 +#: Controller/SocialAccountsController.php:85 msgid "Invalid account" msgstr "Compte invalide" -#: Controller/SocialAccountsController.php:88 +#: Controller/SocialAccountsController.php:89 msgid "Email could not be resent" msgstr "Le courriel n'a pas pu être réenvoyé" @@ -96,23 +96,23 @@ msgstr "" "Clé de salage de l'application invalide, la clé de salage de l'application " "doit-être d'une longueur minimale de 256 bits (32 octets)" -#: Controller/Component/UsersAuthComponent.php:157 +#: Controller/Component/UsersAuthComponent.php:178 msgid "You can't enable email validation workflow if use_email is false" msgstr "" "Vous ne pouvez pas activer le processus de validation par courriel si " "use_email est défini à false" -#: Controller/Traits/LoginTrait.php:95 +#: Controller/Traits/LoginTrait.php:96 msgid "Issues trying to log in with your social account" msgstr "" "Un problème est survu lors de la tentative d'identification avec votre " "compte de réseau social" -#: Controller/Traits/LoginTrait.php:100 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "Merci d'entrer votre email" -#: Controller/Traits/LoginTrait.php:106 +#: Controller/Traits/LoginTrait.php:108 msgid "" "Your user has not been validated yet. Please check your inbox for " "instructions" @@ -120,7 +120,7 @@ msgstr "" "Votre compte n'a pas encore été validé. Merci de vérifier votre boîte de " "réception pour obtenir les instructions" -#: Controller/Traits/LoginTrait.php:108 +#: Controller/Traits/LoginTrait.php:110 msgid "" "Your social account has not been validated yet. Please check your inbox for " "instructions" @@ -128,64 +128,64 @@ msgstr "" "Votre compte de réseau social n'a pas encore été validé. Merci de vérifier " "votre boîte de réception pour obtenir les instructions" -#: Controller/Traits/LoginTrait.php:157 Controller/Traits/RegisterTrait.php:73 +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 msgid "Invalid reCaptcha" msgstr "La validation reCaptcha a échoué" -#: Controller/Traits/LoginTrait.php:165 +#: Controller/Traits/LoginTrait.php:171 msgid "You are already logged in" msgstr "Vous êtes déjà identifié" -#: Controller/Traits/LoginTrait.php:209 +#: Controller/Traits/LoginTrait.php:217 msgid "Username or password is incorrect" msgstr "Le nom d'utilisateur ou le mot de passe est incorrect" -#: Controller/Traits/LoginTrait.php:230 +#: Controller/Traits/LoginTrait.php:238 msgid "You've successfully logged out" msgstr "Vous avez été correctement déconnecté" -#: Controller/Traits/PasswordManagementTrait.php:53;60;68 +#: Controller/Traits/PasswordManagementTrait.php:47;76 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "L'utilisateur n'a pas été trouvé" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 msgid "Password could not be changed" msgstr "Le mot de passe n'a pas pu être changé" -#: Controller/Traits/PasswordManagementTrait.php:57 +#: Controller/Traits/PasswordManagementTrait.php:68 msgid "Password has been changed successfully" msgstr "Le mot de passe a été changé avec succès" -#: Controller/Traits/PasswordManagementTrait.php:64 -#: Controller/Traits/ProfileTrait.php:49 -msgid "User was not found" -msgstr "L'utilisateur n'a pas été trouvé" - -#: Controller/Traits/PasswordManagementTrait.php:66 -msgid "The current password does not match" -msgstr "Le mot de passe actuel ne correspond pas" +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" -#: Controller/Traits/PasswordManagementTrait.php:108 +#: Controller/Traits/PasswordManagementTrait.php:120 msgid "Please check your email to continue with password reset process" msgstr "" "Merci de vérifier vos courriels pour poursuivre la procédure de " "réinitialisation du mot de passe" -#: Controller/Traits/PasswordManagementTrait.php:111 Shell/UsersShell.php:266 +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 msgid "The password token could not be generated. Please try again" msgstr "Le jeton du mot de passe n'a pas pu être généré. Veuillez réessayer" -#: Controller/Traits/PasswordManagementTrait.php:116 -#: Controller/Traits/UserValidationTrait.php:98 +#: Controller/Traits/PasswordManagementTrait.php:129 +#: Controller/Traits/UserValidationTrait.php:100 msgid "User {0} was not found" msgstr "L'utilisateur {0} n'a pas été trouvé" -#: Controller/Traits/PasswordManagementTrait.php:118 +#: Controller/Traits/PasswordManagementTrait.php:131 msgid "The user is not active" msgstr "L'utilisateur n'est pas actif" -#: Controller/Traits/PasswordManagementTrait.php:120 -#: Controller/Traits/UserValidationTrait.php:94;102 +#: Controller/Traits/PasswordManagementTrait.php:133 +#: Controller/Traits/UserValidationTrait.php:95;104 msgid "Token could not be reset" msgstr "Le jeton n'a pas pu être réinitialisé" -#: Controller/Traits/ProfileTrait.php:52 +#: Controller/Traits/ProfileTrait.php:53 msgid "Not authorized, please login first" msgstr "Non autorisé, merci de vous identifier d'abord" @@ -194,31 +194,31 @@ msgid "You must log out to register a new user account" msgstr "" "Vous devez vous déconnecter pour enregistrer un nouveau compte utilisateur" -#: Controller/Traits/RegisterTrait.php:79 +#: Controller/Traits/RegisterTrait.php:88 msgid "The user could not be saved" msgstr "L'utilisateur n'a pas pu être sauvegardé" -#: Controller/Traits/RegisterTrait.php:111 +#: Controller/Traits/RegisterTrait.php:122 msgid "You have registered successfully, please log in" msgstr "Vous êtes désormais enregistré, merci de vous identifier" -#: Controller/Traits/RegisterTrait.php:113 +#: Controller/Traits/RegisterTrait.php:124 msgid "Please validate your account before log in" msgstr "Merci de valider votre compte avant de vous identifier" -#: Controller/Traits/SimpleCrudTrait.php:76;105 +#: Controller/Traits/SimpleCrudTrait.php:76;106 msgid "The {0} has been saved" msgstr "Le {0} a été sauvegardé" -#: Controller/Traits/SimpleCrudTrait.php:79;108 +#: Controller/Traits/SimpleCrudTrait.php:80;110 msgid "The {0} could not be saved" msgstr "Le {0} n'a pas pu être sauvegardé" -#: Controller/Traits/SimpleCrudTrait.php:128 +#: Controller/Traits/SimpleCrudTrait.php:130 msgid "The {0} has been deleted" msgstr "Le {0} a été supprimé" -#: Controller/Traits/SimpleCrudTrait.php:130 +#: Controller/Traits/SimpleCrudTrait.php:132 msgid "The {0} could not be deleted" msgstr "Le {0} n'a pas pu être supprimé" @@ -242,28 +242,28 @@ msgstr "Utilisateur déjà actif" msgid "Reset password token was validated successfully" msgstr "Le jeton de réinitialisation du mot de passe a été validé avec succès" -#: Controller/Traits/UserValidationTrait.php:57 +#: Controller/Traits/UserValidationTrait.php:58 msgid "Reset password token could not be validated" msgstr "Le jeton de réinitialisation du mot de passe n'a pas pu être validé" -#: Controller/Traits/UserValidationTrait.php:61 +#: Controller/Traits/UserValidationTrait.php:62 msgid "Invalid validation type" msgstr "Type de validation invalide" -#: Controller/Traits/UserValidationTrait.php:64 +#: Controller/Traits/UserValidationTrait.php:65 msgid "Invalid token or user account already validated" msgstr "Jeton invalide ou compte utilisateur déjà activé" -#: Controller/Traits/UserValidationTrait.php:66 +#: Controller/Traits/UserValidationTrait.php:67 msgid "Token already expired" msgstr "Le jeton a déjà expiré" -#: Controller/Traits/UserValidationTrait.php:92 +#: Controller/Traits/UserValidationTrait.php:93 msgid "Token has been reset successfully. Please check your email." msgstr "" "Le jeton a été réinitialisé avec succès. Veuillez consulter vos courriels." -#: Controller/Traits/UserValidationTrait.php:100 +#: Controller/Traits/UserValidationTrait.php:102 msgid "User {0} is already active" msgstr "L'utilisateur {0} est déjà actif" @@ -287,12 +287,12 @@ msgstr "La référence ne peut pas être nulle" msgid "Token expiration cannot be empty" msgstr "L'expiration du jeton ne peut pas être vide" -#: Model/Behavior/PasswordBehavior.php:67;115 +#: Model/Behavior/PasswordBehavior.php:67;116 msgid "User not found" msgstr "Utilisateur non trouvé" #: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:110 +#: Model/Behavior/RegisterBehavior.php:111 msgid "User account already validated" msgstr "Compte utilisateur déjà validé" @@ -300,23 +300,28 @@ msgstr "Compte utilisateur déjà validé" msgid "User not active" msgstr "Utilisateur non activé" -#: Model/Behavior/PasswordBehavior.php:120 -msgid "The old password does not match" -msgstr "L'ancien mot de passe ne correspond pas" +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "Le mot de passe actuel ne correspond pas" -#: Model/Behavior/RegisterBehavior.php:88 +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "" +"Vous ne pouvez pas utiliser le mot de passe actuel comme nouveau mot de passe" + +#: Model/Behavior/RegisterBehavior.php:89 msgid "User not found for the given token and email." msgstr "Utilisateur non trouvé pour le jeton et le courriel spécifiés" -#: Model/Behavior/RegisterBehavior.php:91 +#: Model/Behavior/RegisterBehavior.php:92 msgid "Token has already expired user with no token" msgstr "Le jeton a déjà expiré utilisateur sans jeton" -#: Model/Behavior/SocialAccountBehavior.php:101;128 +#: Model/Behavior/SocialAccountBehavior.php:102;129 msgid "Account already validated" msgstr "Compte déjà validé" -#: Model/Behavior/SocialAccountBehavior.php:104;131 +#: Model/Behavior/SocialAccountBehavior.php:105;132 msgid "Account not found for the given token and email." msgstr "Compte non trouvé pour le jeton et le courriel spécifiés" @@ -324,25 +329,25 @@ msgstr "Compte non trouvé pour le jeton et le courriel spécifiés" msgid "Unable to login user with reference {0}" msgstr "Impossible d'identifier l'utilisateur avec la référence {0}" -#: Model/Behavior/SocialBehavior.php:97 +#: Model/Behavior/SocialBehavior.php:98 msgid "Email not present" msgstr "Courriel non présent" -#: Model/Table/UsersTable.php:81 +#: Model/Table/UsersTable.php:82 msgid "Your password does not match your confirm password. Please try again" msgstr "" "Votre mot de passe ne correspond pas à la confirmation de mot de passe. " "Veuillez réessayer" -#: Model/Table/UsersTable.php:159 +#: Model/Table/UsersTable.php:175 msgid "Username already exists" msgstr "Le nom d'utilisateur existe déjà" -#: Model/Table/UsersTable.php:165 +#: Model/Table/UsersTable.php:181 msgid "Email already exists" msgstr "Le courriel existe déjà" -#: Model/Table/UsersTable.php:197 +#: Model/Table/UsersTable.php:214 msgid "Missing 'username' in options data" msgstr "'username' manquant dans les données d'options" @@ -387,83 +392,83 @@ msgstr "Réinitialiser le mot de passe de tous les utilisateurs" msgid "Reset the password for an specific user" msgstr "Réinitialiser le mot de passe pour un utilisateur spécifique" -#: Shell/UsersShell.php:97 +#: Shell/UsersShell.php:98 msgid "User added:" msgstr "Utilisateur ajouté :" -#: Shell/UsersShell.php:98;126 +#: Shell/UsersShell.php:99;127 msgid "Id: {0}" msgstr "Identifiant : {0}" -#: Shell/UsersShell.php:99;127 +#: Shell/UsersShell.php:100;128 msgid "Username: {0}" msgstr "Nom d'utilisateur : {0}" -#: Shell/UsersShell.php:100;128 +#: Shell/UsersShell.php:101;129 msgid "Email: {0}" msgstr "Courriel : {0}" -#: Shell/UsersShell.php:101;129 +#: Shell/UsersShell.php:102;130 msgid "Password: {0}" msgstr "Mot de passe : {0}" -#: Shell/UsersShell.php:125 +#: Shell/UsersShell.php:126 msgid "Superuser added:" msgstr "Super-utilisateur ajouté :" -#: Shell/UsersShell.php:131 +#: Shell/UsersShell.php:132 msgid "Superuser could not be added:" msgstr "Le super-utilisateur n'a pas pu être ajouté :" -#: Shell/UsersShell.php:134 +#: Shell/UsersShell.php:135 msgid "Field: {0} Error: {1}" msgstr "Champ : {0} Erreur : {1}" -#: Shell/UsersShell.php:152;178 +#: Shell/UsersShell.php:153;179 msgid "Please enter a password." msgstr "Veuillez saisir un mot de passe." -#: Shell/UsersShell.php:156 +#: Shell/UsersShell.php:157 msgid "Password changed for all users" msgstr "Mot de passe changé pour tous les utilisateurs" -#: Shell/UsersShell.php:157;185 +#: Shell/UsersShell.php:158;186 msgid "New password: {0}" msgstr "Nouveau mot de passe : {0}" -#: Shell/UsersShell.php:175;203;281;321 +#: Shell/UsersShell.php:176;204;282;324 msgid "Please enter a username." msgstr "Veuillez saisir un nom d'utilisateur." -#: Shell/UsersShell.php:184 +#: Shell/UsersShell.php:185 msgid "Password changed for user: {0}" msgstr "Mot de passe changé pour l'utilisateur : {0}" -#: Shell/UsersShell.php:206 +#: Shell/UsersShell.php:207 msgid "Please enter a role." msgstr "Veuillez saisir un rôle." -#: Shell/UsersShell.php:212 +#: Shell/UsersShell.php:213 msgid "Role changed for user: {0}" msgstr "Rôle changé pour l'utilisateur : {0}" -#: Shell/UsersShell.php:213 +#: Shell/UsersShell.php:214 msgid "New role: {0}" msgstr "Nouveau rôle : {0}" -#: Shell/UsersShell.php:228 +#: Shell/UsersShell.php:229 msgid "User was activated: {0}" msgstr "L'utilisateur a été activé : {0}" -#: Shell/UsersShell.php:243 +#: Shell/UsersShell.php:244 msgid "User was de-activated: {0}" msgstr "L'utilisateur a été désactivé : {0]" -#: Shell/UsersShell.php:255 +#: Shell/UsersShell.php:256 msgid "Please enter a username or email." msgstr "Veuillez saisir un nom d'utilisateur ou un courriel." -#: Shell/UsersShell.php:263 +#: Shell/UsersShell.php:264 msgid "" "Please ask the user to check the email to continue with password reset " "process" @@ -471,15 +476,15 @@ msgstr "" "Veuillez demander à l'utilisateur de vérifier ses courriels pour poursuivre " "la procédure de réinitialisation du mot de passe." -#: Shell/UsersShell.php:300 +#: Shell/UsersShell.php:302 msgid "The user was not found." msgstr "L'utilisateur n'a pas été trouvé." -#: Shell/UsersShell.php:329 +#: Shell/UsersShell.php:332 msgid "The user {0} was not deleted. Please try again" msgstr "L'utilisateur {0} n'a pas été supprimé. Veuillez réessayer" -#: Shell/UsersShell.php:331 +#: Shell/UsersShell.php:334 msgid "The user {0} was deleted successfully" msgstr "L'utilisateur {0} a été supprimé avec succès" @@ -498,8 +503,9 @@ msgstr "Réinitialisez votre mot de passe ici" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 msgid "" -"If the link is not correctly displayed, please copy the following address in " +"If the link is not correcly displayed, please copy the following address in " "your web browser {0}" msgstr "" "Si le lien n'est pas correctement affiché, veuillez copier l'adresse " @@ -522,14 +528,6 @@ msgstr "Activez votre identification sociale ici" msgid "Activate your account here" msgstr "Activez votre compte ici" -#: 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 "" -"Si le lien n'est pas correctement affiché, veuillez copier l'adresse " -"suivante dans votre navigateur web {0}" - #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" @@ -543,18 +541,18 @@ msgstr "" "Veuillez copier l'adresse suivante dans votre navigateur web pour activer " "votre identification sociale {0}" -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:13 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:13;77 +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 msgid "Actions" msgstr "Actions" -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:21 -#: Template/Users/view.ctp:17 +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 +#: Template/Users/view.ctp:19 msgid "List Users" msgstr "Lister les utilisateurs" -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:22 -#: Template/Users/view.ctp:19 +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:21 msgid "List Accounts" msgstr "Lister les comptes" @@ -562,8 +560,35 @@ msgstr "Lister les comptes" msgid "Add User" msgstr "Ajouter un utilisateur" -#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:17 -#: Template/Users/edit.ctp:42 Template/Users/register.ctp:32 +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 +#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Nom d'utilisateur" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "Courriel" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +msgid "First name" +msgstr "Prénom" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Nom" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Actif" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 #: Template/Users/request_reset_password.ctp:8 #: Template/Users/resend_token_validation.ctp:20 #: Template/Users/social_email.ctp:19 @@ -578,25 +603,53 @@ msgstr "Veuillez entrer le nouveau mot de passe" msgid "Current password" msgstr "Mot de passe actuel" -#: Template/Users/edit.ctp:16 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:99 +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Confirmer le mot de passe" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:101 msgid "Delete" msgstr "Supprimer" -#: Template/Users/edit.ctp:18 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:16;99 +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:18;101 msgid "Are you sure you want to delete # {0}?" msgstr "Êtes vous sûr(e) de vouloir supprimler # {0} ?" -#: Template/Users/edit.ctp:28 Template/Users/view.ctp:15 +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 msgid "Edit User" msgstr "Modifier l'utilisateur" +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Jeton" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Expiration du jeton" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "Jeton d'API" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Date d'activiation" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Date CGU" + #: Template/Users/index.ctp:15 msgid "New {0}" msgstr "Nouveau {0}" -#: Template/Users/index.ctp:37 Template/Users/view.ctp:95 +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 msgid "View" msgstr "Voir" @@ -604,7 +657,7 @@ msgstr "Voir" msgid "Change password" msgstr "Changer le mot de passe" -#: Template/Users/index.ctp:39 Template/Users/view.ctp:97 +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 msgid "Edit" msgstr "Modifier" @@ -624,6 +677,14 @@ msgstr "Merci de saisir votre nom d'utilisateur et votre mot de passe" msgid "Remember me" msgstr "Se souvenir de moi" +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "S'inscrire" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Réinitialiser le mot de passe" + #: Template/Users/login.ctp:48 msgid "Login" msgstr "S'identifier" @@ -636,23 +697,15 @@ msgstr "{0} {1}" msgid "Change Password" msgstr "Changer le mot de passe" -#: Template/Users/profile.ctp:27 Template/Users/view.ctp:28;68 -msgid "Username" -msgstr "Nom d'utilisateur" - -#: Template/Users/profile.ctp:29 Template/Users/view.ctp:30 -msgid "Email" -msgstr "Courriel" - #: Template/Users/profile.ctp:34 msgid "Social Accounts" msgstr "Comptes sociaux" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:70 +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 msgid "Avatar" msgstr "Photo de profil" -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:67 +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 msgid "Provider" msgstr "Fournisseur" @@ -664,7 +717,11 @@ msgstr "Lien" msgid "Link to {0}" msgstr "Lier à {0}" -#: Template/Users/register.ctp:25 +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Mot de passe" + +#: Template/Users/register.ctp:28 msgid "Accept TOS conditions?" msgstr "Accepter les CGU ?" @@ -680,71 +737,63 @@ msgstr "Réenvoyer le courriel de validation" msgid "Email or username" msgstr "Courriel ou nom d'utilisateur" -#: Template/Users/view.ctp:16 +#: Template/Users/view.ctp:18 msgid "Delete User" msgstr "Supprimer l'utilisateur" -#: Template/Users/view.ctp:18 +#: Template/Users/view.ctp:20 msgid "New User" msgstr "Nouvel utilisateur" -#: Template/Users/view.ctp:26;65 +#: Template/Users/view.ctp:28;67 msgid "Id" msgstr "Identifiant" -#: Template/Users/view.ctp:32 +#: Template/Users/view.ctp:34 msgid "First Name" msgstr "Prénom" -#: Template/Users/view.ctp:34 +#: Template/Users/view.ctp:36 msgid "Last Name" msgstr "Nom" -#: Template/Users/view.ctp:36;71 -msgid "Token" -msgstr "Jeton" - -#: Template/Users/view.ctp:38 +#: Template/Users/view.ctp:40 msgid "Api Token" msgstr "Jeton d'API" -#: Template/Users/view.ctp:42;73 -msgid "Active" -msgstr "Actif" - -#: Template/Users/view.ctp:46;72 +#: Template/Users/view.ctp:48;74 msgid "Token Expires" msgstr "Expiration du jeton" -#: Template/Users/view.ctp:48 +#: Template/Users/view.ctp:50 msgid "Activation Date" msgstr "Date d'activiation" -#: Template/Users/view.ctp:50 +#: Template/Users/view.ctp:52 msgid "Tos Date" msgstr "Date CGU" -#: Template/Users/view.ctp:52;75 +#: Template/Users/view.ctp:54;77 msgid "Created" msgstr "Créé le" -#: Template/Users/view.ctp:54;76 +#: Template/Users/view.ctp:56;78 msgid "Modified" msgstr "Modifié le" -#: Template/Users/view.ctp:61 +#: Template/Users/view.ctp:63 msgid "Related Accounts" msgstr "Comptes liés" -#: Template/Users/view.ctp:66 +#: Template/Users/view.ctp:68 msgid "User Id" msgstr "Identifiant utilisateur" -#: Template/Users/view.ctp:69 +#: Template/Users/view.ctp:71 msgid "Reference" msgstr "Référence" -#: Template/Users/view.ctp:74 +#: Template/Users/view.ctp:76 msgid "Data" msgstr "Données" @@ -760,19 +809,29 @@ msgstr "fa fa-{0}" msgid "btn btn-social btn-{0} " msgstr "btn btn-social btn-{0} " -#: View/Helper/UserHelper.php:90 +#: View/Helper/UserHelper.php:91 msgid "Logout" msgstr "Se déconnecter" -#: View/Helper/UserHelper.php:139 +#: View/Helper/UserHelper.php:108 msgid "Welcome, {0}" msgstr "Bienvenue, {0}" -#: View/Helper/UserHelper.php:161 +#: View/Helper/UserHelper.php:131 msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" msgstr "" "reCaptcha n'est pas configuré ! Veuillez configurer Users.reCaptcha.key" -#: Model/Behavior/RegisterBehavior.php:147 +#: Model/Behavior/RegisterBehavior.php:148 msgid "This field is required" msgstr "Ce champ est requis" + +#~ msgid "The old password does not match" +#~ msgstr "L'ancien mot de passe ne correspond pas" + +#~ msgid "" +#~ "If the link is not correctly displayed, please copy the following address " +#~ "in your web browser {0}" +#~ msgstr "" +#~ "Si le lien n'est pas correctement affiché, veuillez copier l'adresse " +#~ "suivante dans votre navigateur web {0}" From 109ea1b2aba81a0e4d0cb06016ec550d223bd56b Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 31 Mar 2017 08:49:42 -0500 Subject: [PATCH 0617/1476] Updating link to configuration file --- 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 d303fc9dd..7d043f5c1 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -19,7 +19,7 @@ composer require league/oauth1-client:@stable ``` NOTE: you'll need to enable social login in your bootstrap.php file if you want to use it, social -login is disabled by default. Check the [Configuration](Configuration.md) page for more details. +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 From c031b16cf77679c11601a0a92c6573393314eafe Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 31 Mar 2017 10:09:34 -0500 Subject: [PATCH 0618/1476] Fixing Exception when the only provider enabled is twitter --- src/Auth/SocialAuthenticate.php | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 619575efb..9095ab82d 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -27,9 +27,9 @@ use Cake\Event\Event; use Cake\Event\EventDispatcherTrait; use Cake\Event\EventManager; +use Cake\Http\Response; use Cake\Http\ServerRequest; use Cake\Log\LogTrait; -use Cake\Network\Response; use Cake\ORM\TableRegistry; use Cake\Utility\Hash; use League\OAuth2\Client\Provider\AbstractProvider; @@ -60,19 +60,19 @@ class SocialAuthenticate extends BaseAuthenticate public function __construct(ComponentRegistry $registry, array $config = []) { $oauthConfig = Configure::read('OAuth'); + $enabledNoOAuth2Provider = $this->_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 (!empty($options['options']['redirectUri']) && - !empty($options['options']['clientId']) && - !empty($options['options']['clientSecret'])) { + if ($this->_isProviderEnable($options)) { $providers[$provider] = $options; } } $oauthConfig['providers'] = $providers; Configure::write('OAuth2', $oauthConfig); - $config = $this->normalizeConfig(array_merge($config, $oauthConfig)); + $config = $this->normalizeConfig(array_merge($config, $oauthConfig), $enabledNoOAuth2Provider); parent::__construct($registry, $config); } @@ -80,14 +80,15 @@ public function __construct(ComponentRegistry $registry, array $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) + public function normalizeConfig(array $config, $enabledNoOAuth2Provider = false) { $config = Hash::merge((array)Configure::read('OAuth2'), $config); - if (empty($config['providers'])) { + if (empty($config['providers']) && !$enabledNoOAuth2Provider) { throw new MissingProviderConfigurationException(); } @@ -157,11 +158,24 @@ protected function _getController() return $this->_registry->getController(); } + + /** + * Returns when a provider has been enabled. + * + * @param $options + * @return \Cake\Controller\Controller Controller instance + */ + 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\Network\Response $response Response object. + * @param \Cake\Http\Response $response Response object. * @return bool * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. */ From f2f7fb97b1a366907e1a46cf68e0661deac7f4f5 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 31 Mar 2017 11:18:46 -0500 Subject: [PATCH 0619/1476] Adding unit tests for SocialAuthenticate::normalizeConfig --- src/Auth/SocialAuthenticate.php | 4 +- .../TestCase/Auth/SocialAuthenticateTest.php | 107 ++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 9095ab82d..e208caf91 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -92,7 +92,9 @@ public function normalizeConfig(array $config, $enabledNoOAuth2Provider = false) throw new MissingProviderConfigurationException(); } - array_walk($config['providers'], [$this, '_normalizeConfig'], $config); + if (!empty($config['providers'])) { + array_walk($config['providers'], [$this, '_normalizeConfig'], $config); + } return $config; } diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index be7ad5cd7..fdd23c091 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use Cake\Core\Configure; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -482,4 +483,110 @@ public function testMapUserException() $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 + ] + ]; + } } From d5f457db94db5849cb1dcaabef88e2478adbfddb Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 31 Mar 2017 11:28:01 -0500 Subject: [PATCH 0620/1476] Fix CS --- src/Auth/SocialAuthenticate.php | 5 ++--- tests/TestCase/Auth/SocialAuthenticateTest.php | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index e208caf91..18db5bee8 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -160,12 +160,11 @@ protected function _getController() return $this->_registry->getController(); } - /** * Returns when a provider has been enabled. * - * @param $options - * @return \Cake\Controller\Controller Controller instance + * @param array $options array of options by provider + * @return bool */ protected function _isProviderEnabled($options) { diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index fdd23c091..efbbdf213 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Test\TestCase\Auth; -use Cake\Core\Configure; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; use Cake\Controller\ComponentRegistry; +use Cake\Core\Configure; use Cake\Event\Event; use Cake\Http\ServerRequest; use Cake\Network\Request; From 7a488022a582cb75bc95d5cf410955454b4b40d3 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 31 Mar 2017 16:13:36 -0500 Subject: [PATCH 0621/1476] Improve unit test coverage --- src/Auth/ApiKeyAuthenticate.php | 6 + .../Exception/InvalidProviderException.php | 11 + .../Exception/InvalidSettingsException.php | 11 + .../MissingEventListenerException.php | 11 + .../MissingProviderConfigurationException.php | 11 + .../AccountAlreadyActiveException.php | 10 + src/Exception/AccountNotActiveException.php | 11 + src/Exception/BadConfigurationException.php | 10 + src/Exception/MissingEmailException.php | 10 + src/Exception/MissingProviderException.php | 10 + src/Exception/TokenExpiredException.php | 10 + src/Exception/UserAlreadyActiveException.php | 10 + src/Exception/UserNotActiveException.php | 10 + src/Exception/UserNotFoundException.php | 10 + src/Exception/WrongPasswordException.php | 11 +- .../TestCase/Auth/ApiKeyAuthenticateTest.php | 244 ++++ .../InvalidProviderExceptionTest.php | 46 + .../InvalidSettingsExceptionTest.php | 46 + .../MissingEventListenerExceptionTest.php | 45 + ...singProviderConfigurationExceptionTest.php | 46 + .../Auth/RememberMeAuthenticateTest.php | 168 +++ tests/TestCase/Auth/Rules/OwnerTest.php | 254 ++++ .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 1201 +++++++++++++++++ .../Auth/Social/Mapper/FacebookTest.php | 91 ++ .../Auth/Social/Mapper/GoogleTest.php | 73 + .../Auth/Social/Mapper/InstagramTest.php | 72 + .../Auth/Social/Mapper/LinkedInTest.php | 75 + .../Auth/Social/Mapper/TwitterTest.php | 71 + .../TestCase/Auth/SuperuserAuthorizeTest.php | 90 ++ .../Controller/Traits/RecaptchaTraitTest.php | 27 + .../AccountAlreadyActiveExceptionTest.php | 43 + .../AccountNotActiveExceptionTest.php | 45 + .../BadConfigurationExceptionTest.php | 43 + .../Exception/MissingEmailExceptionTest.php | 43 + .../MissingProviderExceptionTest.php | 43 + .../Exception/TokenExpiredExceptionTest.php | 43 + .../UserAlreadyActiveExceptionTest.php | 43 + .../Exception/UserNotActiveExceptionTest.php | 43 + .../Exception/UserNotFoundExceptionTest.php | 43 + .../Exception/WrongPasswordExceptionTest.php | 43 + 40 files changed, 3132 insertions(+), 1 deletion(-) create mode 100644 tests/TestCase/Auth/ApiKeyAuthenticateTest.php create mode 100644 tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php create mode 100644 tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php create mode 100644 tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php create mode 100644 tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php create mode 100644 tests/TestCase/Auth/RememberMeAuthenticateTest.php create mode 100644 tests/TestCase/Auth/Rules/OwnerTest.php create mode 100644 tests/TestCase/Auth/SimpleRbacAuthorizeTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/FacebookTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/GoogleTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/InstagramTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/LinkedInTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/TwitterTest.php create mode 100644 tests/TestCase/Auth/SuperuserAuthorizeTest.php create mode 100644 tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/AccountNotActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/BadConfigurationExceptionTest.php create mode 100644 tests/TestCase/Exception/MissingEmailExceptionTest.php create mode 100644 tests/TestCase/Exception/MissingProviderExceptionTest.php create mode 100644 tests/TestCase/Exception/TokenExpiredExceptionTest.php create mode 100644 tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/UserNotActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/UserNotFoundExceptionTest.php create mode 100644 tests/TestCase/Exception/WrongPasswordExceptionTest.php diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index cebc65626..142e546f5 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Auth; use Cake\Auth\BaseAuthenticate; +use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\Network\Exception\ForbiddenException; @@ -44,6 +45,11 @@ class ApiKeyAuthenticate extends BaseAuthenticate 'finder' => null, ]; + public function __construct(ComponentRegistry $registry, array $config = []) + { + parent::__construct($registry, $config); + } + /** * Authenticate callback * Reads the API Key based on configuration and login the user diff --git a/src/Auth/Exception/InvalidProviderException.php b/src/Auth/Exception/InvalidProviderException.php index 551def282..04bd49a4f 100644 --- a/src/Auth/Exception/InvalidProviderException.php +++ b/src/Auth/Exception/InvalidProviderException.php @@ -17,4 +17,15 @@ class InvalidProviderException extends Exception { protected $_messageTemplate = 'Invalid provider or missing class (%s)'; protected $code = 500; + + /** + * InvalidProviderException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Auth/Exception/InvalidSettingsException.php b/src/Auth/Exception/InvalidSettingsException.php index df4de7c77..343ba3e8b 100644 --- a/src/Auth/Exception/InvalidSettingsException.php +++ b/src/Auth/Exception/InvalidSettingsException.php @@ -17,4 +17,15 @@ class InvalidSettingsException extends Exception { protected $_messageTemplate = 'Invalid settings for key (%s)'; protected $code = 500; + + /** + * InvalidSettingsException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Auth/Exception/MissingEventListenerException.php b/src/Auth/Exception/MissingEventListenerException.php index 94286a60c..b69f3ac69 100644 --- a/src/Auth/Exception/MissingEventListenerException.php +++ b/src/Auth/Exception/MissingEventListenerException.php @@ -16,4 +16,15 @@ class MissingEventListenerException extends Exception { protected $_messageTemplate = 'Missing listener to the (%s) event.'; + + /** + * MissingEventListenerException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Auth/Exception/MissingProviderConfigurationException.php b/src/Auth/Exception/MissingProviderConfigurationException.php index 9d6092703..c1f2d944d 100644 --- a/src/Auth/Exception/MissingProviderConfigurationException.php +++ b/src/Auth/Exception/MissingProviderConfigurationException.php @@ -17,4 +17,15 @@ class MissingProviderConfigurationException extends Exception { protected $_messageTemplate = 'No OAuth providers configured.'; protected $code = 500; + + /** + * MissingProviderConfigurationException constructor. + * @param string $message + * @param int $code + * @param null $previous + */ + public function __construct($message = null, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/AccountAlreadyActiveException.php b/src/Exception/AccountAlreadyActiveException.php index 19e524020..95b38eb9b 100644 --- a/src/Exception/AccountAlreadyActiveException.php +++ b/src/Exception/AccountAlreadyActiveException.php @@ -15,4 +15,14 @@ class AccountAlreadyActiveException extends Exception { + /** + * AccountAlreadyActiveException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/AccountNotActiveException.php b/src/Exception/AccountNotActiveException.php index 8439217e5..02b09a0ed 100644 --- a/src/Exception/AccountNotActiveException.php +++ b/src/Exception/AccountNotActiveException.php @@ -16,4 +16,15 @@ class AccountNotActiveException extends Exception { protected $_messageTemplate = '/a/validate/%s/%s'; + + /** + * AccountNotActiveException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/BadConfigurationException.php b/src/Exception/BadConfigurationException.php index 089658773..70ba43de3 100644 --- a/src/Exception/BadConfigurationException.php +++ b/src/Exception/BadConfigurationException.php @@ -15,4 +15,14 @@ class BadConfigurationException extends Exception { + /** + * BadConfigurationException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/MissingEmailException.php b/src/Exception/MissingEmailException.php index cd21a5902..8f7432b1c 100644 --- a/src/Exception/MissingEmailException.php +++ b/src/Exception/MissingEmailException.php @@ -15,4 +15,14 @@ class MissingEmailException extends Exception { + /** + * MissingEmailException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/MissingProviderException.php b/src/Exception/MissingProviderException.php index 8c1a9163d..c908c55f7 100644 --- a/src/Exception/MissingProviderException.php +++ b/src/Exception/MissingProviderException.php @@ -15,4 +15,14 @@ class MissingProviderException extends Exception { + /** + * MissingProviderException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/TokenExpiredException.php b/src/Exception/TokenExpiredException.php index 877502194..24b333730 100644 --- a/src/Exception/TokenExpiredException.php +++ b/src/Exception/TokenExpiredException.php @@ -15,4 +15,14 @@ class TokenExpiredException extends Exception { + /** + * TokenExpiredException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/UserAlreadyActiveException.php b/src/Exception/UserAlreadyActiveException.php index 2387879de..7e33e0da3 100644 --- a/src/Exception/UserAlreadyActiveException.php +++ b/src/Exception/UserAlreadyActiveException.php @@ -15,4 +15,14 @@ class UserAlreadyActiveException extends Exception { + /** + * UserAlreadyActiveException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/UserNotActiveException.php b/src/Exception/UserNotActiveException.php index 93d16133c..380ab5c35 100644 --- a/src/Exception/UserNotActiveException.php +++ b/src/Exception/UserNotActiveException.php @@ -15,4 +15,14 @@ class UserNotActiveException extends Exception { + /** + * UserNotActiveException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/UserNotFoundException.php b/src/Exception/UserNotFoundException.php index 7a119f2ec..a1ff18aeb 100644 --- a/src/Exception/UserNotFoundException.php +++ b/src/Exception/UserNotFoundException.php @@ -15,4 +15,14 @@ class UserNotFoundException extends RecordNotFoundException { + /** + * UserNotFoundException constructor. + * @param string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/src/Exception/WrongPasswordException.php b/src/Exception/WrongPasswordException.php index f5e643a9d..71c56fe9a 100644 --- a/src/Exception/WrongPasswordException.php +++ b/src/Exception/WrongPasswordException.php @@ -15,5 +15,14 @@ class WrongPasswordException extends Exception { - + /** + * WrongPasswordException constructor. + * @param array|string $message + * @param int $code + * @param null $previous + */ + public function __construct($message, $code = 500, $previous = null) + { + parent::__construct($message, $code, $previous); + } } diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php new file mode 100644 index 000000000..0c7562582 --- /dev/null +++ b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php @@ -0,0 +1,244 @@ +getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); + $registry = new ComponentRegistry($controller); + $this->apiKey = new ApiKeyAuthenticate($registry, [ + 'finder' => 'all', + 'require_ssl' => false]); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->apiKey, $this->controller); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHappy() + { + $request = new ServerRequest('/?api_key=xxx'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertEquals('user-2', $result['username']); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateFail() + { + $request = new ServerRequest('/'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + + $request = new ServerRequest('/?api_key=none'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + + $request = new ServerRequest('/?api_key='); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Type wrong is not valid + * + */ + public function testAuthenticateWrongType() + { + $this->apiKey->setConfig('type', 'wrong'); + $request = new ServerRequest('/'); + $this->apiKey->authenticate($request, new Response()); + } + + /** + * test + * + * @expectedException \Cake\Network\Exception\ForbiddenException + * @expectedExceptionMessage SSL is required for ApiKey Authentication + * + */ + public function testAuthenticateRequireSSL() + { + $this->apiKey->setConfig('require_ssl', true); + $request = new ServerRequest('/?api_key=test'); + $this->apiKey->authenticate($request, new Response()); + } + + /** + * test + * + */ + public function testAuthenticateRequireSSLNoKey() + { + $this->apiKey->setConfig('require_ssl', true); + $request = new ServerRequest('/'); + $this->assertFalse($this->apiKey->authenticate($request, new Response())); + } + + /** + * test + * + * @return void + */ + public function testHeaderHappy() + { + $request = $this->getMockBuilder('\Cake\Http\ServerRequest') + ->setMethods(['getHeader', 'getHeaderLine']) + ->getMock(); + $request->expects($this->at(0)) + ->method('getHeader') + ->with('api_key') + ->will($this->returnValue(['xxx'])); + $request->expects($this->at(1)) + ->method('getHeaderLine') + ->with('api_key') + ->will($this->returnValue('xxx')); + $this->apiKey->setConfig('type', 'header'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertEquals('user-2', $result['username']); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHeaderFail() + { + $request = $this->getMockBuilder('\Cake\Http\ServerRequest') + ->setMethods(['getHeader', 'getHeaderLine']) + ->getMock(); + $request->expects($this->at(0)) + ->method('getHeader') + ->with('api_key') + ->will($this->returnValue(['wrong'])); + $request->expects($this->at(1)) + ->method('getHeaderLine') + ->with('api_key') + ->will($this->returnValue('wrong')); + $this->apiKey->setConfig('type', 'header'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHeaderNotPresent() + { + $request = $this->getMockBuilder('\Cake\Http\ServerRequest') + ->setMethods(['getHeader']) + ->getMock(); + $request->expects($this->once()) + ->method('getHeader') + ->with('api_key') + ->will($this->returnValue([])); + $this->apiKey->setConfig('type', 'header'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateFinderConfig() + { + $this->apiKey->setConfig('finder', 'undefinedInConfig'); + $request = new ServerRequest('/?api_key=xxx'); + try { + $result = $this->apiKey->authenticate($request, new Response()); + $this->fail(); + } catch (\Exception $ex) { + $this->assertEquals('Unknown finder method "undefinedInConfig"', $ex->getMessage()); + } + } + + /** + * test + * + * @return void + */ + public function testAuthenticateFinderAuthConfig() + { + Configure::write('Auth.authenticate.all.finder', 'undefinedFinderInAuth'); + $this->apiKey->setConfig('finder', null); + $request = new ServerRequest('/?api_key=xxx'); + try { + $result = $this->apiKey->authenticate($request, new Response()); + $this->fail(); + } catch (\Exception $ex) { + $this->assertEquals('Unknown finder method "undefinedFinderInAuth"', $ex->getMessage()); + } + } + + /** + * test + * + * @return void + */ + public function testAuthenticateDefaultAllFinder() + { + Configure::write('Auth.authenticate.all.finder', null); + $request = new ServerRequest('/?api_key=yyy'); + $result = $this->apiKey->authenticate($request, new Response()); + $this->assertEquals('user-1', $result['username']); + } +} diff --git a/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php new file mode 100644 index 000000000..d29960b3f --- /dev/null +++ b/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php @@ -0,0 +1,46 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php new file mode 100644 index 000000000..40725f863 --- /dev/null +++ b/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php @@ -0,0 +1,46 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php b/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php new file mode 100644 index 000000000..3795a4885 --- /dev/null +++ b/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php @@ -0,0 +1,45 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php b/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php new file mode 100644 index 000000000..4d7515a25 --- /dev/null +++ b/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php @@ -0,0 +1,46 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php new file mode 100644 index 000000000..a31eb7782 --- /dev/null +++ b/tests/TestCase/Auth/RememberMeAuthenticateTest.php @@ -0,0 +1,168 @@ +controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); + $registry = new ComponentRegistry($this->controller); + $this->rememberMe = new RememberMeAuthenticate($registry); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->rememberMe, $this->controller); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateHappy() + { + $request = new ServerRequest('/'); + $request = $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('read') + ->with('remember_me') + ->will($this->returnValue([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_agent' => 'user-agent' + ])); + $registry = new ComponentRegistry($this->controller); + $this->controller->Cookie = $mockCookie; + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertEquals('user-1', $result['username']); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateBadUser() + { + $request = new ServerRequest('/'); + $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('read') + ->with('remember_me') + ->will($this->returnValue([ + //bad-user + 'id' => '00000000-0000-0000-0000-000000000000', + 'user_agent' => 'user-agent' + ])); + $registry = new ComponentRegistry($this->controller); + $this->controller->Cookie = $mockCookie; + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateBadAgent() + { + $request = new ServerRequest('/'); + $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('read') + ->with('remember_me') + ->will($this->returnValue([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_agent' => 'bad-agent' + ])); + $registry = new ComponentRegistry($this->controller); + $this->controller->Cookie = $mockCookie; + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testAuthenticateNoCookie() + { + $request = new ServerRequest('/'); + $request->env('HTTP_USER_AGENT', 'user-agent'); + $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->disableOriginalConstructor() + ->setMethods(['check', 'read']) + ->getMock(); + $mockCookie + ->expects($this->once()) + ->method('read') + ->with('remember_me') + ->will($this->returnValue(null)); + + $registry = new ComponentRegistry($this->controller); + $this->controller->Cookie = $mockCookie; + $this->rememberMe = new RememberMeAuthenticate($registry); + $result = $this->rememberMe->authenticate($request, new Response()); + $this->assertFalse($result); + } +} diff --git a/tests/TestCase/Auth/Rules/OwnerTest.php b/tests/TestCase/Auth/Rules/OwnerTest.php new file mode 100644 index 000000000..a7384c5a0 --- /dev/null +++ b/tests/TestCase/Auth/Rules/OwnerTest.php @@ -0,0 +1,254 @@ +Owner = new Owner(); + $this->request = new ServerRequest(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->Owner); + } + + /** + * test + * + * @return void + */ + public function testAllowed() + { + $this->request = $this->request + ->withParam('plugin', 'CakeDC/Users') + ->withParam('controller', 'Posts') + ->withParam('pass', ['00000000-0000-0000-0000-000000000001']); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testAllowedUsingTableAlias() + { + $this->Owner = new Owner([ + 'table' => 'Posts' + ]); + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testAllowedUsingTableInstance() + { + $this->Owner = new Owner([ + 'table' => TableRegistry::get('CakeDC/Users.Posts'), + ]); + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Missing Table alias, we could not extract a default table from the request + */ + public function testAllowedShouldThrowExceptionBecauseEmptyAliasFromRequest() + { + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->Owner->allowed($user, 'user', $this->request); + } + + /** + * test + * + * @return void + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Missing column column_not_found in table Posts while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 + */ + public function testAllowedShouldThrowExceptionBecauseForeignKeyNotPresentInTable() + { + $this->Owner = new Owner([ + 'table' => TableRegistry::get('CakeDC/Users.Posts'), + 'ownerForeignKey' => 'column_not_found', + ]); + $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->Owner->allowed($user, 'user', $this->request); + } + + /** + * test + * + * @return void + */ + public function testNotAllowedBecauseNotOwner() + { + $this->request = $this->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Posts', + 'pass' => ['00000000-0000-0000-0000-000000000002'] + ]); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testNotAllowedBecauseUserNotFound() + { + $this->request = $this->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Posts', + 'pass' => ['00000000-0000-0000-0000-000000000002'] + ]); + $user = [ + 'id' => '99999999-0000-0000-0000-000000000000', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + */ + public function testNotAllowedBecausePostNotFound() + { + $this->request = $this->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Posts', + 'pass' => ['99999999-0000-0000-0000-000000000000'] //not found + ]); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * test + * + * @return void + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Missing column user_id in table NoDefaultTable while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 + */ + public function testNotAllowedBecauseNoDefaultTable() + { + $this->request = $this->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'NoDefaultTable', + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * Test using the Owner rule in a belongsToMany association + * Posts belongsToMany Users + * @return void + */ + public function testAllowedBelongsToMany() + { + $this->Owner = new Owner([ + 'table' => 'PostsUsers', + 'id' => 'post_id', + ]); + $this->request = $this->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'IsNotUsed', + 'pass' => ['00000000-0000-0000-0000-000000000001'] + ]); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); + } + + /** + * Test using the Owner rule in a belongsToMany association + * Posts belongsToMany Users + * @return void + */ + public function testNotAllowedBelongsToMany() + { + $this->Owner = new Owner([ + 'table' => 'PostsUsers', + 'id' => 'post_id', + ]); + $this->request = $this->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'IsNotUsed', + 'pass' => ['00000000-0000-0000-0000-000000000002'] + ]); + $user = [ + 'id' => '00000000-0000-0000-0000-000000000001', + ]; + $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); + } +} diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php new file mode 100644 index 000000000..36c89e15c --- /dev/null +++ b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php @@ -0,0 +1,1201 @@ + 'admin', + 'plugin' => '*', + 'controller' => '*', + 'action' => '*', + ], + //specific actions allowed for the user role in Users plugin + [ + 'role' => 'user', + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => ['profile', 'logout'], + ], + //all roles allowed to Pages/display + [ + 'role' => '*', + 'plugin' => null, + 'controller' => ['Pages'], + 'action' => ['display'], + ], + ]; + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + public function setUp() + { + $request = new ServerRequest(); + $response = new Response(); + + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); + $this->registry = new ComponentRegistry($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->simpleRbacAuthorize, $this->controller); + } + + /** + * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct + */ + public function testConstruct() + { + //don't autoload config + $this->simpleRbacAuthorize = new SimpleRbacAuthorize($this->registry, ['autoload_config' => false]); + $this->assertEmpty($this->simpleRbacAuthorize->getConfig('permissions')); + } + + /** + * test + * + * @return void + */ + public function testLoadPermissions() + { + $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') + ->disableOriginalConstructor() + ->getMock(); + $reflectedClass = new ReflectionClass($this->simpleRbacAuthorize); + $loadPermissions = $reflectedClass->getMethod('_loadPermissions'); + $loadPermissions->setAccessible(true); + $permissions = $loadPermissions->invoke($this->simpleRbacAuthorize, 'missing'); + $this->assertEquals($this->defaultPermissions, $permissions); + } + + /** + * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct + */ + public function testConstructMissingPermissionsFile() + { + $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') + ->setMethods(null) + ->setConstructorArgs([$this->registry, ['autoload_config' => 'does-not-exist']]) + ->getMock(); + //we should have the default permissions + $this->assertEquals($this->defaultPermissions, $this->simpleRbacAuthorize->getConfig('permissions')); + } + + protected function assertConstructorPermissions($instance, $config, $permissions) + { + $reflectedClass = new ReflectionClass($instance); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($this->simpleRbacAuthorize, $this->registry, $config); + + //we should have the default permissions + $resultPermissions = $this->simpleRbacAuthorize->getConfig('permissions'); + $this->assertEquals($permissions, $resultPermissions); + } + + /** + * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct + */ + public function testConstructPermissionsFileHappy() + { + $permissions = [ + [ + 'controller' => 'Test', + 'action' => 'test' + ] + ]; + $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; + $this->simpleRbacAuthorize = $this->getMockBuilder($className) + ->setMethods(['_loadPermissions']) + ->disableOriginalConstructor() + ->getMock(); + $this->simpleRbacAuthorize + ->expects($this->once()) + ->method('_loadPermissions') + ->with('permissions-happy') + ->will($this->returnValue($permissions)); + $this->assertConstructorPermissions($className, ['autoload_config' => 'permissions-happy'], $permissions); + } + + protected function preparePermissions($permissions) + { + $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; + $simpleRbacAuthorize = $this->getMockBuilder($className) + ->setMethods(['_loadPermissions']) + ->disableOriginalConstructor() + ->getMock(); + $simpleRbacAuthorize->config('permissions', $permissions); + + return $simpleRbacAuthorize; + } + + /** + * @dataProvider providerAuthorize + */ + public function testAuthorize($permissions, $user, $requestParams, $expected, $msg = null) + { + $this->simpleRbacAuthorize = $this->preparePermissions($permissions); + $request = $this->_requestFromArray($requestParams); + + $result = $this->simpleRbacAuthorize->authorize($user, $request); + $this->assertSame($expected, $result, $msg); + } + + public function providerAuthorize() + { + $trueRuleMock = $this->getMockBuilder(Rule::class) + ->setMethods(['allowed']) + ->getMock(); + $trueRuleMock->expects($this->any()) + ->method('allowed') + ->willReturn(true); + + return [ + 'discard-first' => [ + //permissions + [ + [ + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'three', // Discard here + function () { + throw new \Exception(); + } + ], + [ + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ], + ], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'deny-first-discard-after' => [ + //permissions + [ + [ + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'one', + 'allowed' => function () { + return false; // Deny here since under 'allowed' key + } + ], + [ + // This permission isn't evaluated + function () { + throw new \Exception(); + }, + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ], + ], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + 'star-invert' => [ + //permissions + [[ + '*plugin' => 'Tests', + '*role' => 'test', + '*controller' => 'Tests', + '*action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'something', + ], + //request + [ + 'plugin' => 'something', + 'controller' => 'something', + 'action' => 'something' + ], + //expected + true + ], + 'star-invert-deny' => [ + //permissions + [[ + '*plugin' => 'Tests', + '*role' => 'test', + '*controller' => 'Tests', + '*action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'something', + ], + //request + [ + 'plugin' => 'something', + 'controller' => 'something', + 'action' => 'test' + ], + //expected + false + ], + 'user-arr' => [ + //permissions + [ + [ + 'username' => 'luke', + 'user.id' => 1, + 'profile.id' => 256, + 'user.profile.signature' => "Hi I'm luke", + 'user.allowed' => false, + 'controller' => 'Tests', + 'action' => 'one' + ], + ], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + 'profile' => [ + 'id' => 256, + 'signature' => "Hi I'm luke" + ], + 'allowed' => false + ], + //request + [ + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'evaluate-order' => [ + //permissions + [ + [ + 'allowed' => false, + function () { + throw new \Exception(); + }, + 'controller' => 'Tests', + 'action' => 'one' + ], + ], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + 'multiple-callables' => [ + //permissions + [ + [ + function () { + return true; + }, + clone $trueRuleMock, + function () { + return true; + }, + 'controller' => 'Tests', + 'action' => 'one' + ], + ], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'happy-strict-all' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + 'allowed' => true, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-strict-all-deny' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + false + ], + 'happy-plugin-null-allowed-null' => [ + //permissions + [[ + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => null, + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-plugin-asterisk' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Any', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-plugin-asterisk-main-app' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => null, + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-role-asterisk' => [ + //permissions + [[ + 'role' => '*', + 'controller' => 'Tests', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'any-role', + ], + //request + [ + 'plugin' => null, + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-controller-asterisk' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => '*', + 'action' => 'test', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + true + ], + 'happy-action-asterisk' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => '*', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'any' + ], + //expected + true + ], + 'happy-some-asterisk-allowed' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => '*', + 'action' => '*', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'any' + ], + //expected + true + ], + 'happy-some-asterisk-deny' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => 'test', + 'controller' => '*', + 'action' => '*', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'any' + ], + //expected + false + ], + 'all-deny' => [ + //permissions + [[ + 'plugin' => '*', + 'role' => '*', + 'controller' => '*', + 'action' => '*', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Any', + 'controller' => 'Any', + 'action' => 'any' + ], + //expected + false + ], + 'dasherized' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'TestTests', + 'action' => 'TestAction', + 'allowed' => true, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'tests', + 'controller' => 'test-tests', + 'action' => 'test-action' + ], + //expected + true + ], + 'happy-array' => [ + //permissions + [[ + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'happy-array-deny' => [ + //permissions + [[ + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'three' + ], + //expected + false + ], + 'happy-callback-check-params' => [ + //permissions + [[ + 'plugin' => ['Tests'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + 'allowed' => function ($user, $role, $request) { + return $user['id'] === 1 && $role = 'test' && $request->plugin == 'Tests'; + } + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'happy-callback-deny' => [ + //permissions + [[ + 'plugin' => ['*'], + 'role' => ['test'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + 'allowed' => function ($user, $role, $request) { + return false; + } + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + 'happy-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['admin'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'deny-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['admin'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + 'star-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => '*', + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'array-prefix' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['one', 'admin'], + 'controller' => '*', + 'action' => '*', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'array-prefix-deny' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['one', 'admin'], + 'controller' => '*', + 'action' => 'one', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + 'happy-ext' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => ['admin'], + 'extension' => ['csv'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + '_ext' => 'csv', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'deny-ext' => [ + //permissions + [[ + 'role' => ['test'], + 'extension' => ['csv'], + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'controller' => 'Tests', + '_ext' => 'csv', + 'action' => 'one' + ], + //expected + false + ], + 'star-ext' => [ + //permissions + [[ + 'role' => ['test'], + 'prefix' => '*', + 'extension' => '*', + 'controller' => ['Tests'], + 'action' => ['one', 'two'], + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'admin', + '_ext' => 'other', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'array-ext' => [ + //permissions + [[ + 'role' => ['test'], + 'extension' => ['csv', 'pdf'], + 'controller' => '*', + 'action' => '*', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + '_ext' => 'csv', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + 'array-ext-deny' => [ + //permissions + [[ + 'role' => ['test'], + 'extension' => ['csv', 'docx'], + 'controller' => '*', + 'action' => 'one', + 'allowed' => false, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'prefix' => 'csv', + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + false + ], + 'rule-class' => [ + //permissions + [ + [ + 'role' => ['test'], + 'controller' => '*', + 'action' => 'one', + 'allowed' => $trueRuleMock, + ], + ], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'controller' => 'Tests', + 'action' => 'one' + ], + //expected + true + ], + ]; + } + + /** + * @dataProvider badPermissionProvider + * + * @param array $permissions + * @param array $user + * @param array $requestParams + * @param string $expectedMsg + */ + public function testBadPermission($permissions, $user, $requestParams, $expectedMsg) + { + $simpleRbacAuthorize = $this->getMockBuilder(SimpleRbacAuthorize::class) + ->setMethods(['_loadPermissions', 'log']) + ->disableOriginalConstructor() + ->getMock(); + $simpleRbacAuthorize + ->expects($this->once()) + ->method('log') + ->with($expectedMsg, LogLevel::DEBUG); + + $simpleRbacAuthorize->config('permissions', $permissions); + $request = $this->_requestFromArray($requestParams); + + $simpleRbacAuthorize->authorize($user, $request); + } + + public function badPermissionProvider() + { + return [ + 'no-controller' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + //'controller' => 'Tests', + 'action' => 'test', + 'allowed' => true, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), + ], + 'no-action' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + //'action' => 'test', + 'allowed' => true, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), + ], + 'no-controller-and-action' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + //'controller' => 'Tests', + //'action' => 'test', + 'allowed' => true, + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), + ], + 'no-controller and user-key' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + //'controller' => 'Tests', + 'action' => 'test', + 'allowed' => true, + 'user' => 'something', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), + ], + 'user-key' => [ + //permissions + [[ + 'plugin' => 'Tests', + 'role' => 'test', + 'controller' => 'Tests', + 'action' => 'test', + 'allowed' => true, + 'user' => 'something', + ]], + //user + [ + 'id' => 1, + 'username' => 'luke', + 'role' => 'test', + ], + //request + [ + 'plugin' => 'Tests', + 'controller' => 'Tests', + 'action' => 'test' + ], + //expected + __d('CakeDC/Users', "Permission key 'user' is illegal, cannot evaluate the permission"), + ], + ]; + } + + /** + * @param array $params + * @return ServerRequest + */ + protected function _requestFromArray($params) + { + $request = new ServerRequest(); + + return $request + ->withParam('plugin', Hash::get($params, 'plugin')) + ->withParam('controller', Hash::get($params, 'controller')) + ->withParam('action', Hash::get($params, 'action')) + ->withParam('prefix', Hash::get($params, 'prefix')) + ->withParam('_ext', Hash::get($params, '_ext')); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php b/tests/TestCase/Auth/Social/Mapper/FacebookTest.php new file mode 100644 index 000000000..ff72c5a74 --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/FacebookTest.php @@ -0,0 +1,91 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'hometown' => [ + 'id' => '108226049197930', + 'name' => 'Madrid' + ], + 'picture' => [ + 'data' => [ + 'url' => 'https://scontent.xx.fbcdn.net/v/test.jpg', + 'is_silhouette' => false + ] + ], + 'cover' => [ + 'source' => 'https://scontent.xx.fbcdn.net/v/test.jpg', + 'id' => '1' + ], + 'gender' => 'male', + 'locale' => 'en_US', + 'link' => 'https://www.facebook.com/app_scoped_user_id/1/', + 'timezone' => (int) -5, + 'age_range' => [ + 'min' => (int) 21 + ], + 'bio' => 'I am the best test user in the world.', + 'picture_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg', + 'is_silhouette' => false, + 'cover_photo_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg' + ]; + $providerMapper = new Facebook($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => null, + 'full_name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'avatar' => 'https://graph.facebook.com/1/picture?type=large', + 'gender' => 'male', + 'link' => 'https://www.facebook.com/app_scoped_user_id/1/', + 'bio' => 'I am the best test user in the world.', + 'locale' => 'en_US', + 'validated' => true, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php b/tests/TestCase/Auth/Social/Mapper/GoogleTest.php new file mode 100644 index 000000000..7e78af431 --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/GoogleTest.php @@ -0,0 +1,73 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'emails' => [['value' => 'test@gmail.com']], + 'id' => '1', + 'displayName' => 'Test User', + 'name' => [ + 'familyName' => 'User', + 'givenName' => 'Test' + ], + 'aboutMe' => 'I am the best test user in the world.', + 'url' => 'https://plus.google.com/+TestUser', + 'image' => [ + 'url' => 'https://lh3.googleusercontent.com/photo.jpg' + ] + ]; + $providerMapper = new Google($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => null, + 'full_name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'avatar' => 'https://lh3.googleusercontent.com/photo.jpg', + 'gender' => null, + 'link' => 'https://plus.google.com/+TestUser', + 'bio' => 'I am the best test user in the world.', + 'locale' => null, + 'validated' => true, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php b/tests/TestCase/Auth/Social/Mapper/InstagramTest.php new file mode 100644 index 000000000..e7914604a --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/InstagramTest.php @@ -0,0 +1,72 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'profile_picture' => 'https://scontent-lax3-2.cdninstagram.com/test.jpg', + 'username' => 'test', + 'id' => '1', + 'full_name' => '', + 'website' => '', + 'counts' => [ + 'followed_by' => 35, + 'media' => 1, + 'follows' => 44 + ], + 'bio' => '' + ]; + $providerMapper = new Instagram($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => 'test', + 'full_name' => '', + 'first_name' => null, + 'last_name' => null, + 'email' => null, + 'avatar' => 'https://scontent-lax3-2.cdninstagram.com/test.jpg', + 'gender' => null, + 'link' => 'https://instagram.com/test', + 'bio' => '', + 'locale' => null, + 'validated' => false, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php b/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php new file mode 100644 index 000000000..4b0595dd3 --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php @@ -0,0 +1,75 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'emailAddress' => 'test@gmail.com', + 'firstName' => 'Test', + 'headline' => 'The best test user in the world.', + 'id' => '1', + 'industry' => 'Computer Software', + 'lastName' => 'User', + 'location' => [ + 'country' => [ + 'code' => 'es' + ], + 'name' => 'Spain' + ], + 'pictureUrl' => 'https://media.licdn.com/mpr/mprx/test.jpg', + 'publicProfileUrl' => 'https://www.linkedin.com/in/test' + ]; + $providerMapper = new LinkedIn($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => null, + 'full_name' => null, + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'avatar' => 'https://media.licdn.com/mpr/mprx/test.jpg', + 'gender' => null, + 'link' => 'https://www.linkedin.com/in/test', + 'bio' => 'The best test user in the world.', + 'locale' => null, + 'validated' => true, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php b/tests/TestCase/Auth/Social/Mapper/TwitterTest.php new file mode 100644 index 000000000..4197e00c7 --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/TwitterTest.php @@ -0,0 +1,71 @@ + '1', + 'nickname' => 'test', + 'name' => 'Test User', + 'firstName' => null, + 'lastName' => null, + 'email' => null, + 'location' => '', + 'description' => '', + 'imageUrl' => 'http://pbs.twimg.com/profile_images/test.jpeg', + 'urls' => [], + 'extra' => [], + 'token' => [ + 'accessToken' => 'test-token', + 'tokenSecret' => 'test-secret' + ] + ]; + $providerMapper = new Twitter($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => 'test', + 'full_name' => 'Test User', + 'first_name' => null, + 'last_name' => null, + 'email' => null, + 'avatar' => 'http://pbs.twimg.com/profile_images/test.jpeg', + 'gender' => null, + 'link' => 'https://twitter.com/test', + 'bio' => '', + 'locale' => null, + 'validated' => false, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => 'test-secret', + 'expires' => null + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php new file mode 100644 index 000000000..12ba6feae --- /dev/null +++ b/tests/TestCase/Auth/SuperuserAuthorizeTest.php @@ -0,0 +1,90 @@ +controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(null) + ->setConstructorArgs([$request, $response]) + ->getMock(); + $registry = new ComponentRegistry($this->controller); + $this->superuserAuthorize = new SuperuserAuthorize($registry); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->superuserAuthorize, $this->controller); + } + + /** + * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize + */ + public function testAuthorizeIsSuperuser() + { + $user = [ + 'is_superuser' => true, + ]; + $request = new ServerRequest(); + $result = $this->superuserAuthorize->authorize($user, $request); + $this->assertTrue($result); + } + + /** + * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize + */ + public function testAuthorizeIsNotSuperuser() + { + $user = [ + 'is_superuser' => false, + ]; + $request = new ServerRequest(); + $result = $this->superuserAuthorize->authorize($user, $request); + $this->assertFalse($result); + } + + /** + * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize + */ + public function testAuthorizeWeirdUser() + { + $request = new ServerRequest(); + $user = 'non array'; + $result = $this->superuserAuthorize->authorize($user, $request); + $this->assertFalse($result); + } +} diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php index 2c53232fb..a72250221 100644 --- a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php +++ b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php @@ -11,7 +11,9 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Cake\Core\Configure; use Cake\TestSuite\TestCase; +use ReflectionMethod; class ReCaptchaTraitTest extends TestCase { @@ -93,4 +95,29 @@ public function testValidateInvalidReCaptcha() ->will($this->returnValue($ReCaptcha)); $this->Trait->validateReCaptcha('invalid', '255.255.255.255'); } + + public function testGetRecaptchaInstance() + { + Configure::write('Users.reCaptcha.secret', 'secret'); + $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); + $method = new ReflectionMethod(get_class($trait), '_getReCaptchaInstance'); + $method->setAccessible(true); + $method->invokeArgs($trait, []); + $this->assertNotEmpty($method->invoke($trait)); + } + + public function testGetRecaptchaInstanceNull() + { + $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); + $method = new ReflectionMethod(get_class($trait), '_getReCaptchaInstance'); + $method->setAccessible(true); + $method->invokeArgs($trait, []); + $this->assertNull($method->invoke($trait)); + } + + public function testValidateReCaptchaFalse() + { + $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); + $this->assertFalse($this->Trait->validateReCaptcha('value', '255.255.255.255')); + } } diff --git a/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php new file mode 100644 index 000000000..618dbce10 --- /dev/null +++ b/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/AccountNotActiveExceptionTest.php b/tests/TestCase/Exception/AccountNotActiveExceptionTest.php new file mode 100644 index 000000000..2b8f5e5bc --- /dev/null +++ b/tests/TestCase/Exception/AccountNotActiveExceptionTest.php @@ -0,0 +1,45 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/BadConfigurationExceptionTest.php b/tests/TestCase/Exception/BadConfigurationExceptionTest.php new file mode 100644 index 000000000..b32d6050f --- /dev/null +++ b/tests/TestCase/Exception/BadConfigurationExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/MissingEmailExceptionTest.php b/tests/TestCase/Exception/MissingEmailExceptionTest.php new file mode 100644 index 000000000..67ec64fbe --- /dev/null +++ b/tests/TestCase/Exception/MissingEmailExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/MissingProviderExceptionTest.php b/tests/TestCase/Exception/MissingProviderExceptionTest.php new file mode 100644 index 000000000..1393535fa --- /dev/null +++ b/tests/TestCase/Exception/MissingProviderExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/TokenExpiredExceptionTest.php b/tests/TestCase/Exception/TokenExpiredExceptionTest.php new file mode 100644 index 000000000..ce332d375 --- /dev/null +++ b/tests/TestCase/Exception/TokenExpiredExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php new file mode 100644 index 000000000..3280cdf0a --- /dev/null +++ b/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/UserNotActiveExceptionTest.php b/tests/TestCase/Exception/UserNotActiveExceptionTest.php new file mode 100644 index 000000000..bf261d972 --- /dev/null +++ b/tests/TestCase/Exception/UserNotActiveExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/UserNotFoundExceptionTest.php b/tests/TestCase/Exception/UserNotFoundExceptionTest.php new file mode 100644 index 000000000..c12df3fea --- /dev/null +++ b/tests/TestCase/Exception/UserNotFoundExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/WrongPasswordExceptionTest.php b/tests/TestCase/Exception/WrongPasswordExceptionTest.php new file mode 100644 index 000000000..7df19e6bf --- /dev/null +++ b/tests/TestCase/Exception/WrongPasswordExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} From 20c5576db63356ed597e6fa8844fe1025cf1ce20 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 31 Mar 2017 16:29:17 -0500 Subject: [PATCH 0622/1476] Fix php cs --- composer.json | 3 ++- src/Auth/ApiKeyAuthenticate.php | 5 +++++ src/Auth/Exception/InvalidProviderException.php | 6 +++--- src/Auth/Exception/InvalidSettingsException.php | 6 +++--- src/Auth/Exception/MissingEventListenerException.php | 6 +++--- .../Exception/MissingProviderConfigurationException.php | 6 +++--- src/Exception/AccountAlreadyActiveException.php | 6 +++--- src/Exception/AccountNotActiveException.php | 6 +++--- src/Exception/BadConfigurationException.php | 6 +++--- src/Exception/MissingEmailException.php | 6 +++--- src/Exception/MissingProviderException.php | 6 +++--- src/Exception/TokenExpiredException.php | 6 +++--- src/Exception/UserAlreadyActiveException.php | 6 +++--- src/Exception/UserNotActiveException.php | 6 +++--- src/Exception/UserNotFoundException.php | 6 +++--- src/Exception/WrongPasswordException.php | 6 +++--- 16 files changed, 49 insertions(+), 43 deletions(-) diff --git a/composer.json b/composer.json index 28e363873..a5148c7ef 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,8 @@ "league/oauth2-google": "@stable", "league/oauth2-linkedin": "@stable", "google/recaptcha": "@stable", - "robthree/twofactorauth": "~1.6.0" + "robthree/twofactorauth": "~1.6.0", + "satooshi/php-coveralls": "dev-master" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php index 142e546f5..59927576d 100644 --- a/src/Auth/ApiKeyAuthenticate.php +++ b/src/Auth/ApiKeyAuthenticate.php @@ -45,6 +45,11 @@ class ApiKeyAuthenticate extends BaseAuthenticate 'finder' => null, ]; + /** + * ApiKeyAuthenticate constructor. + * @param ComponentRegistry $registry registry + * @param array $config config + */ public function __construct(ComponentRegistry $registry, array $config = []) { parent::__construct($registry, $config); diff --git a/src/Auth/Exception/InvalidProviderException.php b/src/Auth/Exception/InvalidProviderException.php index 04bd49a4f..d19eee654 100644 --- a/src/Auth/Exception/InvalidProviderException.php +++ b/src/Auth/Exception/InvalidProviderException.php @@ -20,9 +20,9 @@ class InvalidProviderException extends Exception /** * InvalidProviderException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Auth/Exception/InvalidSettingsException.php b/src/Auth/Exception/InvalidSettingsException.php index 343ba3e8b..fcc3e84b2 100644 --- a/src/Auth/Exception/InvalidSettingsException.php +++ b/src/Auth/Exception/InvalidSettingsException.php @@ -20,9 +20,9 @@ class InvalidSettingsException extends Exception /** * InvalidSettingsException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Auth/Exception/MissingEventListenerException.php b/src/Auth/Exception/MissingEventListenerException.php index b69f3ac69..b404b18cb 100644 --- a/src/Auth/Exception/MissingEventListenerException.php +++ b/src/Auth/Exception/MissingEventListenerException.php @@ -19,9 +19,9 @@ class MissingEventListenerException extends Exception /** * MissingEventListenerException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Auth/Exception/MissingProviderConfigurationException.php b/src/Auth/Exception/MissingProviderConfigurationException.php index c1f2d944d..77bcbea22 100644 --- a/src/Auth/Exception/MissingProviderConfigurationException.php +++ b/src/Auth/Exception/MissingProviderConfigurationException.php @@ -20,9 +20,9 @@ class MissingProviderConfigurationException extends Exception /** * MissingProviderConfigurationException constructor. - * @param string $message - * @param int $code - * @param null $previous + * @param string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message = null, $code = 500, $previous = null) { diff --git a/src/Exception/AccountAlreadyActiveException.php b/src/Exception/AccountAlreadyActiveException.php index 95b38eb9b..f3eddabff 100644 --- a/src/Exception/AccountAlreadyActiveException.php +++ b/src/Exception/AccountAlreadyActiveException.php @@ -17,9 +17,9 @@ class AccountAlreadyActiveException extends Exception { /** * AccountAlreadyActiveException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/AccountNotActiveException.php b/src/Exception/AccountNotActiveException.php index 02b09a0ed..a7afb535c 100644 --- a/src/Exception/AccountNotActiveException.php +++ b/src/Exception/AccountNotActiveException.php @@ -19,9 +19,9 @@ class AccountNotActiveException extends Exception /** * AccountNotActiveException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/BadConfigurationException.php b/src/Exception/BadConfigurationException.php index 70ba43de3..548a67afb 100644 --- a/src/Exception/BadConfigurationException.php +++ b/src/Exception/BadConfigurationException.php @@ -17,9 +17,9 @@ class BadConfigurationException extends Exception { /** * BadConfigurationException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/MissingEmailException.php b/src/Exception/MissingEmailException.php index 8f7432b1c..77cbc292e 100644 --- a/src/Exception/MissingEmailException.php +++ b/src/Exception/MissingEmailException.php @@ -17,9 +17,9 @@ class MissingEmailException extends Exception { /** * MissingEmailException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/MissingProviderException.php b/src/Exception/MissingProviderException.php index c908c55f7..da949c181 100644 --- a/src/Exception/MissingProviderException.php +++ b/src/Exception/MissingProviderException.php @@ -17,9 +17,9 @@ class MissingProviderException extends Exception { /** * MissingProviderException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/TokenExpiredException.php b/src/Exception/TokenExpiredException.php index 24b333730..d468a62e6 100644 --- a/src/Exception/TokenExpiredException.php +++ b/src/Exception/TokenExpiredException.php @@ -17,9 +17,9 @@ class TokenExpiredException extends Exception { /** * TokenExpiredException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/UserAlreadyActiveException.php b/src/Exception/UserAlreadyActiveException.php index 7e33e0da3..f211a37e6 100644 --- a/src/Exception/UserAlreadyActiveException.php +++ b/src/Exception/UserAlreadyActiveException.php @@ -17,9 +17,9 @@ class UserAlreadyActiveException extends Exception { /** * UserAlreadyActiveException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/UserNotActiveException.php b/src/Exception/UserNotActiveException.php index 380ab5c35..fb7bc9f58 100644 --- a/src/Exception/UserNotActiveException.php +++ b/src/Exception/UserNotActiveException.php @@ -17,9 +17,9 @@ class UserNotActiveException extends Exception { /** * UserNotActiveException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/UserNotFoundException.php b/src/Exception/UserNotFoundException.php index a1ff18aeb..c2780474a 100644 --- a/src/Exception/UserNotFoundException.php +++ b/src/Exception/UserNotFoundException.php @@ -17,9 +17,9 @@ class UserNotFoundException extends RecordNotFoundException { /** * UserNotFoundException constructor. - * @param string $message - * @param int $code - * @param null $previous + * @param string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { diff --git a/src/Exception/WrongPasswordException.php b/src/Exception/WrongPasswordException.php index 71c56fe9a..136b42d90 100644 --- a/src/Exception/WrongPasswordException.php +++ b/src/Exception/WrongPasswordException.php @@ -17,9 +17,9 @@ class WrongPasswordException extends Exception { /** * WrongPasswordException constructor. - * @param array|string $message - * @param int $code - * @param null $previous + * @param array|string $message message + * @param int $code code + * @param null $previous previous */ public function __construct($message, $code = 500, $previous = null) { From a8a3b4f6ef0b5dbc14fa8ab1703ddeec41f21e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 3 Apr 2017 12:57:29 +0100 Subject: [PATCH 0623/1476] fix cs --- .../Auth/Exception/InvalidProviderExceptionTest.php | 2 +- .../Auth/Exception/InvalidSettingsExceptionTest.php | 2 +- .../Auth/Exception/MissingEventListenerExceptionTest.php | 2 +- .../Exception/MissingProviderConfigurationExceptionTest.php | 2 +- tests/TestCase/Auth/Social/Mapper/FacebookTest.php | 6 +++--- tests/TestCase/Auth/Social/Mapper/GoogleTest.php | 4 ++-- tests/TestCase/Auth/Social/Mapper/InstagramTest.php | 2 +- tests/TestCase/Auth/Social/Mapper/LinkedInTest.php | 2 +- tests/TestCase/Auth/Social/Mapper/TwitterTest.php | 2 +- .../Exception/AccountAlreadyActiveExceptionTest.php | 2 +- tests/TestCase/Exception/AccountNotActiveExceptionTest.php | 2 +- tests/TestCase/Exception/BadConfigurationExceptionTest.php | 2 +- tests/TestCase/Exception/MissingEmailExceptionTest.php | 2 +- tests/TestCase/Exception/MissingProviderExceptionTest.php | 2 +- tests/TestCase/Exception/TokenExpiredExceptionTest.php | 2 +- tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php | 2 +- tests/TestCase/Exception/UserNotActiveExceptionTest.php | 2 +- tests/TestCase/Exception/UserNotFoundExceptionTest.php | 2 +- tests/TestCase/Exception/WrongPasswordExceptionTest.php | 2 +- 19 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php index d29960b3f..5a44e7451 100644 --- a/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php +++ b/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Exception\InvalidProviderException; +use Cake\TestSuite\TestCase; class InvalidProviderExceptionTest extends TestCase { diff --git a/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php index 40725f863..68d18bc24 100644 --- a/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php +++ b/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Exception\InvalidSettingsException; +use Cake\TestSuite\TestCase; class InvalidSettingsExceptionTest extends TestCase { diff --git a/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php b/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php index 3795a4885..f182d9083 100644 --- a/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php +++ b/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Exception\MissingEventListenerException; +use Cake\TestSuite\TestCase; class MissingEventListenerExceptionTest extends TestCase { diff --git a/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php b/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php index 4d7515a25..e1eb1bb3d 100644 --- a/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php +++ b/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Exception\InvalidSettingsException; +use Cake\TestSuite\TestCase; class MissingProviderConfigurationExceptionTest extends TestCase { diff --git a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php b/tests/TestCase/Auth/Social/Mapper/FacebookTest.php index ff72c5a74..8c8ba9e85 100644 --- a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php +++ b/tests/TestCase/Auth/Social/Mapper/FacebookTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Social\Mapper\Facebook; +use Cake\TestSuite\TestCase; class FacebookTest extends TestCase { @@ -56,9 +56,9 @@ public function testMap() 'gender' => 'male', 'locale' => 'en_US', 'link' => 'https://www.facebook.com/app_scoped_user_id/1/', - 'timezone' => (int) -5, + 'timezone' => -5, 'age_range' => [ - 'min' => (int) 21 + 'min' => 21 ], 'bio' => 'I am the best test user in the world.', 'picture_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg', diff --git a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php b/tests/TestCase/Auth/Social/Mapper/GoogleTest.php index 7e78af431..376e8273a 100644 --- a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php +++ b/tests/TestCase/Auth/Social/Mapper/GoogleTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Social\Mapper\Google; +use Cake\TestSuite\TestCase; class GoogleTest extends TestCase { @@ -46,7 +46,7 @@ public function testMap() 'image' => [ 'url' => 'https://lh3.googleusercontent.com/photo.jpg' ] - ]; + ]; $providerMapper = new Google($rawData); $user = $providerMapper(); $this->assertEquals([ diff --git a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php b/tests/TestCase/Auth/Social/Mapper/InstagramTest.php index e7914604a..7d3b05625 100644 --- a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php +++ b/tests/TestCase/Auth/Social/Mapper/InstagramTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Social\Mapper\Instagram; +use Cake\TestSuite\TestCase; class InstagramTest extends TestCase { diff --git a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php b/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php index 4b0595dd3..3f17e77a7 100644 --- a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php +++ b/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Social\Mapper\LinkedIn; +use Cake\TestSuite\TestCase; class LinkedInTest extends TestCase { diff --git a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php b/tests/TestCase/Auth/Social/Mapper/TwitterTest.php index 4197e00c7..d33aa343f 100644 --- a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php +++ b/tests/TestCase/Auth/Social/Mapper/TwitterTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Social\Mapper\Twitter; +use Cake\TestSuite\TestCase; class TwitterTest extends TestCase { diff --git a/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php index 618dbce10..a42d842f9 100644 --- a/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php +++ b/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\AccountAlreadyActiveException; +use Cake\TestSuite\TestCase; class AccountAlreadyActiveExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/AccountNotActiveExceptionTest.php b/tests/TestCase/Exception/AccountNotActiveExceptionTest.php index 2b8f5e5bc..9e08205d5 100644 --- a/tests/TestCase/Exception/AccountNotActiveExceptionTest.php +++ b/tests/TestCase/Exception/AccountNotActiveExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\AccountNotActiveException; +use Cake\TestSuite\TestCase; class AccountNotActiveExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/BadConfigurationExceptionTest.php b/tests/TestCase/Exception/BadConfigurationExceptionTest.php index b32d6050f..556b7258f 100644 --- a/tests/TestCase/Exception/BadConfigurationExceptionTest.php +++ b/tests/TestCase/Exception/BadConfigurationExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\BadConfigurationException; +use Cake\TestSuite\TestCase; class BadConfigurationExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/MissingEmailExceptionTest.php b/tests/TestCase/Exception/MissingEmailExceptionTest.php index 67ec64fbe..299b51b3f 100644 --- a/tests/TestCase/Exception/MissingEmailExceptionTest.php +++ b/tests/TestCase/Exception/MissingEmailExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\MissingEmailException; +use Cake\TestSuite\TestCase; class MissingEmailExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/MissingProviderExceptionTest.php b/tests/TestCase/Exception/MissingProviderExceptionTest.php index 1393535fa..0020f3360 100644 --- a/tests/TestCase/Exception/MissingProviderExceptionTest.php +++ b/tests/TestCase/Exception/MissingProviderExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\MissingProviderException; +use Cake\TestSuite\TestCase; class MissingProviderExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/TokenExpiredExceptionTest.php b/tests/TestCase/Exception/TokenExpiredExceptionTest.php index ce332d375..195ae5432 100644 --- a/tests/TestCase/Exception/TokenExpiredExceptionTest.php +++ b/tests/TestCase/Exception/TokenExpiredExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\TokenExpiredException; +use Cake\TestSuite\TestCase; class TokenExpiredExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php index 3280cdf0a..529742c53 100644 --- a/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php +++ b/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\UserAlreadyActiveException; +use Cake\TestSuite\TestCase; class UserAlreadyActiveExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/UserNotActiveExceptionTest.php b/tests/TestCase/Exception/UserNotActiveExceptionTest.php index bf261d972..73616e68f 100644 --- a/tests/TestCase/Exception/UserNotActiveExceptionTest.php +++ b/tests/TestCase/Exception/UserNotActiveExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\UserNotActiveException; +use Cake\TestSuite\TestCase; class UserNotActiveExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/UserNotFoundExceptionTest.php b/tests/TestCase/Exception/UserNotFoundExceptionTest.php index c12df3fea..d8e12580c 100644 --- a/tests/TestCase/Exception/UserNotFoundExceptionTest.php +++ b/tests/TestCase/Exception/UserNotFoundExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\UserNotFoundException; +use Cake\TestSuite\TestCase; class UserNotFoundExceptionTest extends TestCase { diff --git a/tests/TestCase/Exception/WrongPasswordExceptionTest.php b/tests/TestCase/Exception/WrongPasswordExceptionTest.php index 7df19e6bf..20b94bedb 100644 --- a/tests/TestCase/Exception/WrongPasswordExceptionTest.php +++ b/tests/TestCase/Exception/WrongPasswordExceptionTest.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Exception; -use Cake\TestSuite\TestCase; use CakeDC\Users\Exception\WrongPasswordException; +use Cake\TestSuite\TestCase; class WrongPasswordExceptionTest extends TestCase { From 64d88316cc33d540c38f6cb43eca26bfe000b959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 3 Apr 2017 13:41:07 +0100 Subject: [PATCH 0624/1476] remove files moved to cakedc/auth plugin --- src/Auth/ApiKeyAuthenticate.php | 146 -- src/Auth/RememberMeAuthenticate.php | 51 - src/Auth/Rules/AbstractRule.php | 97 -- src/Auth/Rules/Owner.php | 97 -- src/Auth/Rules/Rule.php | 26 - src/Auth/SimpleRbacAuthorize.php | 317 ----- src/Auth/SuperuserAuthorize.php | 53 - .../TestCase/Auth/ApiKeyAuthenticateTest.php | 244 ---- .../Auth/RememberMeAuthenticateTest.php | 168 --- tests/TestCase/Auth/Rules/OwnerTest.php | 254 ---- .../TestCase/Auth/SimpleRbacAuthorizeTest.php | 1201 ----------------- .../TestCase/Auth/SuperuserAuthorizeTest.php | 90 -- 12 files changed, 2744 deletions(-) delete mode 100644 src/Auth/ApiKeyAuthenticate.php delete mode 100644 src/Auth/RememberMeAuthenticate.php delete mode 100644 src/Auth/Rules/AbstractRule.php delete mode 100644 src/Auth/Rules/Owner.php delete mode 100644 src/Auth/Rules/Rule.php delete mode 100644 src/Auth/SimpleRbacAuthorize.php delete mode 100644 src/Auth/SuperuserAuthorize.php delete mode 100644 tests/TestCase/Auth/ApiKeyAuthenticateTest.php delete mode 100644 tests/TestCase/Auth/RememberMeAuthenticateTest.php delete mode 100644 tests/TestCase/Auth/Rules/OwnerTest.php delete mode 100644 tests/TestCase/Auth/SimpleRbacAuthorizeTest.php delete mode 100644 tests/TestCase/Auth/SuperuserAuthorizeTest.php diff --git a/src/Auth/ApiKeyAuthenticate.php b/src/Auth/ApiKeyAuthenticate.php deleted file mode 100644 index 59927576d..000000000 --- a/src/Auth/ApiKeyAuthenticate.php +++ /dev/null @@ -1,146 +0,0 @@ - self::TYPE_QUERYSTRING, - //name to retrieve the api key value from - 'name' => 'api_key', - //db field where the key is stored - 'field' => 'api_token', - //require SSL to pass the token. You should always require SSL to use tokens for Auth - 'require_ssl' => true, - //set a specific table for API auth, set as null to use Users.table - 'table' => null, - //set a specific finder for API auth, set as null to use Auth.authenticate.all.finder - 'finder' => null, - ]; - - /** - * ApiKeyAuthenticate constructor. - * @param ComponentRegistry $registry registry - * @param array $config config - */ - public function __construct(ComponentRegistry $registry, array $config = []) - { - parent::__construct($registry, $config); - } - - /** - * Authenticate callback - * Reads the API Key based on configuration and login the user - * - * @param \Cake\Http\ServerRequest $request request object. - * @param Response $response response object. - * @return mixed - */ - public function authenticate(ServerRequest $request, Response $response) - { - return $this->getUser($request); - } - - /** - * Stateless Authentication System - * http://book.cakephp.org/3.0/en/controllers/components/authentication.html#creating-stateless-authentication-systems - * - * Config: - * $this->Auth->config('storage', 'Memory'); - * $this->Auth->config('unauthorizedRedirect', 'false'); - * $this->Auth->config('checkAuthIn', 'Controller.initialize'); - * $this->Auth->config('loginAction', false); - * - * @param \Cake\Http\ServerRequest $request Cake request object. - * @return mixed - */ - public function getUser(ServerRequest $request) - { - $type = $this->getConfig('type'); - if (!in_array($type, $this->types)) { - throw new OutOfBoundsException(__d('CakeDC/Users', 'Type {0} is not valid', $type)); - } - - if (!is_callable([$this, $type])) { - throw new OutOfBoundsException(__d('CakeDC/Users', 'Type {0} has no associated callable', $type)); - } - - $apiKey = $this->$type($request); - if (empty($apiKey)) { - return false; - } - - if ($this->getConfig('require_ssl') && !$request->is('ssl')) { - throw new ForbiddenException(__d('CakeDC/Users', 'SSL is required for ApiKey Authentication', $type)); - } - - $this->_config['fields']['username'] = $this->getConfig('field'); - $this->_config['userModel'] = $this->getConfig('table') ?: Configure::read('Users.table'); - $this->_config['finder'] = $this->getConfig('finder') ?: - Configure::read('Auth.authenticate.all.finder') ?: - 'all'; - $result = $this->_query($apiKey)->first(); - - if (empty($result)) { - return false; - } - - return $result->toArray(); - } - - /** - * Get the api key from the querystring - * - * @param \Cake\Http\ServerRequest $request request - * @return string api key - */ - public function querystring(ServerRequest $request) - { - $name = $this->getConfig('name'); - - return $request->getQuery($name); - } - - /** - * Get the api key from the header - * - * @param \Cake\Http\ServerRequest $request request - * @return string api key - */ - public function header(ServerRequest $request) - { - $name = $this->getConfig('name'); - if (!empty($request->getHeader($name))) { - return $request->getHeaderLine($name); - } - - return null; - } -} diff --git a/src/Auth/RememberMeAuthenticate.php b/src/Auth/RememberMeAuthenticate.php deleted file mode 100644 index ab98bb3ce..000000000 --- a/src/Auth/RememberMeAuthenticate.php +++ /dev/null @@ -1,51 +0,0 @@ -_registry->getController()->Cookie->read($cookieName); - if (empty($cookie)) { - return false; - } - $this->setConfig('fields.username', 'id'); - $user = $this->_findUser($cookie['id']); - if ($user && - !empty($cookie['user_agent']) && - $request->getHeaderLine('User-Agent') === $cookie['user_agent'] - ) { - return $user; - } - - return false; - } -} diff --git a/src/Auth/Rules/AbstractRule.php b/src/Auth/Rules/AbstractRule.php deleted file mode 100644 index 234e93037..000000000 --- a/src/Auth/Rules/AbstractRule.php +++ /dev/null @@ -1,97 +0,0 @@ -setConfig($config); - } - - /** - * Get a table from the alias, table object or inspecting the request for a default table - * - * @param \Cake\Http\ServerRequest $request request - * @param mixed $table table - * @return \Cake\ORM\Table - * @throws \OutOfBoundsException if table alias is empty - */ - protected function _getTable(ServerRequest $request, $table = null) - { - if (empty($table)) { - return $this->_getTableFromRequest($request); - } - if ($table instanceof Table) { - return $table; - } - - return TableRegistry::get($table); - } - - /** - * Inspect the request and try to retrieve a table based on the current controller - * - * @param \Cake\Http\ServerRequest $request request - * @return \Cake\Datasource\RepositoryInterface - * @throws \OutOfBoundsException if table alias can't be extracted from request - */ - protected function _getTableFromRequest(ServerRequest $request) - { - $plugin = $request->getParam('plugin'); - $controller = $request->getParam('controller'); - $modelClass = ($plugin ? $plugin . '.' : '') . $controller; - - $this->modelFactory('Table', [$this->tableLocator(), 'get']); - if (empty($modelClass)) { - $msg = __d('CakeDC/Users', 'Missing Table alias, we could not extract a default table from the request'); - throw new OutOfBoundsException($msg); - } - - return $this->loadModel($modelClass); - } - - /** - * Check the current entity is owned by the logged in user - * - * @param array $user Auth array with the logged in data - * @param string $role role of the user - * @param \Cake\Http\ServerRequest $request current request, used to get a default table if not provided - * @return bool - * @throws \OutOfBoundsException if table is not found or it doesn't have the expected fields - */ - abstract public function allowed(array $user, $role, ServerRequest $request); -} diff --git a/src/Auth/Rules/Owner.php b/src/Auth/Rules/Owner.php deleted file mode 100644 index ed217421e..000000000 --- a/src/Auth/Rules/Owner.php +++ /dev/null @@ -1,97 +0,0 @@ - 'user_id', - /* - * request key type to retrieve the table id, could be "params", "query", "data" to locate the table id - * example: - * yoursite.com/controller/action/XXX would be - * tableKeyType => 'params', 'tableIdParamsKey' => 'pass.0' - * yoursite.com/controlerr/action?post_id=XXX would be - * tableKeyType => 'query', 'tableIdParamsKey' => 'post_id' - * yoursite.com/controller/action [posted form with a field named post_id] would be - * tableKeyType => 'data', 'tableIdParamsKey' => 'post_id' - */ - 'tableKeyType' => 'params', - // request->params key path to retrieve the owned table id - 'tableIdParamsKey' => 'pass.0', - /* - * define table to use or pick it from controller name defaults if null - * if null, table used will be based on current controller's default table - * if string, TableRegistry::get will be used - * if Table, the table object will be used - */ - 'table' => null, - /* - * define the table id to be used to match the row id, this is useful when checking belongsToMany associations - * Example: If checking ownership in a PostsUsers table, we should use 'id' => 'post_id' - * If value is null, we'll use the $table->primaryKey() - */ - 'id' => null, - 'conditions' => [], - ]; - - /** - * {@inheritdoc} - */ - public function allowed(array $user, $role, ServerRequest $request) - { - $table = $this->_getTable($request, $this->getConfig('table')); - //retrieve table id from request - $id = Hash::get($request->{$this->getConfig('tableKeyType')}, $this->getConfig('tableIdParamsKey')); - $userId = Hash::get($user, 'id'); - - try { - if (!$table->hasField($this->getConfig('ownerForeignKey'))) { - $msg = __d( - 'CakeDC/Users', - 'Missing column {0} in table {1} while checking ownership permissions for user {2}', - $this->getConfig('ownerForeignKey'), - $table->getAlias(), - $userId - ); - throw new OutOfBoundsException($msg); - } - } catch (Exception $ex) { - $msg = __d( - 'CakeDC/Users', - 'Missing column {0} in table {1} while checking ownership permissions for user {2}', - $this->getConfig('ownerForeignKey'), - $table->getAlias(), - $userId - ); - throw new OutOfBoundsException($msg); - } - $idColumn = $this->getConfig('id'); - if (empty($idColumn)) { - $idColumn = $table->getPrimaryKey(); - } - $conditions = array_merge([ - $idColumn => $id, - $this->getConfig('ownerForeignKey') => $userId - ], $this->getConfig('conditions')); - - return $table->exists($conditions); - } -} diff --git a/src/Auth/Rules/Rule.php b/src/Auth/Rules/Rule.php deleted file mode 100644 index 92ef89263..000000000 --- a/src/Auth/Rules/Rule.php +++ /dev/null @@ -1,26 +0,0 @@ - 'permissions', - //role field in the Users table - 'role_field' => 'role', - //default role, used in new users registered and also as role matcher when no role is available - 'default_role' => 'user', - /* - * This is a quick roles-permissions implementation - * Rules are evaluated top-down, first matching rule will apply - * Each line define - * [ - * 'role' => 'admin', - * 'plugin', (optional, default = null) - * 'prefix', (optional, default = null) - * 'extension', (optional, default = null) - * 'controller', - * 'action', - * 'allowed' (optional, default = true) - * ] - * You could use '*' to match anything - * You could use [] to match an array of options, example 'role' => ['adm1', 'adm2'] - * You could use a callback in your 'allowed' to process complex authentication, like - * - ownership - * - permissions stored in your database - * - permission based on an external service API call - * You could use an instance of the \CakeDC\Users\Auth\Rules\Rule interface to reuse your custom rules - * - * Examples: - * 1. Callback to allow users editing their own Posts: - * - * 'allowed' => function (array $user, $role, Request $request) { - * $postId = Hash::get($request->params, 'pass.0'); - * $post = TableRegistry::get('Posts')->get($postId); - * $userId = Hash::get($user, 'id'); - * if (!empty($post->user_id) && !empty($userId)) { - * return $post->user_id === $userId; - * } - * return false; - * } - * 2. Using the Owner Rule - * 'allowed' => new Owner() //will pick by default the post id from the first pass param - * - * Check the Owner Rule docs for more details - * - * - */ - 'permissions' => [], - ]; - - /** - * Default permissions to be loaded if no provided permissions - * - * @var array - */ - protected $_defaultPermissions = [ - //admin role allowed to use CakeDC\Users plugin actions - [ - 'role' => 'admin', - 'plugin' => '*', - 'controller' => '*', - 'action' => '*', - ], - //specific actions allowed for the user role in Users plugin - [ - 'role' => 'user', - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => ['profile', 'logout'], - ], - //all roles allowed to Pages/display - [ - 'role' => '*', - 'plugin' => null, - 'controller' => ['Pages'], - 'action' => ['display'], - ], - ]; - - /** - * Autoload permission configuration - * @param ComponentRegistry $registry component registry - * @param array $config config - */ - public function __construct(ComponentRegistry $registry, array $config = []) - { - parent::__construct($registry, $config); - $autoload = $this->getConfig('autoload_config'); - if ($autoload) { - $loadedPermissions = $this->_loadPermissions($autoload); - $this->setConfig('permissions', $loadedPermissions); - } - } - - /** - * Load config and retrieve permissions - * If the configuration file does not exist, or the permissions key not present, return defaultPermissions - * To be mocked - * - * @param string $key name of the configuration file to read permissions from - * @return array permissions - */ - protected function _loadPermissions($key) - { - try { - Configure::load($key, 'default'); - $permissions = Configure::read('Users.SimpleRbac.permissions'); - } catch (Exception $ex) { - $msg = __d('CakeDC/Users', 'Missing configuration file: "config/{0}.php". Using default permissions', $key); - $this->log($msg, LogLevel::WARNING); - } - - if (empty($permissions)) { - return $this->_defaultPermissions; - } - - return $permissions; - } - - /** - * Match the current plugin/controller/action against loaded permissions - * Set a default role if no role is provided - * - * @param array $user user data - * @param \Cake\Http\ServerRequest $request request - * @return bool - */ - public function authorize($user, ServerRequest $request) - { - $roleField = $this->getConfig('role_field'); - $role = $this->getConfig('default_role'); - if (Hash::check($user, $roleField)) { - $role = Hash::get($user, $roleField); - } - - $allowed = $this->_checkPermissions($user, $role, $request); - - return $allowed; - } - - /** - * Match against permissions, return if matched - * Permissions are processed based on the 'permissions' config values - * - * @param array $user current user array - * @param string $role effective role for the current user - * @param \Cake\Http\ServerRequest $request request - * @return bool true if there is a match in permissions - */ - protected function _checkPermissions(array $user, $role, ServerRequest $request) - { - $permissions = $this->getConfig('permissions'); - foreach ($permissions as $permission) { - $allowed = $this->_matchPermission($permission, $user, $role, $request); - if ($allowed !== null) { - return $allowed; - } - } - - return false; - } - - /** - * Match the rule for current permission - * - * @param array $permission The permission configuration - * @param array $user Current user data - * @param string $role Effective user's role - * @param \Cake\Http\ServerRequest $request Current request - * - * @return null|bool Null if permission is discarded, boolean if a final result is produced - */ - protected function _matchPermission(array $permission, array $user, $role, ServerRequest $request) - { - $issetController = isset($permission['controller']) || isset($permission['*controller']); - $issetAction = isset($permission['action']) || isset($permission['*action']); - $issetUser = isset($permission['user']) || isset($permission['*user']); - - if (!$issetController || !$issetAction) { - $this->log( - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - LogLevel::DEBUG - ); - - return false; - } - if ($issetUser) { - $this->log( - __d('CakeDC/Users', "Permission key 'user' is illegal, cannot evaluate the permission"), - LogLevel::DEBUG - ); - - return false; - } - - $permission += ['allowed' => true]; - $userArr = ['user' => $user]; - $reserved = [ - 'prefix' => $request->getParam('prefix'), - 'plugin' => $request->getParam('plugin'), - 'extension' => $request->getParam('_ext'), - 'controller' => $request->getParam('controller'), - 'action' => $request->getParam('action'), - 'role' => $role - ]; - - foreach ($permission as $key => $value) { - $inverse = $this->_startsWith($key, '*'); - if ($inverse) { - $key = ltrim($key, '*'); - } - - if (is_callable($value)) { - $return = (bool)call_user_func($value, $user, $role, $request); - } elseif ($value instanceof Rule) { - $return = (bool)$value->allowed($user, $role, $request); - } elseif ($key === 'allowed') { - $return = (bool)$value; - } elseif (array_key_exists($key, $reserved)) { - $return = $this->_matchOrAsterisk($value, $reserved[$key], true); - } else { - if (!$this->_startsWith($key, 'user.')) { - $key = 'user.' . $key; - } - - $return = $this->_matchOrAsterisk($value, Hash::get($userArr, $key)); - } - - if ($inverse) { - $return = !$return; - } - if ($key === 'allowed') { - return $return; - } - if (!$return) { - break; - } - } - - return null; - } - - /** - * Check if rule matched or '*' present in rule matching anything - * - * @param string|array $possibleValues Values that are accepted (from permission config) - * @param string|mixed|null $value Value to check with. We'll check the DASHERIZED value too - * @param bool $allowEmpty If true and $value is null, the rule will pass - * - * @return bool - */ - protected function _matchOrAsterisk($possibleValues, $value, $allowEmpty = false) - { - $possibleArray = (array)$possibleValues; - - if ($allowEmpty && empty($possibleArray) && $value === null) { - return true; - } - - if ($possibleValues === '*' || - in_array($value, $possibleArray) || - in_array(Inflector::camelize($value, '-'), $possibleArray) - ) { - return true; - } - - return false; - } - - /** - * Checks if $haystack begins with $needle - * - * @see http://stackoverflow.com/a/7168986/2588539 - * - * @param string $haystack The whole string - * @param string $needle The beginning to check - * - * @return bool - */ - protected function _startsWith($haystack, $needle) - { - return substr($haystack, 0, strlen($needle)) === $needle; - } -} diff --git a/src/Auth/SuperuserAuthorize.php b/src/Auth/SuperuserAuthorize.php deleted file mode 100644 index 314397d8b..000000000 --- a/src/Auth/SuperuserAuthorize.php +++ /dev/null @@ -1,53 +0,0 @@ - 'is_superuser', - ]; - - /** - * Check if the user is superuser - * - * @param array $user User information object. - * @param \Cake\Http\ServerRequest $request Cake request object. - * @return bool - */ - public function authorize($user, ServerRequest $request) - { - $user = (array)$user; - $superuserField = $this->getConfig('superuser_field'); - if (Hash::check($user, $superuserField)) { - return (bool)Hash::get($user, $superuserField); - } - - return false; - } -} diff --git a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php b/tests/TestCase/Auth/ApiKeyAuthenticateTest.php deleted file mode 100644 index 0c7562582..000000000 --- a/tests/TestCase/Auth/ApiKeyAuthenticateTest.php +++ /dev/null @@ -1,244 +0,0 @@ -getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $registry = new ComponentRegistry($controller); - $this->apiKey = new ApiKeyAuthenticate($registry, [ - 'finder' => 'all', - 'require_ssl' => false]); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->apiKey, $this->controller); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHappy() - { - $request = new ServerRequest('/?api_key=xxx'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-2', $result['username']); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateFail() - { - $request = new ServerRequest('/'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - - $request = new ServerRequest('/?api_key=none'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - - $request = new ServerRequest('/?api_key='); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Type wrong is not valid - * - */ - public function testAuthenticateWrongType() - { - $this->apiKey->setConfig('type', 'wrong'); - $request = new ServerRequest('/'); - $this->apiKey->authenticate($request, new Response()); - } - - /** - * test - * - * @expectedException \Cake\Network\Exception\ForbiddenException - * @expectedExceptionMessage SSL is required for ApiKey Authentication - * - */ - public function testAuthenticateRequireSSL() - { - $this->apiKey->setConfig('require_ssl', true); - $request = new ServerRequest('/?api_key=test'); - $this->apiKey->authenticate($request, new Response()); - } - - /** - * test - * - */ - public function testAuthenticateRequireSSLNoKey() - { - $this->apiKey->setConfig('require_ssl', true); - $request = new ServerRequest('/'); - $this->assertFalse($this->apiKey->authenticate($request, new Response())); - } - - /** - * test - * - * @return void - */ - public function testHeaderHappy() - { - $request = $this->getMockBuilder('\Cake\Http\ServerRequest') - ->setMethods(['getHeader', 'getHeaderLine']) - ->getMock(); - $request->expects($this->at(0)) - ->method('getHeader') - ->with('api_key') - ->will($this->returnValue(['xxx'])); - $request->expects($this->at(1)) - ->method('getHeaderLine') - ->with('api_key') - ->will($this->returnValue('xxx')); - $this->apiKey->setConfig('type', 'header'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-2', $result['username']); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHeaderFail() - { - $request = $this->getMockBuilder('\Cake\Http\ServerRequest') - ->setMethods(['getHeader', 'getHeaderLine']) - ->getMock(); - $request->expects($this->at(0)) - ->method('getHeader') - ->with('api_key') - ->will($this->returnValue(['wrong'])); - $request->expects($this->at(1)) - ->method('getHeaderLine') - ->with('api_key') - ->will($this->returnValue('wrong')); - $this->apiKey->setConfig('type', 'header'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHeaderNotPresent() - { - $request = $this->getMockBuilder('\Cake\Http\ServerRequest') - ->setMethods(['getHeader']) - ->getMock(); - $request->expects($this->once()) - ->method('getHeader') - ->with('api_key') - ->will($this->returnValue([])); - $this->apiKey->setConfig('type', 'header'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateFinderConfig() - { - $this->apiKey->setConfig('finder', 'undefinedInConfig'); - $request = new ServerRequest('/?api_key=xxx'); - try { - $result = $this->apiKey->authenticate($request, new Response()); - $this->fail(); - } catch (\Exception $ex) { - $this->assertEquals('Unknown finder method "undefinedInConfig"', $ex->getMessage()); - } - } - - /** - * test - * - * @return void - */ - public function testAuthenticateFinderAuthConfig() - { - Configure::write('Auth.authenticate.all.finder', 'undefinedFinderInAuth'); - $this->apiKey->setConfig('finder', null); - $request = new ServerRequest('/?api_key=xxx'); - try { - $result = $this->apiKey->authenticate($request, new Response()); - $this->fail(); - } catch (\Exception $ex) { - $this->assertEquals('Unknown finder method "undefinedFinderInAuth"', $ex->getMessage()); - } - } - - /** - * test - * - * @return void - */ - public function testAuthenticateDefaultAllFinder() - { - Configure::write('Auth.authenticate.all.finder', null); - $request = new ServerRequest('/?api_key=yyy'); - $result = $this->apiKey->authenticate($request, new Response()); - $this->assertEquals('user-1', $result['username']); - } -} diff --git a/tests/TestCase/Auth/RememberMeAuthenticateTest.php b/tests/TestCase/Auth/RememberMeAuthenticateTest.php deleted file mode 100644 index a31eb7782..000000000 --- a/tests/TestCase/Auth/RememberMeAuthenticateTest.php +++ /dev/null @@ -1,168 +0,0 @@ -controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $registry = new ComponentRegistry($this->controller); - $this->rememberMe = new RememberMeAuthenticate($registry); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->rememberMe, $this->controller); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateHappy() - { - $request = new ServerRequest('/'); - $request = $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_agent' => 'user-agent' - ])); - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertEquals('user-1', $result['username']); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateBadUser() - { - $request = new ServerRequest('/'); - $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue([ - //bad-user - 'id' => '00000000-0000-0000-0000-000000000000', - 'user_agent' => 'user-agent' - ])); - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateBadAgent() - { - $request = new ServerRequest('/'); - $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_agent' => 'bad-agent' - ])); - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testAuthenticateNoCookie() - { - $request = new ServerRequest('/'); - $request->env('HTTP_USER_AGENT', 'user-agent'); - $mockCookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->disableOriginalConstructor() - ->setMethods(['check', 'read']) - ->getMock(); - $mockCookie - ->expects($this->once()) - ->method('read') - ->with('remember_me') - ->will($this->returnValue(null)); - - $registry = new ComponentRegistry($this->controller); - $this->controller->Cookie = $mockCookie; - $this->rememberMe = new RememberMeAuthenticate($registry); - $result = $this->rememberMe->authenticate($request, new Response()); - $this->assertFalse($result); - } -} diff --git a/tests/TestCase/Auth/Rules/OwnerTest.php b/tests/TestCase/Auth/Rules/OwnerTest.php deleted file mode 100644 index a7384c5a0..000000000 --- a/tests/TestCase/Auth/Rules/OwnerTest.php +++ /dev/null @@ -1,254 +0,0 @@ -Owner = new Owner(); - $this->request = new ServerRequest(); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->Owner); - } - - /** - * test - * - * @return void - */ - public function testAllowed() - { - $this->request = $this->request - ->withParam('plugin', 'CakeDC/Users') - ->withParam('controller', 'Posts') - ->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testAllowedUsingTableAlias() - { - $this->Owner = new Owner([ - 'table' => 'Posts' - ]); - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testAllowedUsingTableInstance() - { - $this->Owner = new Owner([ - 'table' => TableRegistry::get('CakeDC/Users.Posts'), - ]); - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Missing Table alias, we could not extract a default table from the request - */ - public function testAllowedShouldThrowExceptionBecauseEmptyAliasFromRequest() - { - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->Owner->allowed($user, 'user', $this->request); - } - - /** - * test - * - * @return void - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Missing column column_not_found in table Posts while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 - */ - public function testAllowedShouldThrowExceptionBecauseForeignKeyNotPresentInTable() - { - $this->Owner = new Owner([ - 'table' => TableRegistry::get('CakeDC/Users.Posts'), - 'ownerForeignKey' => 'column_not_found', - ]); - $this->request = $this->request->withParam('pass', ['00000000-0000-0000-0000-000000000001']); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->Owner->allowed($user, 'user', $this->request); - } - - /** - * test - * - * @return void - */ - public function testNotAllowedBecauseNotOwner() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Posts', - 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testNotAllowedBecauseUserNotFound() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Posts', - 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]); - $user = [ - 'id' => '99999999-0000-0000-0000-000000000000', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - */ - public function testNotAllowedBecausePostNotFound() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Posts', - 'pass' => ['99999999-0000-0000-0000-000000000000'] //not found - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * test - * - * @return void - * @expectedException \OutOfBoundsException - * @expectedExceptionMessage Missing column user_id in table NoDefaultTable while checking ownership permissions for user 00000000-0000-0000-0000-000000000001 - */ - public function testNotAllowedBecauseNoDefaultTable() - { - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'NoDefaultTable', - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * Test using the Owner rule in a belongsToMany association - * Posts belongsToMany Users - * @return void - */ - public function testAllowedBelongsToMany() - { - $this->Owner = new Owner([ - 'table' => 'PostsUsers', - 'id' => 'post_id', - ]); - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'IsNotUsed', - 'pass' => ['00000000-0000-0000-0000-000000000001'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertTrue($this->Owner->allowed($user, 'user', $this->request)); - } - - /** - * Test using the Owner rule in a belongsToMany association - * Posts belongsToMany Users - * @return void - */ - public function testNotAllowedBelongsToMany() - { - $this->Owner = new Owner([ - 'table' => 'PostsUsers', - 'id' => 'post_id', - ]); - $this->request = $this->request->addParams([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'IsNotUsed', - 'pass' => ['00000000-0000-0000-0000-000000000002'] - ]); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - ]; - $this->assertFalse($this->Owner->allowed($user, 'user', $this->request)); - } -} diff --git a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php b/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php deleted file mode 100644 index 36c89e15c..000000000 --- a/tests/TestCase/Auth/SimpleRbacAuthorizeTest.php +++ /dev/null @@ -1,1201 +0,0 @@ - 'admin', - 'plugin' => '*', - 'controller' => '*', - 'action' => '*', - ], - //specific actions allowed for the user role in Users plugin - [ - 'role' => 'user', - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => ['profile', 'logout'], - ], - //all roles allowed to Pages/display - [ - 'role' => '*', - 'plugin' => null, - 'controller' => ['Pages'], - 'action' => ['display'], - ], - ]; - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - public function setUp() - { - $request = new ServerRequest(); - $response = new Response(); - - $this->controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $this->registry = new ComponentRegistry($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->simpleRbacAuthorize, $this->controller); - } - - /** - * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct - */ - public function testConstruct() - { - //don't autoload config - $this->simpleRbacAuthorize = new SimpleRbacAuthorize($this->registry, ['autoload_config' => false]); - $this->assertEmpty($this->simpleRbacAuthorize->getConfig('permissions')); - } - - /** - * test - * - * @return void - */ - public function testLoadPermissions() - { - $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') - ->disableOriginalConstructor() - ->getMock(); - $reflectedClass = new ReflectionClass($this->simpleRbacAuthorize); - $loadPermissions = $reflectedClass->getMethod('_loadPermissions'); - $loadPermissions->setAccessible(true); - $permissions = $loadPermissions->invoke($this->simpleRbacAuthorize, 'missing'); - $this->assertEquals($this->defaultPermissions, $permissions); - } - - /** - * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct - */ - public function testConstructMissingPermissionsFile() - { - $this->simpleRbacAuthorize = $this->getMockBuilder('CakeDC\Users\Auth\SimpleRbacAuthorize') - ->setMethods(null) - ->setConstructorArgs([$this->registry, ['autoload_config' => 'does-not-exist']]) - ->getMock(); - //we should have the default permissions - $this->assertEquals($this->defaultPermissions, $this->simpleRbacAuthorize->getConfig('permissions')); - } - - protected function assertConstructorPermissions($instance, $config, $permissions) - { - $reflectedClass = new ReflectionClass($instance); - $constructor = $reflectedClass->getConstructor(); - $constructor->invoke($this->simpleRbacAuthorize, $this->registry, $config); - - //we should have the default permissions - $resultPermissions = $this->simpleRbacAuthorize->getConfig('permissions'); - $this->assertEquals($permissions, $resultPermissions); - } - - /** - * @covers CakeDC\Users\Auth\SimpleRbacAuthorize::__construct - */ - public function testConstructPermissionsFileHappy() - { - $permissions = [ - [ - 'controller' => 'Test', - 'action' => 'test' - ] - ]; - $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; - $this->simpleRbacAuthorize = $this->getMockBuilder($className) - ->setMethods(['_loadPermissions']) - ->disableOriginalConstructor() - ->getMock(); - $this->simpleRbacAuthorize - ->expects($this->once()) - ->method('_loadPermissions') - ->with('permissions-happy') - ->will($this->returnValue($permissions)); - $this->assertConstructorPermissions($className, ['autoload_config' => 'permissions-happy'], $permissions); - } - - protected function preparePermissions($permissions) - { - $className = 'CakeDC\Users\Auth\SimpleRbacAuthorize'; - $simpleRbacAuthorize = $this->getMockBuilder($className) - ->setMethods(['_loadPermissions']) - ->disableOriginalConstructor() - ->getMock(); - $simpleRbacAuthorize->config('permissions', $permissions); - - return $simpleRbacAuthorize; - } - - /** - * @dataProvider providerAuthorize - */ - public function testAuthorize($permissions, $user, $requestParams, $expected, $msg = null) - { - $this->simpleRbacAuthorize = $this->preparePermissions($permissions); - $request = $this->_requestFromArray($requestParams); - - $result = $this->simpleRbacAuthorize->authorize($user, $request); - $this->assertSame($expected, $result, $msg); - } - - public function providerAuthorize() - { - $trueRuleMock = $this->getMockBuilder(Rule::class) - ->setMethods(['allowed']) - ->getMock(); - $trueRuleMock->expects($this->any()) - ->method('allowed') - ->willReturn(true); - - return [ - 'discard-first' => [ - //permissions - [ - [ - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'three', // Discard here - function () { - throw new \Exception(); - } - ], - [ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'deny-first-discard-after' => [ - //permissions - [ - [ - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'one', - 'allowed' => function () { - return false; // Deny here since under 'allowed' key - } - ], - [ - // This permission isn't evaluated - function () { - throw new \Exception(); - }, - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'star-invert' => [ - //permissions - [[ - '*plugin' => 'Tests', - '*role' => 'test', - '*controller' => 'Tests', - '*action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'something', - ], - //request - [ - 'plugin' => 'something', - 'controller' => 'something', - 'action' => 'something' - ], - //expected - true - ], - 'star-invert-deny' => [ - //permissions - [[ - '*plugin' => 'Tests', - '*role' => 'test', - '*controller' => 'Tests', - '*action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'something', - ], - //request - [ - 'plugin' => 'something', - 'controller' => 'something', - 'action' => 'test' - ], - //expected - false - ], - 'user-arr' => [ - //permissions - [ - [ - 'username' => 'luke', - 'user.id' => 1, - 'profile.id' => 256, - 'user.profile.signature' => "Hi I'm luke", - 'user.allowed' => false, - 'controller' => 'Tests', - 'action' => 'one' - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - 'profile' => [ - 'id' => 256, - 'signature' => "Hi I'm luke" - ], - 'allowed' => false - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'evaluate-order' => [ - //permissions - [ - [ - 'allowed' => false, - function () { - throw new \Exception(); - }, - 'controller' => 'Tests', - 'action' => 'one' - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'multiple-callables' => [ - //permissions - [ - [ - function () { - return true; - }, - clone $trueRuleMock, - function () { - return true; - }, - 'controller' => 'Tests', - 'action' => 'one' - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'happy-strict-all' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-strict-all-deny' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - false - ], - 'happy-plugin-null-allowed-null' => [ - //permissions - [[ - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => null, - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-plugin-asterisk' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Any', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-plugin-asterisk-main-app' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => null, - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-role-asterisk' => [ - //permissions - [[ - 'role' => '*', - 'controller' => 'Tests', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'any-role', - ], - //request - [ - 'plugin' => null, - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-controller-asterisk' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => '*', - 'action' => 'test', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - true - ], - 'happy-action-asterisk' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'any' - ], - //expected - true - ], - 'happy-some-asterisk-allowed' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => '*', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'any' - ], - //expected - true - ], - 'happy-some-asterisk-deny' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => 'test', - 'controller' => '*', - 'action' => '*', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'any' - ], - //expected - false - ], - 'all-deny' => [ - //permissions - [[ - 'plugin' => '*', - 'role' => '*', - 'controller' => '*', - 'action' => '*', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Any', - 'controller' => 'Any', - 'action' => 'any' - ], - //expected - false - ], - 'dasherized' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'TestTests', - 'action' => 'TestAction', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'tests', - 'controller' => 'test-tests', - 'action' => 'test-action' - ], - //expected - true - ], - 'happy-array' => [ - //permissions - [[ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'happy-array-deny' => [ - //permissions - [[ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'three' - ], - //expected - false - ], - 'happy-callback-check-params' => [ - //permissions - [[ - 'plugin' => ['Tests'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - 'allowed' => function ($user, $role, $request) { - return $user['id'] === 1 && $role = 'test' && $request->plugin == 'Tests'; - } - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'happy-callback-deny' => [ - //permissions - [[ - 'plugin' => ['*'], - 'role' => ['test'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - 'allowed' => function ($user, $role, $request) { - return false; - } - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'happy-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['admin'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'deny-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['admin'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'star-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => '*', - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-prefix' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['one', 'admin'], - 'controller' => '*', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-prefix-deny' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['one', 'admin'], - 'controller' => '*', - 'action' => 'one', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'happy-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => ['admin'], - 'extension' => ['csv'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - '_ext' => 'csv', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'deny-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'extension' => ['csv'], - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - '_ext' => 'csv', - 'action' => 'one' - ], - //expected - false - ], - 'star-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'prefix' => '*', - 'extension' => '*', - 'controller' => ['Tests'], - 'action' => ['one', 'two'], - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'admin', - '_ext' => 'other', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-ext' => [ - //permissions - [[ - 'role' => ['test'], - 'extension' => ['csv', 'pdf'], - 'controller' => '*', - 'action' => '*', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - '_ext' => 'csv', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - 'array-ext-deny' => [ - //permissions - [[ - 'role' => ['test'], - 'extension' => ['csv', 'docx'], - 'controller' => '*', - 'action' => 'one', - 'allowed' => false, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'prefix' => 'csv', - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - false - ], - 'rule-class' => [ - //permissions - [ - [ - 'role' => ['test'], - 'controller' => '*', - 'action' => 'one', - 'allowed' => $trueRuleMock, - ], - ], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'controller' => 'Tests', - 'action' => 'one' - ], - //expected - true - ], - ]; - } - - /** - * @dataProvider badPermissionProvider - * - * @param array $permissions - * @param array $user - * @param array $requestParams - * @param string $expectedMsg - */ - public function testBadPermission($permissions, $user, $requestParams, $expectedMsg) - { - $simpleRbacAuthorize = $this->getMockBuilder(SimpleRbacAuthorize::class) - ->setMethods(['_loadPermissions', 'log']) - ->disableOriginalConstructor() - ->getMock(); - $simpleRbacAuthorize - ->expects($this->once()) - ->method('log') - ->with($expectedMsg, LogLevel::DEBUG); - - $simpleRbacAuthorize->config('permissions', $permissions); - $request = $this->_requestFromArray($requestParams); - - $simpleRbacAuthorize->authorize($user, $request); - } - - public function badPermissionProvider() - { - return [ - 'no-controller' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - //'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'no-action' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - //'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'no-controller-and-action' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - //'controller' => 'Tests', - //'action' => 'test', - 'allowed' => true, - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'no-controller and user-key' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - //'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - 'user' => 'something', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Cannot evaluate permission when 'controller' and/or 'action' keys are absent"), - ], - 'user-key' => [ - //permissions - [[ - 'plugin' => 'Tests', - 'role' => 'test', - 'controller' => 'Tests', - 'action' => 'test', - 'allowed' => true, - 'user' => 'something', - ]], - //user - [ - 'id' => 1, - 'username' => 'luke', - 'role' => 'test', - ], - //request - [ - 'plugin' => 'Tests', - 'controller' => 'Tests', - 'action' => 'test' - ], - //expected - __d('CakeDC/Users', "Permission key 'user' is illegal, cannot evaluate the permission"), - ], - ]; - } - - /** - * @param array $params - * @return ServerRequest - */ - protected function _requestFromArray($params) - { - $request = new ServerRequest(); - - return $request - ->withParam('plugin', Hash::get($params, 'plugin')) - ->withParam('controller', Hash::get($params, 'controller')) - ->withParam('action', Hash::get($params, 'action')) - ->withParam('prefix', Hash::get($params, 'prefix')) - ->withParam('_ext', Hash::get($params, '_ext')); - } -} diff --git a/tests/TestCase/Auth/SuperuserAuthorizeTest.php b/tests/TestCase/Auth/SuperuserAuthorizeTest.php deleted file mode 100644 index 12ba6feae..000000000 --- a/tests/TestCase/Auth/SuperuserAuthorizeTest.php +++ /dev/null @@ -1,90 +0,0 @@ -controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(null) - ->setConstructorArgs([$request, $response]) - ->getMock(); - $registry = new ComponentRegistry($this->controller); - $this->superuserAuthorize = new SuperuserAuthorize($registry); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->superuserAuthorize, $this->controller); - } - - /** - * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize - */ - public function testAuthorizeIsSuperuser() - { - $user = [ - 'is_superuser' => true, - ]; - $request = new ServerRequest(); - $result = $this->superuserAuthorize->authorize($user, $request); - $this->assertTrue($result); - } - - /** - * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize - */ - public function testAuthorizeIsNotSuperuser() - { - $user = [ - 'is_superuser' => false, - ]; - $request = new ServerRequest(); - $result = $this->superuserAuthorize->authorize($user, $request); - $this->assertFalse($result); - } - - /** - * @covers CakeDC\Users\Auth\SuperuserAuthorize::authorize - */ - public function testAuthorizeWeirdUser() - { - $request = new ServerRequest(); - $user = 'non array'; - $result = $this->superuserAuthorize->authorize($user, $request); - $this->assertFalse($result); - } -} From 3db8b5841bd5b88992ca230226ded723660fc1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 3 Apr 2017 13:42:12 +0100 Subject: [PATCH 0625/1476] refs #cakedc-auth-integration fix cs --- src/Auth/SocialAuthenticate.php | 1 - src/Shell/UsersShell.php | 20 ++++++++++---------- src/View/Helper/UserHelper.php | 1 - 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 18db5bee8..32c614b68 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -39,7 +39,6 @@ */ class SocialAuthenticate extends BaseAuthenticate { - use EventDispatcherTrait; use LogTrait; diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 881708794..27e704418 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -135,10 +135,10 @@ public function resetPassword() $username = Hash::get($this->args, 0); $password = Hash::get($this->args, 1); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($password)) { - $this->setError(__d('CakeDC/Users', 'Please enter a password.')); + $this->setError(__d('CakeDC/Users', 'Please enter a password.')); } $data = [ 'password' => $password @@ -163,10 +163,10 @@ public function changeRole() $username = Hash::get($this->args, 0); $role = Hash::get($this->args, 1); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($role)) { - $this->setError(__d('CakeDC/Users', 'Please enter a role.')); + $this->setError(__d('CakeDC/Users', 'Please enter a role.')); } $data = [ 'role' => $role @@ -215,7 +215,7 @@ public function passwordEmail() { $reference = Hash::get($this->args, 0); if (empty($reference)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username or email.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username or email.')); } $resetUser = $this->Users->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -227,7 +227,7 @@ public function passwordEmail() $this->out($msg); } else { $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); - $this->setError($msg); + $this->setError($msg); } } @@ -241,7 +241,7 @@ protected function _changeUserActive($active) { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } $data = [ 'active' => $active @@ -316,7 +316,7 @@ protected function _updateUser($username, $data) { $user = $this->Users->find()->where(['username' => $username])->first(); if (empty($user)) { - $this->setError(__d('CakeDC/Users', 'The user was not found.')); + $this->setError(__d('CakeDC/Users', 'The user was not found.')); } $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { @@ -338,7 +338,7 @@ public function deleteUser() { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->setError(__d('CakeDC/Users', 'Please enter a username.')); } $user = $this->Users->find()->where(['username' => $username])->first(); if (isset($this->Users->SocialAccounts)) { @@ -346,7 +346,7 @@ public function deleteUser() } $deleteUser = $this->Users->delete($user); if (!$deleteUser) { - $this->setError(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); + $this->setError(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); } $this->out(__d('CakeDC/Users', 'The user {0} was deleted successfully', $username)); } diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 21712d000..c22688519 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -23,7 +23,6 @@ */ class UserHelper extends Helper { - public $helpers = ['Html', 'Form', 'CakeDC/Users.AuthLink']; /** From ebb1feef022a88755b56d8086d4a3f7702872c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 3 Apr 2017 14:54:17 +0100 Subject: [PATCH 0626/1476] Update and rename 4.1.x-5.0.md to 4.x-5.0.md --- Docs/Documentation/Migration/{4.1.x-5.0.md => 4.x-5.0.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Docs/Documentation/Migration/{4.1.x-5.0.md => 4.x-5.0.md} (97%) diff --git a/Docs/Documentation/Migration/4.1.x-5.0.md b/Docs/Documentation/Migration/4.x-5.0.md similarity index 97% rename from Docs/Documentation/Migration/4.1.x-5.0.md rename to Docs/Documentation/Migration/4.x-5.0.md index 9f92b805e..6cd858a23 100644 --- a/Docs/Documentation/Migration/4.1.x-5.0.md +++ b/Docs/Documentation/Migration/4.x-5.0.md @@ -1,4 +1,4 @@ -Migration 4.1.x to 5.0 +Migration 4.x to 5.0 ====================== 5.0 is compatible with CakePHP ^3.4 and refactored some Auth objects into a new plugin From a25e4e9dc7ae0f7bd95c912c34c214c301fa3adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 3 Apr 2017 14:54:45 +0100 Subject: [PATCH 0627/1476] Update Home.md --- Docs/Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Home.md b/Docs/Home.md index bce0a151c..55c374ae2 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -25,6 +25,6 @@ Documentation Migration guides ---------------- -* [4.1.x to 5.0](Documentation/Migration/4.1.x-5.0.md) +* [4.x to 5.0](Documentation/Migration/4.x-5.0.md) From 22090329029157debe8d7ed86346482322649214 Mon Sep 17 00:00:00 2001 From: cristiandean Date: Mon, 3 Apr 2017 16:18:48 -0300 Subject: [PATCH 0628/1476] Wrong method name '_isProviderEnable" --- src/Auth/SocialAuthenticate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 32c614b68..48efb6a02 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -65,7 +65,7 @@ public function __construct(ComponentRegistry $registry, array $config = []) $providers = []; foreach ($oauthConfig['providers'] as $provider => $options) { - if ($this->_isProviderEnable($options)) { + if ($this->_isProviderEnabled($options)) { $providers[$provider] = $options; } } From 3fd2a0177e1fccbeff72c99317fd57d407498682 Mon Sep 17 00:00:00 2001 From: cristiandean Date: Mon, 3 Apr 2017 17:34:22 -0300 Subject: [PATCH 0629/1476] Fix: Behavior::getTable() is not acessible Fix: CakePHP 3.4 Behavior::getTable() is not acessible --- src/Model/Behavior/AuthFinderBehavior.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index f886c0a1b..bc906831c 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -29,7 +29,7 @@ class AuthFinderBehavior extends Behavior */ public function findActive(Query $query, array $options = []) { - $query->where([$this->getTable()->aliasField('active') => 1]); + $query->where([$this->_table->aliasField('active') => 1]); return $query; } @@ -50,7 +50,7 @@ public function findAuth(Query $query, array $options = []) } $query - ->orWhere([$this->getTable()->aliasField('email') => $identifier]) + ->orWhere([$this->_table->aliasField('email') => $identifier]) ->find('active', $options); return $query; From db02ae96bd9487bd3ba2b42275ef73550107eba3 Mon Sep 17 00:00:00 2001 From: Cristian Dean Date: Wed, 5 Apr 2017 10:00:11 -0300 Subject: [PATCH 0630/1476] Update Users.po --- src/Locale/pt_BR/Users.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Locale/pt_BR/Users.po b/src/Locale/pt_BR/Users.po index db8f2bbe5..ccf0d9fa8 100644 --- a/src/Locale/pt_BR/Users.po +++ b/src/Locale/pt_BR/Users.po @@ -361,7 +361,7 @@ msgstr "Adicionar um novo usuário" #: Shell/UsersShell.php:58 msgid "Change the role for an specific user" -msgstr "Mudar o role de um usuário específico" +msgstr "Alterar o role de um usuário específico" #: Shell/UsersShell.php:59 msgid "Deactivate an specific user" @@ -653,7 +653,7 @@ msgstr "Visualizar" #: Template/Users/index.ctp:38 msgid "Change password" -msgstr "Mudar senha" +msgstr "Alterar senha" #: Template/Users/index.ctp:39 Template/Users/view.ctp:99 msgid "Edit" @@ -721,7 +721,7 @@ msgstr "Senha" #: Template/Users/register.ctp:28 msgid "Accept TOS conditions?" -msgstr "Concordar com TOS?" +msgstr "Concordar com Termos de Uso?" #: Template/Users/request_reset_password.ctp:5 msgid "Please enter your email to reset your password" From 083f5032fdf100c45d3686704fcde621c5ad9763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 6 Apr 2017 09:18:03 +0100 Subject: [PATCH 0631/1476] refs #add-tests-covering-typo add social authenticate tests covering typo --- src/Auth/SocialAuthenticate.php | 2 +- .../TestCase/Auth/SocialAuthenticateTest.php | 76 ++++++++++++++++--- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 48efb6a02..0fbbe059a 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -71,7 +71,7 @@ public function __construct(ComponentRegistry $registry, array $config = []) } $oauthConfig['providers'] = $providers; Configure::write('OAuth2', $oauthConfig); - $config = $this->normalizeConfig(array_merge($config, $oauthConfig), $enabledNoOAuth2Provider); + $config = $this->normalizeConfig(Hash::merge($config, $oauthConfig), $enabledNoOAuth2Provider); parent::__construct($registry, $config); } diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index efbbdf213..f3c86b866 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Auth; +use CakeDC\Users\Auth\SocialAuthenticate; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -64,7 +65,7 @@ public function setUp() $this->Request = $request; $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', '_getProviderName', - '_mapUser', '_socialLogin', 'dispatchEvent', '_validateConfig', '_getController']); + '_mapUser', '_socialLogin', 'dispatchEvent', '_validateConfig', '_getController']); $this->SocialAuthenticate->expects($this->any()) ->method('_getController') @@ -95,6 +96,57 @@ protected function _getSocialAuthenticateMockMethods($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.5', + '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.5', + 'redirectUri' => 'http://example.com/auth/facebook', + ] + ] + ] + ]); + } + /** * Test getUser * @@ -109,9 +161,9 @@ public function testGetUserAuth($rawData, $mapper) ->with(UsersAuthComponent::EVENT_AFTER_REGISTER, compact('user')); $this->SocialAuthenticate->expects($this->once()) - ->method('_authenticate') - ->with($this->Request) - ->will($this->returnValue($rawData)); + ->method('_authenticate') + ->with($this->Request) + ->will($this->returnValue($rawData)); $this->SocialAuthenticate->expects($this->once()) ->method('_getProviderName') @@ -186,11 +238,11 @@ public function testGetUserSessionData() { $user = ['username' => 'username', 'email' => 'myemail@test.com']; $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', - '_getProviderName', '_mapUser', '_touch', '_validateConfig' ]); + '_getProviderName', '_mapUser', '_touch', '_validateConfig']); $session = $this->getMockBuilder('Cake\Network\Session') - ->setMethods(['read', 'delete']) - ->getMock(); + ->setMethods(['read', 'delete']) + ->getMock(); $session->expects($this->once()) ->method('read') ->with('Users.social') @@ -201,8 +253,8 @@ public function testGetUserSessionData() ->with('Users.social'); $this->Request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session']) - ->getMock(); + ->setMethods(['session']) + ->getMock(); $this->Request->expects($this->any()) ->method('session') ->will($this->returnValue($session)); @@ -432,7 +484,7 @@ public function testMapUser($data, $mappedData) public function providerMapper() { return [ - [ + [ 'rawData' => [ 'id' => 'my-facebook-id', 'name' => 'My name.', @@ -463,7 +515,7 @@ public function providerMapper() ], 'provider' => 'Facebook' ], - ] + ] ]; } @@ -493,7 +545,7 @@ public function testNormalizeConfig($data, $oauth2, $callTimes, $enabledNoOAuth2 { Configure::write('OAuth2', $oauth2); $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', - '_getProviderName', '_mapUser', '_touch', '_validateConfig', '_normalizeConfig' ]); + '_getProviderName', '_mapUser', '_touch', '_validateConfig', '_normalizeConfig']); $this->SocialAuthenticate->expects($this->exactly($callTimes)) ->method('_normalizeConfig'); From 0a3cbdf5fbf793d0b3664916dd1408c4be743158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 6 Apr 2017 09:22:53 +0100 Subject: [PATCH 0632/1476] refs #add-tests-covering-typo fix cs --- .gitignore | 2 ++ tests/App/Controller/AppController.php | 1 - .../Controller/Component/GoogleAuthenticatorComponentTest.php | 1 - tests/TestCase/Controller/Component/RememberMeComponentTest.php | 1 - 4 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4e2c08050..c89d5a392 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /vendor /.idea composer.lock +.php_cs* +/coverage diff --git a/tests/App/Controller/AppController.php b/tests/App/Controller/AppController.php index 2a2c3675a..4afebdf12 100644 --- a/tests/App/Controller/AppController.php +++ b/tests/App/Controller/AppController.php @@ -23,7 +23,6 @@ */ class AppController extends Controller { - public function initialize() { parent::initialize(); diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index e66faaeef..b94cd798a 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -29,7 +29,6 @@ class GoogleAuthenticatorComponentTest extends TestCase { - public $fixtures = [ 'plugin.CakeDC/Users.users' ]; diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 95e6e756e..0fff648cf 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -29,7 +29,6 @@ */ class RememberMeComponentTest extends TestCase { - public $fixtures = [ 'plugin.CakeDC/Users.users' ]; From cdcfc32dcfd31afb4cdad155baea0a9913f3a894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 6 Apr 2017 09:36:13 +0100 Subject: [PATCH 0633/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index d6dac21e0..dfbcf8d29 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 5 :minor: 0 -:patch: 0 +:patch: 1 :special: '' From 3ea2012b8d03154bcafd7b50ca2d0a46a5962c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 6 Apr 2017 09:36:49 +0100 Subject: [PATCH 0634/1476] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1523c52b2..00edebba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Changelog Releases for CakePHP 3 ------------- +* 5.0.1 + * Bugfix release + * Minor BR language improvements + * 5.0.0 * Some Auth objects refactored into https://github.com/CakeDC/auth * Upgrade to CakePHP 3.4 From 4716b9909ca8c5eb8f714101de5678ec48a97a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 23 Apr 2017 00:42:27 +0100 Subject: [PATCH 0635/1476] refs #538-base-routes fix base issue missing normalize --- .../Component/UsersAuthComponent.php | 2 +- .../Component/UsersAuthComponentTest.php | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 4de4723d9..be65f6ead 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -155,7 +155,7 @@ public function isUrlAuthorized(Event $event) } if (is_array($url)) { - $requestUrl = Router::reverse($url); + $requestUrl = Router::normalize(Router::reverse($url)); $requestParams = Router::parseRequest(new ServerRequest($requestUrl)); } else { try { diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index c469cec29..5221f4ffa 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; +use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotFoundException; @@ -437,4 +438,52 @@ public function testIsUrlAuthorizedUrlArray() $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->data = [ + '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->params === [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_ext' => null, + 'pass' => [], + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } } From 768ba3d8dee99acad78024c1ec33305d6ec5384d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 23 Apr 2017 00:42:27 +0100 Subject: [PATCH 0636/1476] fix cs --- tests/TestCase/Controller/Component/UsersAuthComponentTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 5221f4ffa..1d81bffb4 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -453,8 +453,7 @@ public function testIsUrlAuthorizedBaseUrl() Router::pushRequest(new ServerRequest([ 'base' => '/app', 'url' => '/', - ] - )); + ])); $event = new Event('event'); $event->data = [ 'url' => [ From 9302c6523db05aa1091163795378b6661997c101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 23 Apr 2017 00:49:35 +0100 Subject: [PATCH 0637/1476] refs #538-base-routes fix cs --- tests/TestCase/Controller/Component/UsersAuthComponentTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 1d81bffb4..6c9572576 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; -use Cake\Http\ServerRequest; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotFoundException; @@ -20,6 +19,7 @@ use Cake\Core\Plugin; use Cake\Database\Exception; use Cake\Event\Event; +use Cake\Http\ServerRequest; use Cake\Network\Request; use Cake\Network\Session; use Cake\ORM\Entity; From 3df881785d7c07fb342c19ac545c35a1bab25c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 23 Apr 2017 00:55:20 +0100 Subject: [PATCH 0638/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index dfbcf8d29..6700f56e3 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 5 :minor: 0 -:patch: 1 +:patch: 2 :special: '' From f1858cff9317b201e06539b8c9f5c97dc33db1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 23 Apr 2017 00:56:27 +0100 Subject: [PATCH 0639/1476] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00edebba4..8bafddcc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ Changelog Releases for CakePHP 3 ------------- +* 5.0.2 + * Fixed bug parsing rule urls when application installed in a subdirectory + * 5.0.1 * Bugfix release * Minor BR language improvements From c7acf77140ddf2a784670e7c4bdea6cf864f18bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 23 Apr 2017 00:58:04 +0100 Subject: [PATCH 0640/1476] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f7bf2014d..a20f99bc6 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | | 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | -| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.0.0 | stable | -| 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | 5.0.0 | unstable | +| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.0.2 | stable | +| 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stable | | 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stable | | 3.3 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.0 | stable | From 6006d62d15901a39327769622d71e3e8d099fee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Mon, 24 Apr 2017 10:57:46 +0200 Subject: [PATCH 0641/1476] Patch of bug #544 Changed all setError calls back to error calls This fails on one test. UsersShellTest::testResetAllPasswordsNoPassingParams This test expects a call to the setError method I guess there was a plan to implement the setError method. --- src/Shell/UsersShell.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 27e704418..bfdea13be 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -112,7 +112,7 @@ public function resetAllPasswords() { $password = Hash::get($this->args, 0); if (empty($password)) { - $this->setError(__d('CakeDC/Users', 'Please enter a password.')); + $this->error(__d('CakeDC/Users', 'Please enter a password.')); } $hashedPassword = $this->_generatedHashedPassword($password); $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); @@ -135,10 +135,10 @@ public function resetPassword() $username = Hash::get($this->args, 0); $password = Hash::get($this->args, 1); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($password)) { - $this->setError(__d('CakeDC/Users', 'Please enter a password.')); + $this->error(__d('CakeDC/Users', 'Please enter a password.')); } $data = [ 'password' => $password @@ -163,10 +163,10 @@ public function changeRole() $username = Hash::get($this->args, 0); $role = Hash::get($this->args, 1); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($role)) { - $this->setError(__d('CakeDC/Users', 'Please enter a role.')); + $this->error(__d('CakeDC/Users', 'Please enter a role.')); } $data = [ 'role' => $role @@ -215,7 +215,7 @@ public function passwordEmail() { $reference = Hash::get($this->args, 0); if (empty($reference)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username or email.')); + $this->error(__d('CakeDC/Users', 'Please enter a username or email.')); } $resetUser = $this->Users->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -227,7 +227,7 @@ public function passwordEmail() $this->out($msg); } else { $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); - $this->setError($msg); + $this->error($msg); } } @@ -241,7 +241,7 @@ protected function _changeUserActive($active) { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } $data = [ 'active' => $active @@ -316,7 +316,7 @@ protected function _updateUser($username, $data) { $user = $this->Users->find()->where(['username' => $username])->first(); if (empty($user)) { - $this->setError(__d('CakeDC/Users', 'The user was not found.')); + $this->error(__d('CakeDC/Users', 'The user was not found.')); } $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { @@ -338,7 +338,7 @@ public function deleteUser() { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->setError(__d('CakeDC/Users', 'Please enter a username.')); + $this->error(__d('CakeDC/Users', 'Please enter a username.')); } $user = $this->Users->find()->where(['username' => $username])->first(); if (isset($this->Users->SocialAccounts)) { @@ -346,7 +346,7 @@ public function deleteUser() } $deleteUser = $this->Users->delete($user); if (!$deleteUser) { - $this->setError(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); + $this->error(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); } $this->out(__d('CakeDC/Users', 'The user {0} was deleted successfully', $username)); } From b7539c2c0551d8db6fa7293e656a37fa1aa65a2e Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Mon, 24 Apr 2017 20:16:15 +0300 Subject: [PATCH 0642/1476] added even triggering before social login auth for additional configuration. --- src/Controller/Component/UsersAuthComponent.php | 1 + src/Model/Behavior/SocialBehavior.php | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 4de4723d9..6a11bc920 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -32,6 +32,7 @@ class UsersAuthComponent extends Component const EVENT_AFTER_REGISTER = 'Users.Component.UsersAuth.afterRegister'; const EVENT_BEFORE_LOGOUT = 'Users.Component.UsersAuth.beforeLogout'; const EVENT_AFTER_LOGOUT = 'Users.Component.UsersAuth.afterLogout'; + const EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE = 'Users.Component.UsersAuth.beforeSocialLoginUserCreate'; /** * Initialize method, setup Auth if not already done passing the $config provided and diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 6ce16f8b1..e5fc6c39a 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -11,6 +11,7 @@ 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; @@ -106,6 +107,14 @@ protected function _createSocialUser($data, $options = []) } $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); + + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE, [ + 'userEntity' => $user, + ]); + if ($event->result instanceof EntityInterface) { + $user = $event->result; + } + $this->_table->isValidateEmail = $validateEmail; $result = $this->_table->save($user); From dfb0e3a64f397f048bfae8df45b7a698ca045a75 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Mon, 24 Apr 2017 20:53:22 +0300 Subject: [PATCH 0643/1476] Make social authenticator configurable. --- config/users.php | 2 ++ src/Controller/Component/UsersAuthComponent.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 8254f6d0d..318128ed7 100644 --- a/config/users.php +++ b/config/users.php @@ -59,6 +59,8 @@ 'Social' => [ // enable social login 'login' => false, + // enable social login + 'authenticator' => 'CakeDC/Users.Social', ], 'GoogleAuthenticator' => [ // enable Google Authenticator diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 9f61e231e..769e4d226 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -79,7 +79,7 @@ protected function _loadGoogleAuthenticator() protected function _loadSocialLogin() { $this->getController()->Auth->setConfig('authenticate', [ - 'CakeDC/Users.Social' + Configure::read('Users.Social.authenticator') ], true); } From a4dbba3dd0a9d3ff0f05cc02fae0a6808e5f4374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 25 Apr 2017 15:18:40 +0100 Subject: [PATCH 0644/1476] fix failing test --- tests/TestCase/Shell/UsersShellTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index e376ab2f6..3d242b733 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -43,7 +43,7 @@ public function setUp() $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', - '_generateRandomUsername', '_generatedHashedPassword', 'setError', '_updateUser']) + '_generateRandomUsername', '_generatedHashedPassword', 'error', '_updateUser']) ->setConstructorArgs([$this->io]) ->getMock(); @@ -278,7 +278,7 @@ public function testResetAllPasswords() public function testResetAllPasswordsNoPassingParams() { $this->Shell->expects($this->once()) - ->method('setError') + ->method('error') ->with('Please enter a password.'); $this->Shell->runCommand(['resetAllPasswords']); From c6423abd61877879fe9241bfd08cc6b189c24b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 18 Apr 2017 23:34:05 +0100 Subject: [PATCH 0645/1476] refs #527 do not check for allowed actions in other controllers --- .../Component/UsersAuthComponent.php | 7 ++++ .../Component/UsersAuthComponentTest.php | 37 ++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 769e4d226..cde49bf3a 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -208,6 +208,10 @@ protected function _validateConfig() /** * 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 */ @@ -216,6 +220,9 @@ protected function _isActionAllowed($requestParams = []) if (empty($requestParams['action'])) { return false; } + if (!empty($requestParams['controller']) && $requestParams['controller'] !== $this->getController()->name) { + return false; + } $action = strtolower($requestParams['action']); if (in_array($action, array_map('strtolower', $this->getController()->Auth->allowedActions))) { return true; diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 6c9572576..5f85dbf75 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -74,6 +74,7 @@ public function setUp() ->setMethods(['stop']) ->getMock(); $this->Controller = new Controller($this->request, $this->response); + $this->Controller->name = 'Users'; $this->Registry = $this->Controller->components(); $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); } @@ -267,7 +268,7 @@ public function testIsUrlAuthorizedUrlRelativeString() * test * * @return void - * @expectedException Cake\Routing\Exception\MissingRouteException + * @expectedException \Cake\Routing\Exception\MissingRouteException */ public function testIsUrlAuthorizedMissingRouteString() { @@ -288,7 +289,7 @@ public function testIsUrlAuthorizedMissingRouteString() * test * * @return void - * @expectedException Cake\Routing\Exception\MissingRouteException + * @expectedException \Cake\Routing\Exception\MissingRouteException */ public function testIsUrlAuthorizedMissingRouteArray() { @@ -485,4 +486,36 @@ 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 + * + * 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->data = [ + '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 bed4c98534d9cb4838ae20f3dde56de8fd82cd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 25 Apr 2017 16:13:49 +0100 Subject: [PATCH 0646/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 6700f56e3..75bf20832 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 5 :minor: 0 -:patch: 2 +:patch: 3 :special: '' From 3ea39ad28baef0d60fff19c980bb4e2b502b7b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 25 Apr 2017 16:15:41 +0100 Subject: [PATCH 0647/1476] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bafddcc6..39f171a84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Changelog Releases for CakePHP 3 ------------- +* 5.0.3 + * Implemented event dispatching on social login + * Fixed bugs reported + * Don't check for allowed actions in other controllers + * 5.0.2 * Fixed bug parsing rule urls when application installed in a subdirectory From 51a74644a7048f6e44db7ecf70a005931bdcbe97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 25 Apr 2017 16:16:04 +0100 Subject: [PATCH 0648/1476] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a20f99bc6..8c397f8ac 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | | 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | -| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.0.2 | stable | +| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.0.3 | stable | | 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stable | | 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stable | From 18182259b6cffed1849a77f8f640676adc95380f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 8 May 2017 13:33:55 +0100 Subject: [PATCH 0649/1476] improve example permissions.php file --- config/permissions.php | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/config/permissions.php b/config/permissions.php index 9db03d365..c4e296fa1 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -1,11 +1,11 @@ [ + //admin role allowed to all the things [ - 'role' => '*', - 'plugin' => 'CakeDC/Users', + 'role' => 'admin', + 'prefix' => '*', + 'extension' => '*', + 'plugin' => '*', 'controller' => '*', 'action' => '*', ], + //specific actions allowed for the all roles in Users plugin [ - 'role' => 'user', + 'role' => '*', 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => ['register', 'edit', 'view'], + 'action' => ['profile', 'logout'], ], [ 'role' => '*', @@ -77,17 +81,12 @@ return false; } ], + //all roles allowed to Pages/display [ - 'role' => 'user', - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => '*', - 'allowed' => false, - ], - [ - 'role' => ['user'], - 'controller' => ['Pages'], - 'action' => ['other', 'display'], - 'allowed' => true, + 'role' => '*', + //'plugin' => null, + 'controller' => 'Pages', + 'action' => 'display', ], - ]]; + ] +]; From 0618cb68f3eac5811007dc7cfacdba87eb6701f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 8 May 2017 13:35:40 +0100 Subject: [PATCH 0650/1476] Update permissions.php --- config/permissions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/permissions.php b/config/permissions.php index c4e296fa1..4a9efbfde 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -1,11 +1,11 @@ Date: Mon, 8 May 2017 16:25:40 +0100 Subject: [PATCH 0651/1476] update codesniffer to stable --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 303ead93f..40c825cdf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,9 +33,9 @@ before_script: - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test;'; fi" - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi" - - sh -c "if [ '$PHPCS' = '1' ]; then composer require cakephp/cakephp-codesniffer:dev-master; fi" + - sh -c "if [ '$PHPCS' = '1' ]; then composer require 'cakephp/cakephp-codesniffer:@stable'; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev satooshi/php-coveralls:dev-master; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev 'satooshi/php-coveralls:@stable'; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" script: From 7b9915bde69241b1e071c13fd9959ad059e56a69 Mon Sep 17 00:00:00 2001 From: vagrant Date: Mon, 15 May 2017 22:09:15 +0000 Subject: [PATCH 0652/1476] Added link social --- config/routes.php | 10 + src/Controller/Traits/LinkSocialTrait.php | 168 +++++++++++ src/Controller/UsersController.php | 2 + src/Model/Behavior/LinkSocialBehavior.php | 142 ++++++++++ src/Model/Table/UsersTable.php | 1 + .../Model/Behavior/LinkSocialBehaviorTest.php | 261 ++++++++++++++++++ 6 files changed, 584 insertions(+) create mode 100644 src/Controller/Traits/LinkSocialTrait.php create mode 100644 src/Model/Behavior/LinkSocialBehavior.php create mode 100644 tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php diff --git a/config/routes.php b/config/routes.php index a90bfe630..f19f356a3 100644 --- a/config/routes.php +++ b/config/routes.php @@ -40,3 +40,13 @@ Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); +Router::connect('/link-social/*', [ + 'controller' => 'Users', + 'action' => 'linkSocial', + 'plugin' => 'CakeDC/Users', +]); +Router::connect('/callback-link-social/*', [ + 'controller' => 'Users', + 'action' => 'callbackLinkSocial', + 'plugin' => 'CakeDC/Users', +]); diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php new file mode 100644 index 000000000..c5ce4b94b --- /dev/null +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -0,0 +1,168 @@ +_getSocialProvider($alias); + + $authUrl = $provider->getAuthorizationUrl(); + $this->request->session()->write('SocialLink.oauth2state', $provider->getState()); + + return $this->redirect($authUrl); + } + + /** + * Ação para receber o retorno do provedor (facebook, google) referente ao + * processo de link e autenticação social + * + * @param string $alias of the provider. + * + * @throws \Cake\Network\Exception\NotFoundException Quando o provider informado não existe + * @return \Cake\Network\Response Redirects to profile if okay or error + */ + public function callbackLinkSocial($alias = null) + { + $provider = $this->_getSocialProvider($alias); + if (!$this->_validateCallbackSocialLink()) { + $this->Flash->error('Não foi possivel associar conta, por favor tente novamente'); + + 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(); + $data = $this->_mapSocialUser($alias, $data); + $user = $this->getUsersTable()->get($this->Auth->user('id')); + + $this->getUsersTable()->linkSocialAccount($user, $data); + + if ($user->errors()) { + $error = $user->errors('social_accounts'); + $error = $error ? reset($error) : 'Não foi possivel associar conta, por favor tente novamente'; + $this->Flash->error(is_array($error) ? implode('. ', $error) : $error); + } else { + $this->Flash->success('Conta social associada ao cadastro.'); + } + } 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); + + $this->Flash->error('Não foi possivel associar conta, por favor tente novamente'); + } + + return $this->redirect(['action' => 'profile']); + } + + /** + * Get the provider name based on the request or on the provider set. + * + * @param string $alias of the provider. + * @param array $data User data + * + * @throws MissingProviderException + * @return array + */ + protected function _mapSocialUser($alias, $data) + { + $alias = ucfirst($alias); + $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$alias"; + $providerMapper = new $providerMapperClass($data); + $user = $providerMapper(); + $user['provider'] = $alias; + + return $user; + } + + /** + * Instantiates provider object. + * + * @param string $alias of the provider. + * + * @throws \Cake\Network\Exception\NotFoundException Quando o provider informado não existe + * @return \League\OAuth2\Client\Provider\AbstractProvider + */ + protected function _getSocialProvider($alias) : AbstractProvider + { + $config = Configure::read('OAuth.providers.' . $alias); + if (!$config) { + throw new NotFoundException("Página não encontrada"); + } + + $optionsLink = Configure::read('SocialLink.providers.' . $alias . '.options.redirectUri'); + if (!$optionsLink) { + throw new NotFoundException("Página não encontrada"); + } + + if (is_object($config) && $config instanceof AbstractProvider) { + return $config; + } + + $class = $config['className']; + $config['options']['redirectUri'] = $optionsLink; + + return new $class($config['options'], []); + } + + /** + * Validates OAuth2 request. + * + * @return bool + */ + protected function _validateCallbackSocialLink(): bool + { + $error = $this->request->getQuery('error'); + if (!empty($error)) { + $this->log('Got error in _validateCallbackSocialLink: ' . htmlspecialchars($error, ENT_QUOTES, 'UTF-8')); + + return false; + } + + $queryParams = $this->request->getQueryParams(); + if (!array_key_exists('code', $queryParams)) { + return false; + } + + $sessionKey = 'SocialLink.oauth2state'; + $oauth2state = $this->request->session()->read($sessionKey); + $this->request->session()->delete($sessionKey); + $state = $this->request->getQuery('state'); + + return $oauth2state === $state; + } +} diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 6f5ce97f2..b86bd0940 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\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Controller\Traits\ProfileTrait; use CakeDC\Users\Controller\Traits\ReCaptchaTrait; @@ -30,6 +31,7 @@ */ class UsersController extends AppController { + use LinkSocialTrait; use LoginTrait; use ProfileTrait; use ReCaptchaTrait; diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php new file mode 100644 index 000000000..6079b71d2 --- /dev/null +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -0,0 +1,142 @@ +_table->SocialAccounts->getAlias(); + $socialAccount = $this->_table->SocialAccounts->find() + ->where([ + $alias . '.reference' => $reference, + $alias . '.provider' => Hash::get($data, 'provider') + ])->first(); + + if ($socialAccount && $user->id !== $socialAccount->user_id) { + $user->errors([ + 'social_accounts' => [ + '_existsIn' => 'Conta social já está associada a um conta' + ] + ]); + + return $user; + } + + return $this->createOrUpdateSocialAccount($user, $data, $socialAccount); + } + + /** + * Cria/atualiza conta social associando a um usuário + * + * @param User $user Usuário a linkar + * @param array $data Dados da conta social que será linkada + * @param EntityInterface $socialAccount Entidade SocialAccount para popular + * + * @return EntityInterface + */ + protected function createOrUpdateSocialAccount($user, $data, $socialAccount) + { + if (!$socialAccount) { + $socialAccount = $this->_table->SocialAccounts->newEntity(); + } + + $data['user_id'] = $user->id; + $socialAccount = $this->populateSocialAccount($socialAccount, $data); + + $result = $this->_table->SocialAccounts->save($socialAccount); + + $accounts = (array)$user->social_accounts; + $found = false; + foreach ($accounts as $key => $account) { + if ($account->id == $socialAccount->id) { + $accounts[$key] = $socialAccount; + $found = true; + break; + } + } + if (!$found) { + $accounts[] = $socialAccount; + } + $user->social_accounts = $accounts; + + if ($result && !$result->errors()) { + return $user; + } + + $user->errors($socialAccount->errors()); + + return $user; + } + + /** + * Creates social user, populate the user data based on the social login data first and save it + * + * @param EntityInterface $socialAccount Entidade SocialAccount para popular + * @param array $data Dados da conta social que será linkada + * + * @return EntityInterface + */ + protected function populateSocialAccount($socialAccount, $data) + { + $accountData = $socialAccount->toArray(); + $accountData['username'] = Hash::get($data, 'username'); + $accountData['reference'] = Hash::get($data, 'id'); + $accountData['avatar'] = Hash::get($data, 'avatar'); + $accountData['link'] = Hash::get($data, 'link'); + $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); + $accountData['description'] = Hash::get($data, 'bio'); + $accountData['token'] = Hash::get($data, 'credentials.token'); + $accountData['token_secret'] = Hash::get($data, 'credentials.secret'); + $accountData['user_id'] = Hash::get($data, 'user_id'); + $expires = Hash::get($data, 'credentials.expires'); + if (!empty($expires)) { + $expiresTime = new Time(); + $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); + } else { + $accountData['token_expires'] = null; + } + $accountData['data'] = serialize(Hash::get($data, 'raw')); + $accountData['active'] = true; + + $socialAccount = $this->_table->SocialAccounts->patchEntity($socialAccount, $accountData); + //ensure provider is present in Entity + $socialAccount['provider'] = Hash::get($data, 'provider'); + + return $socialAccount; + } +} diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index b0ce416c0..e604839d9 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -53,6 +53,7 @@ public function initialize(array $config) $this->addBehavior('CakeDC/Users.Register'); $this->addBehavior('CakeDC/Users.Password'); $this->addBehavior('CakeDC/Users.Social'); + $this->addBehavior('CakeDC/Users.LinkSocial'); $this->addBehavior('CakeDC/Users.AuthFinder'); $this->hasMany('SocialAccounts', [ 'foreignKey' => 'user_id', diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php new file mode 100644 index 000000000..f8933d168 --- /dev/null +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -0,0 +1,261 @@ +Table = TableRegistry::get('CakeDC/Users.Users'); + $this->Behavior = new LinkSocialBehavior($this->Table); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->Table, $this->Behavior); + parent::tearDown(); + } + + /** + * Test linkSocialAccount with facebook and not existing social account + * + * @param array $data Test input data + * @param string $userId User id to add social account + * @param array $result Expected result + * + * @author Marcelo Rocha + * @return void + * @dataProvider providerFacebookLinkSocialAccount + */ + public function testlinkSocialAccountFacebookProvider($data, $userId, $result) + { + $user = $this->Table->get($userId); + $resultUser = $this->Behavior->linkSocialAccount($user, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $actual = $resultUser->social_accounts[0]; + + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); + $actual->token_expires = $actual->token_expires->format('Y-m-d H:i:s'); + foreach ($result as $property => $value) { + $this->assertEquals($value, $actual->$property); + } + + $result = $this->Table->SocialAccounts->exists(['id' => $actual->id]); + $this->assertTrue($result); + } + + /** + * Provider for linkSocialAccount with facebook and not existing social account + * + * @author Marcelo Rocha + * @return array + */ + public function providerFacebookLinkSocialAccount() + { + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + return [ + 'provider' => [ + 'data' => [ + 'id' => '9999911112255', //Reference existe mas provider google + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'raw' => [ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link-15579', + 'provider' => 'Facebook' + ], + 'user' => '00000000-0000-0000-0000-000000000001', + 'result' => [ + 'provider' => 'Facebook', + 'username' => null, + 'reference' => '9999911112255', + 'avatar' => '', + 'link' => 'facebook-link-15579', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => $tokenExpires, + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'active' => true + + ] + ] + + ]; + } + + /** + * Test linkSocialAccount with facebook when account already exists + * + * @param array $data Test input data + * @param string $userId User id to add social account + * @param array $result Expected result + * + * @author Marcelo Rocha + * @return void + * @dataProvider providerFacebookLinkSocialAccountAccountExists + */ + public function testlinkSocialAccountFacebookProviderAccountExists($data, $userId, $result) + { + $user = $this->Table->get($userId); + $resultUser = $this->Behavior->linkSocialAccount($user, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $this->assertFalse($resultUser->has('social_accounts')); + $expected = [ + 'social_accounts' => [ + '_existsIn' => 'Conta social já está associada a um conta' + ] + ]; + $actual = $user->errors(); + $this->assertEquals($expected, $actual); + + //Se for o usuário que já esta associado então okay + $socialAccount = $this->Table->SocialAccounts->find()->where([ + 'reference' => $data['id'], + 'provider' => $data['provider'] + ])->firstOrFail(); + + $userBase = $this->Table->get('00000000-0000-0000-0000-000000000002'); + $resultUser = $this->Behavior->linkSocialAccount($userBase, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $this->assertEquals([], $userBase->errors()); + + $actual = $resultUser->social_accounts[0]; + + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); + + $actual->token_expires = $actual->token_expires->format('Y-m-d H:i:s'); + foreach ($result as $property => $value) { + $this->assertEquals($value, $actual->$property); + } + } + + /** + * Provider for linkSocialAccount with facebook when account already exists + * + * @author Marcelo Rocha + * @return array + */ + public function providerFacebookLinkSocialAccountAccountExists() + { + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-2-1', + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'raw' => [ + 'id' => 'reference-2-1', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link-15579', + 'provider' => 'Facebook' + ], + 'user' => '00000000-0000-0000-0000-000000000001', + 'result' => [ + 'id' => '00000000-0000-0000-0000-000000000003', + 'provider' => 'Facebook', + 'username' => null, + 'reference' => 'reference-2-1', + 'avatar' => '', + 'link' => 'facebook-link-15579', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => $tokenExpires, + 'user_id' => '00000000-0000-0000-0000-000000000002', + 'active' => true + ] + ] + + ]; + } +} From 8f8da6ec50a5d9a153d961df9606c0d78fffd51f Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Wed, 17 May 2017 14:40:28 -0500 Subject: [PATCH 0653/1476] Implement dynamic providers --- src/Auth/SocialAuthenticate.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 0fbbe059a..3406144ba 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -201,6 +201,7 @@ protected function _authenticate(ServerRequest $request) $code = $request->getQuery('code'); try { + $token = $provider->getAccessToken('authorization_code', compact('code')); return compact('token') + $provider->getResourceOwner($token)->toArray(); @@ -433,10 +434,10 @@ public function getUser(ServerRequest $request) protected function _getProviderName($request = null) { $provider = false; - if (!is_null($this->_provider)) { - $provider = SocialUtils::getProvider($this->_provider); - } elseif (!empty($request)) { + if (!empty($request->getParam('provider'))) { $provider = ucfirst($request->getParam('provider')); + } elseif (!is_null($this->_provider)) { + $provider = SocialUtils::getProvider($this->_provider); } return $provider; @@ -455,7 +456,7 @@ protected function _mapUser($provider, $data) if (empty($provider)) { throw new MissingProviderException(__d('CakeDC/Users', "Provider cannot be empty")); } - $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; + $providerMapperClass = $this->getConfig('providers.' . strtolower($provider) . '.options.mapper') ?: "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; $providerMapper = new $providerMapperClass($data); $user = $providerMapper(); $user['provider'] = $provider; From be8a9f7db7b2bb6cab62684184b3191a1f42b0c7 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Wed, 17 May 2017 15:00:56 -0500 Subject: [PATCH 0654/1476] Fix phpcs --- src/Auth/SocialAuthenticate.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 3406144ba..4ce4fb648 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -201,7 +201,6 @@ protected function _authenticate(ServerRequest $request) $code = $request->getQuery('code'); try { - $token = $provider->getAccessToken('authorization_code', compact('code')); return compact('token') + $provider->getResourceOwner($token)->toArray(); From 3ee122deabc6a4972c8a27380dc6a9072b28b289 Mon Sep 17 00:00:00 2001 From: Bernat Arlandis Date: Mon, 29 May 2017 17:02:48 +0200 Subject: [PATCH 0655/1476] Update Spanish translations --- src/Locale/es/Users.mo | Bin 15567 -> 15243 bytes src/Locale/es/Users.po | 510 +++++++++++++++++++++++------------------ 2 files changed, 281 insertions(+), 229 deletions(-) diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo index 3e447d98795a6ff4a2c7c6d709bb0deb9a3d1737..50edf1e2bd033c310ec6e9f4fe7a3a8d25ed92d0 100644 GIT binary patch delta 5811 zcmb8xdvp}l9l-IM1QO&8ArKNELlP2_kYtmP#5|OQ@J1d&L=Z(Ly8|q4W;V0C;i>DR zAc$IJkorOtq?oi+Frb`cE0nag!0}O^g?c!x)pI<@9);?$t&g65f4h?u>_2u6zx~{~ zyEF5<_x|pLH#Y287rijN&m)TCI5CF!ps!Nj;FAOR;Mg`qsjF~1jzkAXV<(Qo-=GKo z>Yk4ns#FT+6)3-}!wkFuvoMJKR6P_os-C8iOvhpDhc96Xp2WfUIZ6Wm#yspdEdKja zlp9sK&cIyGmmoh?n@|$D-#y=jeKkqmtoT8ZyEN%2I5?Y`hz< z#{)PM|ADeZQy7jo3kTx$D2c5=xp5F>Aa|hLXDiC@J5Xxo1=l~MG5=%fxJZYr?O-ZQ zZcvHyu?eT(PP`G{!Wt}OxasIaa#FYBc--msA4R$EYsf$KDIZc(NnDhVrplp^g%K@{OAlqG3G4MQjo+=a5ceu-S7 z&Y|pzzei~l&=|y-Ol37n=F@NjwxHC&Hk74#6eW?pD8D<5lHlvO2H!^+Km#Q%H8Kb5 z(8OHqME0L7Whmb-!b!Li>v+C;fQF3VG)l&Aq1@mrl&Kp?#YiztMk$_pKIC`HU85*V zvLD$1>UoqI>qc3cx3L&ML>cJNtoVQ?;&9pjO>V~$l##WeB(x3Xf`?Ixs{>^OXWjF2 zDBJ2Al%TM!igfWmB)?)%Yng z`zn`$kOxgg$#^cx46Q}^{w|d5x7YP3N|ByMS%NoF68SSqEqsfTKpI)el4RvE|8l`R zI%MsdUDu#wxEZAu4q!6AjFRvv?2GTBeE%nuL@%N2j;~Q(NCPOKWE_i93%MxQRiNCb zCZGA2kz7ZIWV#k5)2%2Y*z5K`kMgEGi}JwtP;UG;*Dp{K_!<*2iR@D_8CT+9l*BB& z7Vkt>L!F4y&}e*!Q!%L^p3n@GrSPFl*&f$}C=Wh@Qgp{rM)q5jgx_)f2xX*SqK03i ziJ83imf?LU1B!k`L#q07lqvfTWsQgMI+Gjc;Z<0P^0#0L4#0;|_VFI%-s%ieHtI{1 zk&Wg{8F4*s!g+Wro<>QafC8wK{eKS)>O!4BS%QzT3=>M?H?BY?N8N(5R9mqgpGEGa z{(_TnFndfAZ9)y_p^VT(d0%Y60k{XHXggx(tp6)CDEDbY*}hv)W@Zl##ZxFt_%@E@`RY6k$?y`&2-0|KJcL;& zMRXYD0mpF;o=56TO{j=Z^*oeUbP#3fc3>Xv!v;K!vVHqAO)}5|lp>#rQOR&64RJk6 z(L96$aW@Xb{ixwFtj71;?*~`LAC!r+=%0!*fE`E~sYg)Wh$rzHJdd&@=~eOTa;jK= z8OaHWomceeC$BE?w@!AHrK`< z*oiVjzji$vrO}U$cX1|OKuIKzr%C38C{tOEYz%b^CZLS=7;%)yAbO5Q8Y_rUPlqd; zB=)yuH_FoX9MNCUnnA22eoV;2ib8da2}vghp&3EJ8+pBO%A3 zIK7`tMC?DOxAykLUU1RaUVO>zT;=+6-0!xfE`CA`Cpz6eFK#0S5o?JlgdE{GSA0^d zv89{q_TG)N-F6Z6r>Ldac9WNb9CL_Wu@-+9@TbHB?zyaGo7>LB9}!Xyvfbp6C0b5A zOKc$I*hf4?43-m)#|f!{t;8Ol-+MT;o+A#sJyOZD-1ZLKNh~57h-t(|m zmJu?82Z&U{PgD}?2{{fDPfLSiFR_s@ho&vesvDA;kfMkEmZ|xi=|kTfVwtP_cB>ZDL!ot+?dwV%R+x}7!*7Sen(5RGU+<)* zZgM(OoxZyCbXAWSncy^}HFxbu%S=jM?GJ?w+u5I9-)~{h4gQ#3n&6aYG&}n$2gu2o}_6P$x%qbbJvpx-t^U0LG>B^7&h)3m}`BxGpeHHPMm z*tTJYd-KxtP^{lH)@hcxKW}`Zlby3ATIMM(uhKj9*+JC7Zfit+WjF0SUim< z*J|aSvg%?_WpR0pR#sJ8=_&G*@w@97PI0rXo1uUnw(MGMs$rXYSZlNcy6N+WwEC7< zM}uuyts$Sjp~P#oUdv_X>WIGDC~h|N)>_S(ko#(%s**B~^Leh8+8Fd}%`(gC)QLu~ z5e(}gCwsy>8M+pZFd&AbYkFIx`;cn%hW+hyJ45q|oV>h^gMEh97Lo89%!t#Ow{}E) zVRT#bT4vbRLq_)zy=!=WO~MWHt=1OXP_wLnu5I$%u4eoAR~u_Cv}|pa-fr2GxGd<` zHGUHEujaO9*wB1Tx7X|M?lLvQl%!0(-B_*rxG3bToS5y5E4agXv7k8nvV=G2+8Vv3 z`;gqnXKC$v!0*$2y3?nyvBYosy?!zb8KKxs$@H=-Ll$2KRAbNxaE%pmRuncAU2%b0 z%-w7?Lk}=B`7Aw4&}!sMaslSIGc;FNeo4trNvs3tjDI}rC0y(Nek*W zD;ir%n~R5(WEcG4i=7oEqY}M_v%Vy!uh-Cwfb&$zD7SUIq}XkJQZhk)G_-VLAAS^e zt|=WIZ!9kzoe*{+rCIUQ$4V#WUQuQ&cZl(6-&-Q*Lh1Z!BNS%Q+I26hsumftiEZ5u z8LBB(qan>U0=kzS#5#xgfj83KVYB4Tp7GA9yb;b3PocBdvm_;~w*(Bb`B zROIv*wqZ`jp@g0|r^cx$!# zWqdM6(rJXLOlm^Sv>7_ZXIA7mM=P#P(48+TCOdac-ce>+?1cC(Xt8XYZBwGnHpAT= z?CXFfH!>qeyY=5poVrTOxlp-1{fY^Xy&*KO?u&SxVAZNv*`2E@>gzY#EpJ!9>U$G2 zOZ7>y-MmcpUdUZTHXr-UIaZ?&o6kccj3PvFvy$P6(^fGeofni9OW}%HSBspnwG*;r z-}USuHO*+@T4ssuw~-qJbZ2qxb3(KY%L)Wy!B4dWlMmm@B;6~U8Z-JM?d*MX* zFsy+mArs6GpcZ%~=38(+<9~zNct)`?bWJ534;x?wY=N4;3Cg!^a2ER;myTW>g4*x^ zBnakSI0HTi<;fS}EchMB$GjTzo%s3hp(0gWV$4if2{mqk+W0Cs4z7hVbUpki`2l306UE)C(2DAy^GR1DoJqK^gQeOh8#H2b!TAS`OvuN_ZLUgfi$>CNX~G?`4a%TZPz!cJdE!FNPeIkh(U@o89L9eSYv8+3^QKZr zo8X*M;(raDG!M4JufldX9=B%0t06X+?QkAU$Il;xTKH+m$GpUsYUd5O5Kdw8V%Q30 z_)e(x`uI|W4#ndmvx&comqKlDGt_B00C~kc3YDUB za1ne3PJzFNIBkmfQI1qX8Qu&Rz|F&Sl=B?af_Fou1P zL)An-oC}Y^kc*wH`iEU`z(;oKGdMiex#I$E%?X z*aq8R0EbD7IYUPqybNXO&!8gm9@Oubvbw6b1{T5PP@!H8Wxy7wTxXyRzXvXY$6yis z7F3E}i1`|AC zW%wy517CnL@J%Sg|08~WNiFeLsH!nX8#Y2MycTNX>)|-K6O6519*84Hkes91|IQ$NsdOEFqX+an2;y423$+J)% zUVsPT+i)lJF#mS=61)ahH%3L6g!24;sOmojiMIJU)cPMl)mRNbUZwMYEggm8aLlt% z7QO`?_-iPSCMBZdI1{QEmq9)6gbL|)sEZ{BSHiPU>%I@!(>Tr1{LRo|yf;54|HtW& zMsp6TO5cDgqW54i9N!Wh%TlPwG{R}HD}LSsmAX5iLVXx=0?p^(VfZ&twX=FjH2*p{ zkFgJ{*xwwZa~(Vf6{Dt_Xntuu2>pH;x?#iAA-71 zjzg9-Ux~+WLe;Bes^nAX+4x7D zh?VFg=pJ+wsrl#u^eOalq(%_U0kjpBpf05JjJ9$*$I<7I(s3h7qbp?QYC4}q%3lhp zKxUzbk%LCtnz-{g+#L5QalD!dkLipO7oAC3ECF~Z;ph3RS3gyy3s(XB|W zGJ>%&b1|!9?u9zX_s8Q0;iu7U@wgQx;=YP|3fh96LX(i%@R5k-lW-3jipRoL=rS}7 zeFI&K)aFJoH^3sa0dW=N+x0PZKYS_fk77KXacD8pg><*_-%m&FArzp~8jNW*^zVzu zm%|Xb=r7Q8bPScDo6$m~mPDUNC($9a4sArAKm%wp^3Ydw&wh+fJyK(6x=}AGMYp5v zNbM%nhVImW_C@p@T7{OPJCLb!KAyPK3B6=Ea(wFa0{h&w?~goCTw7qjSCX|CN@f>i z?Z1}1IKk_8Q)&Ci^wT4qGl~oB?wRXHo}XD#XkVS(Zi9+Sd!T&M$eOZo1&dO>87Gx- z_NB6Y&N?^gb^HDv(>3<#R({KRfn8I6bA_Kwx#?BOq@T-V9XB0#ZqJb8CbOwQ&puq< zW?wHKoKuzc!zyPW@CUpgJLIH7C*x-sd!d)f+Km;93jK7C-Bxj+GR!Z>{Aj)S&3L)5 z%_%E&cKHF;h1np-9)2cll=mY)u9#fV<^`U!&kY?n<9I>9dv2ItFPqBrIzxUgaN^}N zUUr`!>>1t0zE*kH$gVj>g(F{Z{g>x4yh(d=p0hWX!fm^vX7|XqYnBzv+~B8OMZ|3E;nR`tcG(TJRd!e7L*aOpmwQ zWj)r%(;m0p>GS&8!OIM$h>eq@w3Obwy>S^PDMK%emQ+b+Jr}QBy}}xycmAxM(sbG6 zF+16}>UR`)ir(D+9ldCoe8ICyX#Iw&=*`7{_NKCQBUQf39rS~G0-X)~p4|SVYcDiZ z7eNQ_6OA(p^=MXOL!KKO7vwq6SUW+lg!ZwCeJ_Pnl<_24V}QFhKLd249ylV=?6V-V87oq z&wkK!aJ<504<{B!opXu0`u`(-%KGrp=zaBx z=FPJrt442vAr6<0m1}?2yvELLnN=29@7Fs6qoJi7cBL||-O^IG?PFvV4>=hbzrUON zhEgHb3YE$xjk8o$m^JGIe8%5SH-GP?ydJm5iS9uT6K|Y9IeGzl_M0u$rM&27vK-5? zh2z>EwOmjB%a*j>!VB?r5Z_|aB3PDppwSsq3m?{6n)~p7)@gLw$wJ`y`ODLGE;-t? zX|qmvpX+q<1C>73e=6(zX)cSjFLyIJZ_u|BTm2;)a^2C1h%VbS_pPpP70jrqQFsEc zCl0vX*LwfNi#1})mhQ?I(OpaH#wXo$dgL2R?-^H9pTB@^A*`|})OpVFXN9nF=n2z6 zI+b*jc59n^Nmt(Hz`ozMpjcJtnYB90RBb?wUD@7RvVpK^#PrY$Q|CuA_Kx=IDHlyN zT{(NEeP!ub@07LpCi+N6#m4%Jw*)5ToIk%MM$djS#~(QS|M23(|3NOW9*RLbcXiaT j+M4*z`TwqVx}(<~tSYk&%jXq@cJuPO;)`Cz;Wqybx1mXB diff --git a/src/Locale/es/Users.po b/src/Locale/es/Users.po index 9748f8420..16f4de825 100644 --- a/src/Locale/es/Users.po +++ b/src/Locale/es/Users.po @@ -4,48 +4,48 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2016-04-20 09:48-0300\n" -"Last-Translator: Jorge González \n" -"PO-Revision-Date: 2016-07-27 11:04+0100\n" +"POT-Creation-Date: 2016-10-26 09:23+0000\n" +"PO-Revision-Date: 2017-05-29 16:50+0100\n" +"Last-Translator: Bernat Arlandis \n" "Language-Team: CakeDC \n" "Language: es_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.4\n" +"X-Generator: Poedit 1.6.10\n" "X-Poedit-SourceCharset: UTF-8\n" -#: Auth/ApiKeyAuthenticate.php:55 +#: Auth/ApiKeyAuthenticate.php:73 msgid "Type {0} is not valid" msgstr "El tipo {0} no es válido" -#: Auth/ApiKeyAuthenticate.php:59 +#: Auth/ApiKeyAuthenticate.php:77 msgid "Type {0} has no associated callable" -msgstr "El tipo {0} no tiene un callable asociado" +msgstr "El tipo {0} no tiene un invocable asociado" -#: Auth/ApiKeyAuthenticate.php:68 +#: Auth/ApiKeyAuthenticate.php:86 msgid "SSL is required for ApiKey Authentication" -msgstr "SSL requerido para autenticación ApiKey" +msgstr "SSL requerido para autenticación por ApiKey" -#: Auth/SimpleRbacAuthorize.php:141 +#: Auth/SimpleRbacAuthorize.php:142 msgid "" "Missing configuration file: \"config/{0}.php\". Using default permissions" msgstr "" "Falta el archivo de configuración: \"config/{0}.php\". Utilizando permisos " "predeterminados" -#: Auth/SocialAuthenticate.php:410 +#: Auth/SocialAuthenticate.php:432 msgid "Provider cannot be empty" msgstr "El proveedor no puede ser vacío" -#: Auth/Rules/AbstractRule.php:77 +#: Auth/Rules/AbstractRule.php:78 msgid "" "Table alias is empty, please define a table alias, we could not extract a " "default table from the request" msgstr "" -"El alias de la tabla es vacío, por favor defina un alias para la tabla ya " -"que no podemos extraer el nombre de la tabla del request" +"El alias de la tabla está vacío, por favor define un alias para la tabla ya " +"que no podemos establecer una tabla predeterminada de la petición" #: Auth/Rules/Owner.php:67;70 msgid "" @@ -67,7 +67,7 @@ msgstr "No se pudo validar la cuenta" msgid "Invalid token and/or social account" msgstr "Token o cuenta social incorrecta" -#: Controller/SocialAccountsController.php:59;86 +#: Controller/SocialAccountsController.php:59;87 msgid "Social Account already active" msgstr "Cuenta social ya activa" @@ -75,19 +75,19 @@ msgstr "Cuenta social ya activa" msgid "Social Account could not be validated" msgstr "No se pudo validar la cuenta social " -#: Controller/SocialAccountsController.php:79 +#: Controller/SocialAccountsController.php:80 msgid "Email sent successfully" msgstr "Email enviado correctamente" -#: Controller/SocialAccountsController.php:81 +#: Controller/SocialAccountsController.php:82 msgid "Email could not be sent" msgstr "No se puede enviar el email" -#: Controller/SocialAccountsController.php:84 +#: Controller/SocialAccountsController.php:85 msgid "Invalid account" msgstr "Cuenta inválida" -#: Controller/SocialAccountsController.php:88 +#: Controller/SocialAccountsController.php:89 msgid "Email could not be resent" msgstr "No se puede reenviar el Email" @@ -95,128 +95,129 @@ msgstr "No se puede reenviar el Email" msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" msgstr "App salt inválido, debe contener al menos 256 bits (32 bytes)" -#: Controller/Component/UsersAuthComponent.php:157 +#: Controller/Component/UsersAuthComponent.php:178 msgid "You can't enable email validation workflow if use_email is false" msgstr "" "No es posible activar el flujo de trabajo para la validación de email si " "use_mail es falso" -#: Controller/Traits/LoginTrait.php:95 +#: Controller/Traits/LoginTrait.php:96 msgid "Issues trying to log in with your social account" -msgstr "Hubo un problema al hacer login con su cuenta" +msgstr "Hubo un problema al iniciar sesión con tu cuenta social" -#: Controller/Traits/LoginTrait.php:100 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 msgid "Please enter your email" -msgstr "Por favor, introduzca su email" +msgstr "Por favor, introduce tu email" -#: Controller/Traits/LoginTrait.php:106 +#: Controller/Traits/LoginTrait.php:108 msgid "" "Your user has not been validated yet. Please check your inbox for " "instructions" msgstr "" -"El usuario no se ha validado todavía, Comprueba tu bandeja de entrada para " -"recuperar el enlace de validación" +"El usuario no se ha validado todavía. Instrucciones enviadas a tu bandeja de " +"entrada" -#: Controller/Traits/LoginTrait.php:108 +#: Controller/Traits/LoginTrait.php:110 msgid "" "Your social account has not been validated yet. Please check your inbox for " "instructions" msgstr "" -"La cuenta no se ha validado todavía, comprueba tu bandeja de entrada para " -"recuperar el enlace de validación" +"La cuenta social no se ha validado todavía. Instrucciones enviadas a tu " +"bandeja de entrada" -#: Controller/Traits/LoginTrait.php:157 Controller/Traits/RegisterTrait.php:73 +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 msgid "Invalid reCaptcha" msgstr "El código reCaptcha no es válido" -#: Controller/Traits/LoginTrait.php:165 +#: Controller/Traits/LoginTrait.php:171 msgid "You are already logged in" -msgstr "Ya te has logueado en la aplicación" +msgstr "Ya has iniciado sesión" -#: Controller/Traits/LoginTrait.php:209 +#: Controller/Traits/LoginTrait.php:217 msgid "Username or password is incorrect" msgstr "Usuario o contraseña incorrecta" -#: Controller/Traits/LoginTrait.php:230 +#: Controller/Traits/LoginTrait.php:238 msgid "You've successfully logged out" -msgstr "Ha cerrado sesión correctamente" +msgstr "Sesión finalizada correctamente" + +#: Controller/Traits/PasswordManagementTrait.php:47;76 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "Usuario no encontrado" -#: Controller/Traits/PasswordManagementTrait.php:53;60;68 +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 msgid "Password could not be changed" msgstr "No es posible cambiar la contraseña" -#: Controller/Traits/PasswordManagementTrait.php:57 +#: Controller/Traits/PasswordManagementTrait.php:68 msgid "Password has been changed successfully" msgstr "Contraseña cambiada correctamente" -#: Controller/Traits/PasswordManagementTrait.php:64 -#: Controller/Traits/ProfileTrait.php:49 -msgid "User was not found" -msgstr "Usuario no encontrado" - -#: Controller/Traits/PasswordManagementTrait.php:66 -msgid "The current password does not match" -msgstr "La contraseña actual no coincide" +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" -#: Controller/Traits/PasswordManagementTrait.php:108 +#: Controller/Traits/PasswordManagementTrait.php:120 msgid "Please check your email to continue with password reset process" msgstr "" -"Por favor, compruebe su correo para continuar con el proceso de " +"Por favor, comprueba tu correo para continuar con el proceso de " "restablecimiento de contraseña" -#: Controller/Traits/PasswordManagementTrait.php:111 Shell/UsersShell.php:266 +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 msgid "The password token could not be generated. Please try again" msgstr "" -"No se pudo generar el token de contraseña. Por favor, inténtelo de nuevo" +"No se pudo generar el token de contraseña. Por favor, inténtalo de nuevo" -#: Controller/Traits/PasswordManagementTrait.php:116 -#: Controller/Traits/UserValidationTrait.php:98 +#: Controller/Traits/PasswordManagementTrait.php:129 +#: Controller/Traits/UserValidationTrait.php:100 msgid "User {0} was not found" msgstr "Usuario {0} no encontrado" -#: Controller/Traits/PasswordManagementTrait.php:118 +#: Controller/Traits/PasswordManagementTrait.php:131 msgid "The user is not active" msgstr "El usuario no está activo" -#: Controller/Traits/PasswordManagementTrait.php:120 -#: Controller/Traits/UserValidationTrait.php:94;102 +#: Controller/Traits/PasswordManagementTrait.php:133 +#: Controller/Traits/UserValidationTrait.php:95;104 msgid "Token could not be reset" msgstr "No se puede restablecer el token" -#: Controller/Traits/ProfileTrait.php:52 +#: Controller/Traits/ProfileTrait.php:53 msgid "Not authorized, please login first" msgstr "" -"No estás autorizado para realizar esta acción, por favor haz login primero" +"No estás autorizado para realizar esta acción, por favor inicia sesión " +"primero" #: Controller/Traits/RegisterTrait.php:42 msgid "You must log out to register a new user account" -msgstr "Debe cerrar sesión para registrar una nueva cuenta de usuario" +msgstr "Debes finalizar la sesión para registrar una nueva cuenta de usuario" -#: Controller/Traits/RegisterTrait.php:79 +#: Controller/Traits/RegisterTrait.php:88 msgid "The user could not be saved" msgstr "No se ha podido guardar el usuario" -#: Controller/Traits/RegisterTrait.php:111 +#: Controller/Traits/RegisterTrait.php:122 msgid "You have registered successfully, please log in" -msgstr "Se ha registrado correctamente, por favor ingrese" +msgstr "Registrado correctamente, por favor inicia sesión" -#: Controller/Traits/RegisterTrait.php:113 +#: Controller/Traits/RegisterTrait.php:124 msgid "Please validate your account before log in" -msgstr "Por favor, valide su cuenta antes de ingresar" +msgstr "Por favor, valida tu cuenta antes de iniciar sesión" -#: Controller/Traits/SimpleCrudTrait.php:76;105 +#: Controller/Traits/SimpleCrudTrait.php:76;106 msgid "The {0} has been saved" msgstr "El {0} ha sido guardado" -#: Controller/Traits/SimpleCrudTrait.php:79;108 +#: Controller/Traits/SimpleCrudTrait.php:80;110 msgid "The {0} could not be saved" msgstr "El {0} no ha podido guardarse" -#: Controller/Traits/SimpleCrudTrait.php:128 +#: Controller/Traits/SimpleCrudTrait.php:130 msgid "The {0} has been deleted" msgstr "El {0} ha sido eliminado" -#: Controller/Traits/SimpleCrudTrait.php:130 +#: Controller/Traits/SimpleCrudTrait.php:132 msgid "The {0} could not be deleted" msgstr "El {0} no ha podido eliminarse" @@ -240,57 +241,57 @@ msgstr "Usuario ya activo" msgid "Reset password token was validated successfully" msgstr "Restablecimiento del token de contraseña validado correctamente" -#: Controller/Traits/UserValidationTrait.php:57 +#: Controller/Traits/UserValidationTrait.php:58 msgid "Reset password token could not be validated" msgstr "Restablecimiento del token de contraseña no pudo validarse" -#: Controller/Traits/UserValidationTrait.php:61 +#: Controller/Traits/UserValidationTrait.php:62 msgid "Invalid validation type" msgstr "Tipo de validación inválido" -#: Controller/Traits/UserValidationTrait.php:64 +#: Controller/Traits/UserValidationTrait.php:65 msgid "Invalid token or user account already validated" -msgstr "Token inválido, or tu cuenta ya se había validado anteriormente" +msgstr "Token inválido, o tu cuenta ya había sido validada anteriormente" -#: Controller/Traits/UserValidationTrait.php:66 +#: Controller/Traits/UserValidationTrait.php:67 msgid "Token already expired" msgstr "Token ya expirado" -#: Controller/Traits/UserValidationTrait.php:92 +#: Controller/Traits/UserValidationTrait.php:93 msgid "Token has been reset successfully. Please check your email." msgstr "" -"Se ha restablecido el token correctamente. Por favor compruebe su email." +"Se ha restablecido el token correctamente. Por favor comprueba tu email." -#: Controller/Traits/UserValidationTrait.php:100 +#: Controller/Traits/UserValidationTrait.php:102 msgid "User {0} is already active" msgstr "El usuario {0} ya está activo" #: Email/EmailSender.php:39 msgid "Your account validation link" -msgstr "Enlace para validar su cuenta" +msgstr "Enlace para validar tu cuenta" #: Mailer/UsersMailer.php:55 msgid "{0}Your reset password link" -msgstr "{0} Enlace para restablecer su contraseña" +msgstr "{0} Enlace para restablecer tu contraseña" #: Mailer/UsersMailer.php:78 msgid "{0}Your social account validation link" -msgstr "{0} Enlace de validación de su cuenta social" +msgstr "{0} Enlace de validación de tu cuenta social" #: Model/Behavior/PasswordBehavior.php:56 msgid "Reference cannot be null" -msgstr "La referencia no puede ser vacía" +msgstr "La referencia no puede estar vacía" #: Model/Behavior/PasswordBehavior.php:61 msgid "Token expiration cannot be empty" -msgstr "La fecha de expiración del Token no puede ser vacía" +msgstr "La fecha de expiración del Token no puede estar vacía" -#: Model/Behavior/PasswordBehavior.php:67;115 +#: Model/Behavior/PasswordBehavior.php:67;116 msgid "User not found" msgstr "Usuario no encontrado" #: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:110 +#: Model/Behavior/RegisterBehavior.php:111 msgid "User account already validated" msgstr "Tu usuario ya se había validado antes" @@ -298,23 +299,27 @@ msgstr "Tu usuario ya se había validado antes" msgid "User not active" msgstr "El usuario no está activo" -#: Model/Behavior/PasswordBehavior.php:120 -msgid "The old password does not match" -msgstr "La antigua contraseña no coincide" +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "La contraseña actual no coincide" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "No puedes usar tu contraseña actual como nueva contraseña" -#: Model/Behavior/RegisterBehavior.php:88 +#: Model/Behavior/RegisterBehavior.php:89 msgid "User not found for the given token and email." msgstr "Usuario no encontrado para el token y email proporcionado" -#: Model/Behavior/RegisterBehavior.php:91 +#: Model/Behavior/RegisterBehavior.php:92 msgid "Token has already expired user with no token" msgstr "El token ha expirado usuario sin token" -#: Model/Behavior/SocialAccountBehavior.php:101;128 +#: Model/Behavior/SocialAccountBehavior.php:102;129 msgid "Account already validated" msgstr "Cuenta ya activada" -#: Model/Behavior/SocialAccountBehavior.php:104;131 +#: Model/Behavior/SocialAccountBehavior.php:105;132 msgid "Account not found for the given token and email." msgstr "Cuenta no encontrada para el token y email proporcionado" @@ -322,26 +327,26 @@ msgstr "Cuenta no encontrada para el token y email proporcionado" msgid "Unable to login user with reference {0}" msgstr "No se puede iniciar sesión con el usuario con referencia {0}" -#: Model/Behavior/SocialBehavior.php:97 +#: Model/Behavior/SocialBehavior.php:98 msgid "Email not present" msgstr "No se encuentra el email" -#: Model/Table/UsersTable.php:81 +#: Model/Table/UsersTable.php:82 msgid "Your password does not match your confirm password. Please try again" msgstr "" -"Su contraseña y la comprobación no concuerdan. Por favor inténtelo de nuevo" +"La contraseña y la comprobación no concuerdan. Por favor inténtalo de nuevo" -#: Model/Table/UsersTable.php:159 +#: Model/Table/UsersTable.php:175 msgid "Username already exists" msgstr "Nombre de usuario ya existente" -#: Model/Table/UsersTable.php:165 +#: Model/Table/UsersTable.php:181 msgid "Email already exists" msgstr "Email ya existente" -#: Model/Table/UsersTable.php:197 +#: Model/Table/UsersTable.php:214 msgid "Missing 'username' in options data" -msgstr "Falta 'username' en los datos de opciones" +msgstr "Falta 'username' en las opciones" #: Shell/UsersShell.php:54 msgid "Utilities for CakeDC Users Plugin" @@ -373,109 +378,109 @@ msgstr "Borrar un usuario" #: Shell/UsersShell.php:61 msgid "Reset the password via email" -msgstr "Resetear la contraseña via email" +msgstr "Restablecer la contraseña vía email" #: Shell/UsersShell.php:62 msgid "Reset the password for all users" -msgstr "Resetear la contraseña de todos los usuarios" +msgstr "Restablecer la contraseña de todos los usuarios" #: Shell/UsersShell.php:63 msgid "Reset the password for an specific user" -msgstr "Resetear la contraseña de un usuario concreto" +msgstr "Restablecer la contraseña de un usuario concreto" -#: Shell/UsersShell.php:97 +#: Shell/UsersShell.php:98 msgid "User added:" msgstr "Usuario añadido:" -#: Shell/UsersShell.php:98;126 +#: Shell/UsersShell.php:99;127 msgid "Id: {0}" msgstr "Id: {0}" -#: Shell/UsersShell.php:99;127 +#: Shell/UsersShell.php:100;128 msgid "Username: {0}" msgstr "Nombre de usuario: {0}" -#: Shell/UsersShell.php:100;128 +#: Shell/UsersShell.php:101;129 msgid "Email: {0}" msgstr "Email: {0}" -#: Shell/UsersShell.php:101;129 +#: Shell/UsersShell.php:102;130 msgid "Password: {0}" msgstr "Contraseña: {0}" -#: Shell/UsersShell.php:125 +#: Shell/UsersShell.php:126 msgid "Superuser added:" msgstr "Superusuario añadido:" -#: Shell/UsersShell.php:131 +#: Shell/UsersShell.php:132 msgid "Superuser could not be added:" msgstr "No se pudo añadir un superusuario:" -#: Shell/UsersShell.php:134 +#: Shell/UsersShell.php:135 msgid "Field: {0} Error: {1}" msgstr "Campo: {0} Error: {1}" -#: Shell/UsersShell.php:152;178 +#: Shell/UsersShell.php:153;179 msgid "Please enter a password." -msgstr "Por favor, introduzca una contraseña." +msgstr "Por favor, introduce una contraseña." -#: Shell/UsersShell.php:156 +#: Shell/UsersShell.php:157 msgid "Password changed for all users" msgstr "Contraseña cambiada para todos los usuarios" -#: Shell/UsersShell.php:157;185 +#: Shell/UsersShell.php:158;186 msgid "New password: {0}" msgstr "Nueva contraseña: {0}" -#: Shell/UsersShell.php:175;203;281;321 +#: Shell/UsersShell.php:176;204;282;324 msgid "Please enter a username." -msgstr "Por favor introduzca nombre de usuario." +msgstr "Por favor introduce el nombre de usuario." -#: Shell/UsersShell.php:184 +#: Shell/UsersShell.php:185 msgid "Password changed for user: {0}" msgstr "Contraseña cambiada para el usuario: {0}" -#: Shell/UsersShell.php:206 +#: Shell/UsersShell.php:207 msgid "Please enter a role." -msgstr "Por favor introduzca rol." +msgstr "Por favor introduce el rol." -#: Shell/UsersShell.php:212 +#: Shell/UsersShell.php:213 msgid "Role changed for user: {0}" msgstr "Rol cambiado para el usuario: {0}" -#: Shell/UsersShell.php:213 +#: Shell/UsersShell.php:214 msgid "New role: {0}" msgstr "Nuevo rol: {0}" -#: Shell/UsersShell.php:228 +#: Shell/UsersShell.php:229 msgid "User was activated: {0}" msgstr "Usuario activado: {0}" -#: Shell/UsersShell.php:243 +#: Shell/UsersShell.php:244 msgid "User was de-activated: {0}" msgstr "Usuario desactivado: {0}" -#: Shell/UsersShell.php:255 +#: Shell/UsersShell.php:256 msgid "Please enter a username or email." -msgstr "Por favor introduzca nombre de usuario o email." +msgstr "Por favor introduce el nombre de usuario o email." -#: Shell/UsersShell.php:263 +#: Shell/UsersShell.php:264 msgid "" "Please ask the user to check the email to continue with password reset " "process" msgstr "" -"Avise al usuario para que compruebe su bandeja de entrada, hemos enviado un " -"email con instrucciones para resetear la contraseña" +"Por favor, pide al usuario que mire su buzón de correo para continuar con el " +"proceso de restablecimiento de su contraseña" -#: Shell/UsersShell.php:300 +#: Shell/UsersShell.php:302 msgid "The user was not found." msgstr "Usuario no encontrado." -#: Shell/UsersShell.php:329 +#: Shell/UsersShell.php:332 msgid "The user {0} was not deleted. Please try again" -msgstr "El usuario {0} NO se ha borrado, por favor inténtelo de nuevo" +msgstr "El usuario {0} no ha sido borrado. Inténtalo de nuevo por favor" -#: Shell/UsersShell.php:331 +#: Shell/UsersShell.php:334 msgid "The user {0} was deleted successfully" msgstr "El usuario {0} se borró correctamente" @@ -490,16 +495,17 @@ msgstr "Hola {0}" #: Template/Email/html/reset_password.ctp:24 msgid "Reset your password here" -msgstr "Restablezca su contraseña aquí" +msgstr "Restablece tu contraseña aquí" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 msgid "" -"If the link is not correctly displayed, please copy the following address in " +"If the link is not correcly displayed, please copy the following address in " "your web browser {0}" msgstr "" -"Si el enlace no se ve correctamente, por favor copie la siguente URL en su " -"navegador: {0}" +"Por favor, copia la siguiente dirección en tu navegador si el enlace no se " +"ve correctamente {0}" #: Template/Email/html/reset_password.ctp:30 #: Template/Email/html/social_account_validation.ctp:35 @@ -512,45 +518,37 @@ msgstr "Gracias" #: Template/Email/html/social_account_validation.ctp:18 msgid "Activate your social login here" -msgstr "Active su acceso social aquí" +msgstr "Activa tu acceso social aquí" #: Template/Email/html/validation.ctp:24 msgid "Activate your account here" -msgstr "Active su cuenta aquí" - -#: 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 "" -"Si el enlace no se muestra correctamente, por favor copie la siguiente " -"dirección en su navegador web {0}" +msgstr "Activa tu cuenta aquí" #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" -msgstr "Por favor copie la siguiente dirección en su navegador web {0}" +msgstr "Por favor copia la siguiente dirección en tu navegador {0}" #: Template/Email/text/social_account_validation.ctp:24 msgid "" "Please copy the following address in your web browser to activate your " "social login {0}" msgstr "" -"Por favor copie la siguiente dirección en su navegador web para activar su " +"Por favor copia la siguiente dirección en tu navegador para activar tu " "acceso social {0}" -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:13 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:13;77 +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 msgid "Actions" msgstr "Acciones" -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:21 -#: Template/Users/view.ctp:17 +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 +#: Template/Users/view.ctp:19 msgid "List Users" msgstr "Listar Usuarios" -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:22 -#: Template/Users/view.ctp:19 +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:21 msgid "List Accounts" msgstr "Listar Cuentas" @@ -558,8 +556,35 @@ msgstr "Listar Cuentas" msgid "Add User" msgstr "Añadir Usuario" -#: Template/Users/add.ctp:32 Template/Users/change_password.ctp:17 -#: Template/Users/edit.ctp:42 Template/Users/register.ctp:32 +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 +#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Usuario" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "Email" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +msgid "First name" +msgstr "Nombre" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Apellidos" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Activo" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 #: Template/Users/request_reset_password.ctp:8 #: Template/Users/resend_token_validation.ctp:20 #: Template/Users/social_email.ctp:19 @@ -568,31 +593,59 @@ msgstr "Enviar" #: Template/Users/change_password.ctp:5 msgid "Please enter the new password" -msgstr "Por favor introduzca la nueva contraseña" +msgstr "Por favor introduce la nueva contraseña" #: Template/Users/change_password.ctp:10 msgid "Current password" msgstr "Contraseña actual" -#: Template/Users/edit.ctp:16 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:99 +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nueva contraseña" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Confirmar contraseña" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:101 msgid "Delete" msgstr "Eliminar" -#: Template/Users/edit.ctp:18 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:16;99 +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:18;101 msgid "Are you sure you want to delete # {0}?" -msgstr "¿Está seguro que quiere eliminar # {0}?" +msgstr "¿Está seguro de que quieres eliminar # {0}?" -#: Template/Users/edit.ctp:28 Template/Users/view.ctp:15 +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 msgid "Edit User" msgstr "Editar Usuario" +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token caduca" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "Api Token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Fecha de activación" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Fecha TOS" + #: Template/Users/index.ctp:15 msgid "New {0}" msgstr "Nuevo {0}" -#: Template/Users/index.ctp:37 Template/Users/view.ctp:95 +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 msgid "View" msgstr "Ver" @@ -600,7 +653,7 @@ msgstr "Ver" msgid "Change password" msgstr "Cambiar contraseña" -#: Template/Users/index.ctp:39 Template/Users/view.ctp:97 +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 msgid "Edit" msgstr "Editar" @@ -614,15 +667,23 @@ msgstr "siguiente" #: Template/Users/login.ctp:19 msgid "Please enter your username and password" -msgstr "Por favor introduzca su usuario y contraseña" +msgstr "Por favor introduce tu usuario y contraseña" #: Template/Users/login.ctp:29 msgid "Remember me" -msgstr "Recordarme" +msgstr "Recuérdame" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Registrarse" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Cambiar contraseña" #: Template/Users/login.ctp:48 msgid "Login" -msgstr "Ingresar" +msgstr "Iniciar sesión" #: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 msgid "{0} {1}" @@ -632,23 +693,15 @@ msgstr "{0} {1}" msgid "Change Password" msgstr "Cambiar contraseña" -#: Template/Users/profile.ctp:27 Template/Users/view.ctp:28;68 -msgid "Username" -msgstr "Usuario" - -#: Template/Users/profile.ctp:29 Template/Users/view.ctp:30 -msgid "Email" -msgstr "Email" - #: Template/Users/profile.ctp:34 msgid "Social Accounts" msgstr "Cuentas sociales" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:70 +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 msgid "Avatar" msgstr "Avatar" -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:67 +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 msgid "Provider" msgstr "Proveedor" @@ -660,13 +713,17 @@ msgstr "Enlace" msgid "Link to {0}" msgstr "Enlace a {0}" -#: Template/Users/register.ctp:25 +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Contraseña" + +#: Template/Users/register.ctp:28 msgid "Accept TOS conditions?" -msgstr "¿Acepta las condiciones del servicios?" +msgstr "¿Aceptas las condiciones del servicios?" #: Template/Users/request_reset_password.ctp:5 msgid "Please enter your email to reset your password" -msgstr "Por favor introduzca su email para restablecer su contraseña" +msgstr "Por favor introduce tu email para restablecer tu contraseña" #: Template/Users/resend_token_validation.ctp:15 msgid "Resend Validation email" @@ -676,71 +733,63 @@ msgstr "Reenviar email de validación" msgid "Email or username" msgstr "Email o usuario" -#: Template/Users/view.ctp:16 +#: Template/Users/view.ctp:18 msgid "Delete User" msgstr "Eliminar Usuario" -#: Template/Users/view.ctp:18 +#: Template/Users/view.ctp:20 msgid "New User" msgstr "Nuevo Usuario" -#: Template/Users/view.ctp:26;65 +#: Template/Users/view.ctp:28;67 msgid "Id" msgstr "Id" -#: Template/Users/view.ctp:32 +#: Template/Users/view.ctp:34 msgid "First Name" msgstr "Nombre" -#: Template/Users/view.ctp:34 +#: Template/Users/view.ctp:36 msgid "Last Name" msgstr "Apellidos" -#: Template/Users/view.ctp:36;71 -msgid "Token" -msgstr "Token" - -#: Template/Users/view.ctp:38 +#: Template/Users/view.ctp:40 msgid "Api Token" msgstr "Api Token" -#: Template/Users/view.ctp:42;73 -msgid "Active" -msgstr "Activo" - -#: Template/Users/view.ctp:46;72 +#: Template/Users/view.ctp:48;74 msgid "Token Expires" msgstr "Token caduca" -#: Template/Users/view.ctp:48 +#: Template/Users/view.ctp:50 msgid "Activation Date" msgstr "Fecha de activación" -#: Template/Users/view.ctp:50 +#: Template/Users/view.ctp:52 msgid "Tos Date" msgstr "Fecha Tos" -#: Template/Users/view.ctp:52;75 +#: Template/Users/view.ctp:54;77 msgid "Created" msgstr "Creado" -#: Template/Users/view.ctp:54;76 +#: Template/Users/view.ctp:56;78 msgid "Modified" msgstr "Modificado" -#: Template/Users/view.ctp:61 +#: Template/Users/view.ctp:63 msgid "Related Accounts" msgstr "Cuentas relacionadas" -#: Template/Users/view.ctp:66 +#: Template/Users/view.ctp:68 msgid "User Id" msgstr "Id Usuario" -#: Template/Users/view.ctp:69 +#: Template/Users/view.ctp:71 msgid "Reference" msgstr "Referencia" -#: Template/Users/view.ctp:74 +#: Template/Users/view.ctp:76 msgid "Data" msgstr "Datos" @@ -756,47 +805,50 @@ msgstr "fa fa-{0}" msgid "btn btn-social btn-{0} " msgstr "btn btn-social btn-{0}" -#: View/Helper/UserHelper.php:90 +#: View/Helper/UserHelper.php:91 msgid "Logout" msgstr "Salir" -#: View/Helper/UserHelper.php:139 +#: View/Helper/UserHelper.php:108 msgid "Welcome, {0}" -msgstr "Bienvenido, {0}" +msgstr "Bienvenido/a, {0}" -#: View/Helper/UserHelper.php:161 +#: View/Helper/UserHelper.php:131 msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" msgstr "" -"reCaptcha no se ha configurado, por favor configure Users.reCaptcha.key" +"reCaptcha no se ha configurado, por favor configura Users.reCaptcha.key" -msgid "SocialAccount already active" -msgstr "Cuenta social ya activa" +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Este campo es requerido" -msgid "" -"The social account is not active. Please check your email for instructions. " -"{0}" -msgstr "" -"La cuenta social está inactiva. Por favor, compruebe las instrucciones en su " -"correo. {0}" +#~ msgid "The old password does not match" +#~ msgstr "La antigua contraseña no coincide" -msgid "There was an error associating your social network account" -msgstr "Hubo un error al asociar su cuenta de la red social" +#~ msgid "SocialAccount already active" +#~ msgstr "Cuenta social ya activa" -msgid "Invalid token and/or email" -msgstr "Token y/o email inválido" +#~ msgid "" +#~ "The social account is not active. Please check your email for " +#~ "instructions. {0}" +#~ msgstr "" +#~ "La cuenta social está inactiva. Por favor, compruebe las instrucciones en " +#~ "su correo. {0}" -msgid "The \"tos\" property is not present" -msgstr "La propiedad \"tos\" no está presente" +#~ msgid "There was an error associating your social network account" +#~ msgstr "Hubo un error al asociar su cuenta de la red social" -msgid "+ {0} secs" -msgstr "+ {0} secs" +#~ msgid "Invalid token and/or email" +#~ msgstr "Token y/o email inválido" -msgid "Sign in with Facebook" -msgstr "Login con Facebook" +#~ msgid "The \"tos\" property is not present" +#~ msgstr "La propiedad \"tos\" no está presente" -msgid "Sign in with Twitter" -msgstr "Login con Twitter" +#~ msgid "+ {0} secs" +#~ msgstr "+ {0} secs" -#: Model/Behavior/RegisterBehavior.php:147 -msgid "This field is required" -msgstr "Este campo es requerido" +#~ msgid "Sign in with Facebook" +#~ msgstr "Login con Facebook" + +#~ msgid "Sign in with Twitter" +#~ msgstr "Login con Twitter" From fe1a946e6bf917ee32cc8b31c4b02522cfca2a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Cansado=20Sola=CC=80?= Date: Tue, 30 May 2017 19:56:26 +0200 Subject: [PATCH 0656/1476] replace deprecated method --- src/Shell/UsersShell.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index bfdea13be..eb8cdd4d6 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -112,7 +112,7 @@ public function resetAllPasswords() { $password = Hash::get($this->args, 0); if (empty($password)) { - $this->error(__d('CakeDC/Users', 'Please enter a password.')); + $this->abort(__d('CakeDC/Users', 'Please enter a password.')); } $hashedPassword = $this->_generatedHashedPassword($password); $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); @@ -135,10 +135,10 @@ public function resetPassword() $username = Hash::get($this->args, 0); $password = Hash::get($this->args, 1); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($password)) { - $this->error(__d('CakeDC/Users', 'Please enter a password.')); + $this->abort(__d('CakeDC/Users', 'Please enter a password.')); } $data = [ 'password' => $password @@ -163,10 +163,10 @@ public function changeRole() $username = Hash::get($this->args, 0); $role = Hash::get($this->args, 1); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); } if (empty($role)) { - $this->error(__d('CakeDC/Users', 'Please enter a role.')); + $this->abort(__d('CakeDC/Users', 'Please enter a role.')); } $data = [ 'role' => $role @@ -215,7 +215,7 @@ public function passwordEmail() { $reference = Hash::get($this->args, 0); if (empty($reference)) { - $this->error(__d('CakeDC/Users', 'Please enter a username or email.')); + $this->abort(__d('CakeDC/Users', 'Please enter a username or email.')); } $resetUser = $this->Users->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -227,7 +227,7 @@ public function passwordEmail() $this->out($msg); } else { $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); - $this->error($msg); + $this->abort($msg); } } @@ -241,7 +241,7 @@ protected function _changeUserActive($active) { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); } $data = [ 'active' => $active @@ -316,7 +316,7 @@ protected function _updateUser($username, $data) { $user = $this->Users->find()->where(['username' => $username])->first(); if (empty($user)) { - $this->error(__d('CakeDC/Users', 'The user was not found.')); + $this->abort(__d('CakeDC/Users', 'The user was not found.')); } $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { @@ -338,7 +338,7 @@ public function deleteUser() { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->error(__d('CakeDC/Users', 'Please enter a username.')); + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); } $user = $this->Users->find()->where(['username' => $username])->first(); if (isset($this->Users->SocialAccounts)) { @@ -346,7 +346,7 @@ public function deleteUser() } $deleteUser = $this->Users->delete($user); if (!$deleteUser) { - $this->error(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); + $this->abort(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); } $this->out(__d('CakeDC/Users', 'The user {0} was deleted successfully', $username)); } From d47e203e6c39ed33840764995c3d77a0bcdea3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Cansado=20Sola=CC=80?= Date: Wed, 31 May 2017 09:16:44 +0200 Subject: [PATCH 0657/1476] fix test --- tests/TestCase/Shell/UsersShellTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 3d242b733..29047c69e 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -278,7 +278,7 @@ public function testResetAllPasswords() public function testResetAllPasswordsNoPassingParams() { $this->Shell->expects($this->once()) - ->method('error') + ->method('abort') ->with('Please enter a password.'); $this->Shell->runCommand(['resetAllPasswords']); From aefa3f56d56374cb786708614d8aa9d4f88ac9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Cansado=20Sola=CC=80?= Date: Fri, 23 Jun 2017 19:28:18 +0200 Subject: [PATCH 0658/1476] display correct subcommand help --- src/Shell/UsersShell.php | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index bfdea13be..250866c43 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -56,15 +56,33 @@ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->setDescription(__d('CakeDC/Users', 'Utilities for CakeDC Users Plugin')) - ->addSubcommand('activateUser')->setDescription(__d('CakeDC/Users', 'Activate an specific user')) - ->addSubcommand('addSuperuser')->setDescription(__d('CakeDC/Users', 'Add a new superadmin user for testing purposes')) - ->addSubcommand('addUser')->setDescription(__d('CakeDC/Users', 'Add a new user')) - ->addSubcommand('changeRole')->setDescription(__d('CakeDC/Users', 'Change the role for an specific user')) - ->addSubcommand('deactivateUser')->setDescription(__d('CakeDC/Users', 'Deactivate an specific user')) - ->addSubcommand('deleteUser')->setDescription(__d('CakeDC/Users', 'Delete an specific user')) - ->addSubcommand('passwordEmail')->setDescription(__d('CakeDC/Users', 'Reset the password via email')) - ->addSubcommand('resetAllPasswords')->setDescription(__d('CakeDC/Users', 'Reset the password for all users')) - ->addSubcommand('resetPassword')->setDescription(__d('CakeDC/Users', 'Reset the password for an specific user')) + ->addSubcommand('activateUser', [ + 'help' => __d('CakeDC/Users', 'Activate an specific user') + ]) + ->addSubcommand('addSuperuser', [ + 'help' => __d('CakeDC/Users', 'Add a new superadmin user for testing purposes') + ]) + ->addSubcommand('addUser', [ + 'help' => __d('CakeDC/Users', 'Add a new user') + ]) + ->addSubcommand('changeRole', [ + 'help' => __d('CakeDC/Users', 'Change the role for an specific user') + ]) + ->addSubcommand('deactivateUser', [ + 'help' => __d('CakeDC/Users', 'Deactivate an specific user') + ]) + ->addSubcommand('deleteUser', [ + 'help' => __d('CakeDC/Users', 'Delete an specific user') + ]) + ->addSubcommand('passwordEmail', [ + 'help' => __d('CakeDC/Users', 'Reset the password via email') + ]) + ->addSubcommand('resetAllPasswords', [ + 'help' => __d('CakeDC/Users', 'Reset the password for all users') + ]) + ->addSubcommand('resetPassword', [ + 'help' => __d('CakeDC/Users', 'Reset the password for an specific user') + ]) ->addOptions([ 'username' => ['short' => 'u', 'help' => 'The username for the new user'], 'password' => ['short' => 'p', 'help' => 'The password for the new user'], From 9e45ecd4b3f2164c632caad91ca5ce3fe86d10e1 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 30 Jun 2017 11:27:26 -0300 Subject: [PATCH 0659/1476] refs #573 making the username field custom --- src/Model/Behavior/SocialBehavior.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index e5fc6c39a..56db02d3e 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -31,6 +31,28 @@ class SocialBehavior extends BaseTokenBehavior use EventDispatcherTrait; use RandomStringTrait; + /** + * Username field it can be modified via config + * + * @var string + */ + protected $_username = 'username'; + + /** + * Initialize an action instance + * + * @param array $config Configuration options passed to the constructor + * @return void + */ + public function initialize(array $config) + { + if (isset($config['username'])) { + $this->_username = $config['username']; + } + + parent::initialize($config); + } + /** * Performs social login * From 701794e5058325d1d5566372ba5d69577e691706 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 30 Jun 2017 11:37:54 -0300 Subject: [PATCH 0660/1476] refs #573 fixing code standard --- src/Model/Behavior/SocialBehavior.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 56db02d3e..6b969a8dd 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -36,8 +36,8 @@ class SocialBehavior extends BaseTokenBehavior * * @var string */ - protected $_username = 'username'; - + protected $_username = 'username'; + /** * Initialize an action instance * @@ -49,7 +49,7 @@ public function initialize(array $config) if (isset($config['username'])) { $this->_username = $config['username']; } - + parent::initialize($config); } From 285cce486becbb3c38e3ea0ea8bb6cebb4be8b83 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 1 Jul 2017 15:04:30 -0300 Subject: [PATCH 0661/1476] Update LinkSocialBehavior.php --- src/Model/Behavior/LinkSocialBehavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php index 6079b71d2..c75c99839 100644 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -61,7 +61,7 @@ public function linkSocialAccount(EntityInterface $user, $data) } /** - * Cria/atualiza conta social associando a um usuário + * Cria/atualiza conta social associando a um usuário. * * @param User $user Usuário a linkar * @param array $data Dados da conta social que será linkada From 1ab354a99242a4ef79ab5871b8ee7592a9bc3171 Mon Sep 17 00:00:00 2001 From: vagrant Date: Sat, 1 Jul 2017 22:27:43 +0000 Subject: [PATCH 0662/1476] fixes for php 5.6 and better testing behavior --- src/Controller/Traits/LinkSocialTrait.php | 27 ++--- src/Model/Behavior/LinkSocialBehavior.php | 31 +++-- .../Model/Behavior/LinkSocialBehaviorTest.php | 106 +++++++++++++++++- 3 files changed, 129 insertions(+), 35 deletions(-) diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index c5ce4b94b..2e0b3d298 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -51,8 +51,9 @@ public function linkSocial($alias = null) public function callbackLinkSocial($alias = null) { $provider = $this->_getSocialProvider($alias); + $message = __d('CakeDC/Users', 'Could not associate account, please try again.'); if (!$this->_validateCallbackSocialLink()) { - $this->Flash->error('Não foi possivel associar conta, por favor tente novamente'); + $this->Flash->error($message); return $this->redirect(['action' => 'profile']); } @@ -69,11 +70,9 @@ public function callbackLinkSocial($alias = null) $this->getUsersTable()->linkSocialAccount($user, $data); if ($user->errors()) { - $error = $user->errors('social_accounts'); - $error = $error ? reset($error) : 'Não foi possivel associar conta, por favor tente novamente'; - $this->Flash->error(is_array($error) ? implode('. ', $error) : $error); + $this->Flash->error($message); } else { - $this->Flash->success('Conta social associada ao cadastro.'); + $this->Flash->success(__d('CakeDC/Users', 'Social account was associated.')); } } catch (\Exception $e) { $message = sprintf( @@ -83,7 +82,7 @@ public function callbackLinkSocial($alias = null) ); $this->log($message); - $this->Flash->error('Não foi possivel associar conta, por favor tente novamente'); + $this->Flash->error($message); } return $this->redirect(['action' => 'profile']); @@ -93,7 +92,7 @@ public function callbackLinkSocial($alias = null) * Get the provider name based on the request or on the provider set. * * @param string $alias of the provider. - * @param array $data User data + * @param array $data User data. * * @throws MissingProviderException * @return array @@ -114,19 +113,15 @@ protected function _mapSocialUser($alias, $data) * * @param string $alias of the provider. * - * @throws \Cake\Network\Exception\NotFoundException Quando o provider informado não existe + * @throws \Cake\Network\Exception\NotFoundException * @return \League\OAuth2\Client\Provider\AbstractProvider */ - protected function _getSocialProvider($alias) : AbstractProvider + protected function _getSocialProvider($alias) { $config = Configure::read('OAuth.providers.' . $alias); - if (!$config) { - throw new NotFoundException("Página não encontrada"); - } - $optionsLink = Configure::read('SocialLink.providers.' . $alias . '.options.redirectUri'); - if (!$optionsLink) { - throw new NotFoundException("Página não encontrada"); + if (!$config || !$optionsLink) { + throw new NotFoundException; } if (is_object($config) && $config instanceof AbstractProvider) { @@ -144,7 +139,7 @@ protected function _getSocialProvider($alias) : AbstractProvider * * @return bool */ - protected function _validateCallbackSocialLink(): bool + protected function _validateCallbackSocialLink() { $error = $this->request->getQuery('error'); if (!empty($error)) { diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php index c75c99839..926f31f02 100644 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -30,10 +30,10 @@ class LinkSocialBehavior extends Behavior protected $_defaultConfig = []; /** - * Linkando uma conta de usuário a uma conta social (facebook, google) + * Link an user account with a social account (facebook, google) * - * @param User $user Usuário a linkar - * @param array $data Dados da conta social que será linkada + * @param EntityInterface $user User to link. + * @param array $data Social account information. * * @return EntityInterface */ @@ -50,7 +50,7 @@ public function linkSocialAccount(EntityInterface $user, $data) if ($socialAccount && $user->id !== $socialAccount->user_id) { $user->errors([ 'social_accounts' => [ - '_existsIn' => 'Conta social já está associada a um conta' + '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') ] ]); @@ -61,15 +61,15 @@ public function linkSocialAccount(EntityInterface $user, $data) } /** - * Cria/atualiza conta social associando a um usuário. + * Create or update a new social account linking to the user. * - * @param User $user Usuário a linkar - * @param array $data Dados da conta social que será linkada - * @param EntityInterface $socialAccount Entidade SocialAccount para popular + * @param EntityInterface $user User to link. + * @param array $data Social account information. + * @param EntityInterface $socialAccount to update or create. * * @return EntityInterface */ - protected function createOrUpdateSocialAccount($user, $data, $socialAccount) + protected function createOrUpdateSocialAccount(EntityInterface $user, $data, $socialAccount) { if (!$socialAccount) { $socialAccount = $this->_table->SocialAccounts->newEntity(); @@ -89,6 +89,7 @@ protected function createOrUpdateSocialAccount($user, $data, $socialAccount) break; } } + if (!$found) { $accounts[] = $socialAccount; } @@ -98,16 +99,14 @@ protected function createOrUpdateSocialAccount($user, $data, $socialAccount) return $user; } - $user->errors($socialAccount->errors()); - return $user; } /** - * Creates social user, populate the user data based on the social login data first and save it + * Populate the social account * - * @param EntityInterface $socialAccount Entidade SocialAccount para popular - * @param array $data Dados da conta social que será linkada + * @param EntityInterface $socialAccount to populate. + * @param array $data Social account information. * * @return EntityInterface */ @@ -123,13 +122,13 @@ protected function populateSocialAccount($socialAccount, $data) $accountData['token'] = Hash::get($data, 'credentials.token'); $accountData['token_secret'] = Hash::get($data, 'credentials.secret'); $accountData['user_id'] = Hash::get($data, 'user_id'); + $accountData['token_expires'] = null; $expires = Hash::get($data, 'credentials.expires'); if (!empty($expires)) { $expiresTime = new Time(); $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); - } else { - $accountData['token_expires'] = null; } + $accountData['data'] = serialize(Hash::get($data, 'raw')); $accountData['active'] = true; diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index f8933d168..e4fafb277 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -76,13 +76,16 @@ public function tearDown() */ public function testlinkSocialAccountFacebookProvider($data, $userId, $result) { - $user = $this->Table->get($userId); + $user = $this->Table->get($userId, [ + 'contain' => 'SocialAccounts' + ]); $resultUser = $this->Behavior->linkSocialAccount($user, $data); $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); - $actual = $resultUser->social_accounts[0]; + $actual = $resultUser->social_accounts[2]; $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); $actual->token_expires = $actual->token_expires->format('Y-m-d H:i:s'); + foreach ($result as $property => $value) { $this->assertEquals($value, $actual->$property); } @@ -152,6 +155,103 @@ public function providerFacebookLinkSocialAccount() ]; } + /** + * Test linkSocialAccount with facebook and could not save social account + * + * @param array $data Test input data + * @param string $userId User id to add social account + * @param array $result Expected result + * + * @author Marcelo Rocha + * @return void + * @dataProvider providerFacebookLinkSocialAccountErrorSaving + */ + public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId, $result) + { + $user = $this->Table->get($userId); + $resultUser = $this->Behavior->linkSocialAccount($user, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $actual = $resultUser->social_accounts[0]; + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); + + $actual = $user->errors(); + + $expected = [ + 'social_accounts' => [ + [ + 'token' => [ + '_empty' => 'This field cannot be left empty' + ] + ] + ] + ]; + $this->assertEquals($expected, $actual); + + $error = $user->errors('social_accounts'); + $error = $error ? reset($error) : $message; + } + + /** + * Provider for linkSocialAccount with facebook and could not save social account + * + * @author Marcelo Rocha + * @return array + */ + public function providerFacebookLinkSocialAccountErrorSaving() + { + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + return [ + 'provider' => [ + 'data' => [ + 'id' => '9999911112255', //Reference existe mas provider google + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'raw' => [ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => '', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link-15579', + 'provider' => 'Facebook' + ], + 'user' => '00000000-0000-0000-0000-000000000001', + 'result' => [ + 'provider' => 'Facebook', + 'username' => null, + 'reference' => '9999911112255', + 'avatar' => '', + 'link' => 'facebook-link-15579', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => $tokenExpires, + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'active' => true + + ] + ] + + ]; + } + /** * Test linkSocialAccount with facebook when account already exists * @@ -171,7 +271,7 @@ public function testlinkSocialAccountFacebookProviderAccountExists($data, $userI $this->assertFalse($resultUser->has('social_accounts')); $expected = [ 'social_accounts' => [ - '_existsIn' => 'Conta social já está associada a um conta' + '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') ] ]; $actual = $user->errors(); From e6c43c621ab8e2b5d71acce7cda1568bbc54b5e9 Mon Sep 17 00:00:00 2001 From: rochamarcelo Date: Sat, 1 Jul 2017 22:41:01 +0000 Subject: [PATCH 0663/1476] better code coverage --- tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index e4fafb277..9344ac513 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -283,7 +283,9 @@ public function testlinkSocialAccountFacebookProviderAccountExists($data, $userI 'provider' => $data['provider'] ])->firstOrFail(); - $userBase = $this->Table->get('00000000-0000-0000-0000-000000000002'); + $userBase = $this->Table->get('00000000-0000-0000-0000-000000000002', [ + 'contain' => ['SocialAccounts'] + ]); $resultUser = $this->Behavior->linkSocialAccount($userBase, $data); $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); $this->assertEquals([], $userBase->errors()); From bab8752b7bb04893302e79953fe85752b3bb062a Mon Sep 17 00:00:00 2001 From: rochamarcelo Date: Sun, 2 Jul 2017 02:17:08 +0000 Subject: [PATCH 0664/1476] testing new trait --- src/Controller/Traits/LinkSocialTrait.php | 33 +- .../Controller/Traits/LinkSocialTraitTest.php | 737 ++++++++++++++++++ 2 files changed, 760 insertions(+), 10 deletions(-) create mode 100644 tests/TestCase/Controller/Traits/LinkSocialTraitTest.php diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 2e0b3d298..261eb0d3b 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -64,7 +64,9 @@ public function callbackLinkSocial($alias = null) $token = $provider->getAccessToken('authorization_code', compact('code')); $data = compact('token') + $provider->getResourceOwner($token)->toArray(); + $data = $this->_mapSocialUser($alias, $data); + $user = $this->getUsersTable()->get($this->Auth->user('id')); $this->getUsersTable()->linkSocialAccount($user, $data); @@ -75,12 +77,12 @@ public function callbackLinkSocial($alias = null) $this->Flash->success(__d('CakeDC/Users', 'Social account was associated.')); } } catch (\Exception $e) { - $message = sprintf( + $log = sprintf( "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", $e->getMessage(), $e ); - $this->log($message); + $this->log($log); $this->Flash->error($message); } @@ -119,15 +121,27 @@ protected function _mapSocialUser($alias, $data) protected function _getSocialProvider($alias) { $config = Configure::read('OAuth.providers.' . $alias); + $optionsLink = Configure::read('SocialLink.providers.' . $alias . '.options.redirectUri'); + if (!$config || !$optionsLink) { throw new NotFoundException; } - if (is_object($config) && $config instanceof AbstractProvider) { - return $config; - } + return $this->_createSocialProvider($config, $optionsLink); + } + /** + * Instantiates provider object. + * + * @param array $config for social provider. + * @param string $optionsLink to use as redirect. + * + * @throws \Cake\Network\Exception\NotFoundException + * @return \League\OAuth2\Client\Provider\AbstractProvider + */ + protected function _createSocialProvider($config, $optionsLink) + { $class = $config['className']; $config['options']['redirectUri'] = $optionsLink; @@ -141,14 +155,13 @@ protected function _getSocialProvider($alias) */ protected function _validateCallbackSocialLink() { - $error = $this->request->getQuery('error'); - if (!empty($error)) { - $this->log('Got error in _validateCallbackSocialLink: ' . htmlspecialchars($error, ENT_QUOTES, 'UTF-8')); + $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; } - $queryParams = $this->request->getQueryParams(); if (!array_key_exists('code', $queryParams)) { return false; } @@ -156,7 +169,7 @@ protected function _validateCallbackSocialLink() $sessionKey = 'SocialLink.oauth2state'; $oauth2state = $this->request->session()->read($sessionKey); $this->request->session()->delete($sessionKey); - $state = $this->request->getQuery('state'); + $state = $queryParams['state']; return $oauth2state === $state; } diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php new file mode 100644 index 000000000..793c2305c --- /dev/null +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -0,0 +1,737 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\LinkSocialTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; + + parent::setUp(); + $request = new ServerRequest(); + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set']) + ->getMockForTrait(); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->request = $request; + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * mock request for GET + * + * @return void + */ + protected function _mockRequestGet($withSession = false) + { + $methods = ['is', 'referer', 'getData', 'getQuery', 'getQueryParams']; + + if ($withSession) { + $methods[] = 'session'; + } + + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods($methods) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + } + + /** + * test linkSocial method + * + * @return void + */ + public function testLinkSocialHappy() + { + Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->_mockRequestGet(true); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->_mockSession([]); + $this->Trait->Flash->expects($this->never()) + ->method('error'); + + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAuthorizationUrl', 'getState']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAuthorizationUrl') + ->will($this->returnValue('http://localhost/fake/facebook/login')); + + $ProviderMock->expects($this->once()) + ->method('getState') + ->will($this->returnValue('a3423ja9ads90u3242309')); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] + ]), + $this->equalTo('/callback-link-social/facebook') + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo('http://localhost/fake/facebook/login') + ); + + $this->Trait->linkSocial('facebook'); + } + + /** + * test + * + * @return void + */ + public function testLinkSocialNotDefineSocialLinkRedictUri() + { + $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('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + + $Table = TableRegistry::get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->once()) + ->method('getQuery') + ->with('code') + ->will($this->returnValue('99999000222220')); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('error'); + + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with(__d('CakeDC/Users', 'Social account was associated.')); + + $fbToken = new AccessToken([ + 'access_token' => 'token', + 'tokenSecret' => null, + 'expires' => 1458423682 + ]); + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo([ + 'code' => '99999000222220' + ]) + )->will($this->returnValue($fbToken)); + + $fbUser = new FacebookUser([ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'username' => 'mock_username', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'Location' => 'mock_home', + 'bio' => 'mock_description', + 'link' => 'facebook-link-15579', + ]); + $ProviderMock->expects($this->once()) + ->method('getResourceOwner') + ->with( + $this->equalTo($fbToken) + )->will($this->returnValue($fbUser)); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] + ]), + $this->equalTo('/callback-link-social/facebook') + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + + $actual = $Table->SocialAccounts->find('all')->where(['reference' => '9999911112255'])->firstOrFail(); + + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + $expected = [ + 'provider' => 'Facebook', + 'username' => 'mock_username', + 'reference' => '9999911112255', + 'avatar' => 'https://graph.facebook.com/9999911112255/picture?type=large', + 'description' => 'mock_description', + 'token' => 'token', + 'token_secret' => null, + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'active' => true + ]; + foreach ($expected as $property => $value) { + $check = $actual->$property; + $this->assertEquals($value, $actual->$property); + } + $this->assertEquals($tokenExpires, $actual->token_expires->format('Y-m-d H:i:s')); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialWithValidationErrors() + { + Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + $user = TableRegistry::get('akeDC/Users.Users')->get('00000000-0000-0000-0000-000000000001'); + $user->errors([ + 'social_accounts' => [ + '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') + ] + ]); + $Table = $this->getMockForModel('CakeDC/Users.Users', ['linkSocialAccount', 'get']); + $Table->setAlias('Users'); + + $Table->expects($this->once()) + ->method('get') + ->will($this->returnValue($user)); + + $Table->expects($this->once()) + ->method('linkSocialAccount') + ->will($this->returnValue($user)); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->once()) + ->method('getQuery') + ->with('code') + ->will($this->returnValue('99999000222220')); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $fbToken = new AccessToken([ + 'access_token' => 'token', + 'tokenSecret' => null, + 'expires' => 1458423682 + ]); + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo([ + 'code' => '99999000222220' + ]) + )->will($this->returnValue($fbToken)); + + $fbUser = new FacebookUser([ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'username' => 'mock_username', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'Location' => 'mock_home', + 'bio' => 'mock_description', + 'link' => 'facebook-link-15579', + ]); + $ProviderMock->expects($this->once()) + ->method('getResourceOwner') + ->with( + $this->equalTo($fbToken) + )->will($this->returnValue($fbUser)); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] + ]), + $this->equalTo('/callback-link-social/facebook') + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + + $actual = $Table->SocialAccounts->exists(['reference' => '9999911112255']); + $this->assertFalse($actual); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialFailGettingAccessToken() + { + Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + + $Table = TableRegistry::get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->once()) + ->method('getQuery') + ->with('code') + ->will($this->returnValue('99999000222220')); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo([ + 'code' => '99999000222220' + ]) + )->will($this->throwException(new \Exception)); + + $ProviderMock->expects($this->never()) + ->method('getResourceOwner'); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] + ]), + $this->equalTo('/callback-link-social/facebook') + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + + $actual = $Table->SocialAccounts->exists(['reference' => '9999911112255']); + $this->assertFalse($actual); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialQueryHasErrors() + { + Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + + $Table = TableRegistry::get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->never()) + ->method('getQuery'); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'error' => 'We got some error', + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo(['action' => 'profile']) + ); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->never()) + ->method('getAccessToken'); + + $ProviderMock->expects($this->never()) + ->method('getResourceOwner'); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] + ]), + $this->equalTo('/callback-link-social/facebook') + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialWrongState() + { + Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + + $Table = TableRegistry::get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->never()) + ->method('getQuery'); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'bd393j2942789' + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo(['action' => 'profile']) + ); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->never()) + ->method('getAccessToken'); + + $ProviderMock->expects($this->never()) + ->method('getResourceOwner'); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] + ]), + $this->equalTo('/callback-link-social/facebook') + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialMissingCode() + { + Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + + $Table = TableRegistry::get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->never()) + ->method('getQuery'); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'state' => 'bd393j2942789' + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo(['action' => 'profile']) + ); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $this->Trait->callbackLinkSocial('facebook'); + } +} From 7b4da8344ec5a608beba215fdd80e905cc498cd9 Mon Sep 17 00:00:00 2001 From: rochamarcelo Date: Sun, 2 Jul 2017 02:32:29 +0000 Subject: [PATCH 0665/1476] phpcs fixes --- .../Controller/Traits/LinkSocialTraitTest.php | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 793c2305c..f1424be03 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -132,11 +132,11 @@ public function testLinkSocialHappy() ->method('_createSocialProvider') ->with( $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' - ] + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] ]), $this->equalTo('/callback-link-social/facebook') ) @@ -265,11 +265,11 @@ public function testCallbackLinkSocialHappy() ->method('_createSocialProvider') ->with( $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' - ] + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] ]), $this->equalTo('/callback-link-social/facebook') ) @@ -406,11 +406,11 @@ public function testCallbackLinkSocialWithValidationErrors() ->method('_createSocialProvider') ->with( $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' - ] + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] ]), $this->equalTo('/callback-link-social/facebook') ) @@ -495,11 +495,11 @@ public function testCallbackLinkSocialFailGettingAccessToken() ->method('_createSocialProvider') ->with( $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' - ] + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] ]), $this->equalTo('/callback-link-social/facebook') ) @@ -582,11 +582,11 @@ public function testCallbackLinkSocialQueryHasErrors() ->method('_createSocialProvider') ->with( $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' - ] + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] ]), $this->equalTo('/callback-link-social/facebook') ) @@ -665,11 +665,11 @@ public function testCallbackLinkSocialWrongState() ->method('_createSocialProvider') ->with( $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' - ] + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.5', + 'redirectUri' => '/auth/facebook' + ] ]), $this->equalTo('/callback-link-social/facebook') ) From 7db29c9f12faf13c9667204b575182970ef22844 Mon Sep 17 00:00:00 2001 From: Aleksander Meloch Date: Sun, 2 Jul 2017 12:56:30 +0200 Subject: [PATCH 0666/1476] Added polish translation --- src/Locale/pl/Users.mo | Bin 0 -> 14520 bytes src/Locale/pl/Users.po | 811 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 811 insertions(+) create mode 100644 src/Locale/pl/Users.mo create mode 100644 src/Locale/pl/Users.po diff --git a/src/Locale/pl/Users.mo b/src/Locale/pl/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..c5a1c88a33dc06eb0a6a1831ac6d7b562e8516b6 GIT binary patch literal 14520 zcmb`Md6XqpeaB105eHDj5f?Nm5uF*FZh9IJ?3odoo*o#O&FStL#kKmq>h9`(ujX1z-7V+Cb%Ikh=@v18Dm@qqsbwJoaxpRjhg5&9?+9N)EpB%8keZYCCle~@2z@E z_dqbI)4%tvyVSkE``hmC-u~w^PkyJz^Ev2Q(6=AwdA|kUcPc+TH$BPoo&dfHJPUjW z_zdtU_y^!3I0SyzmDil%d5@=j0jPePz-NL};2(lDkgnd_9DV>?MfsE9Dd1G0LA{s6d|`Zs}31#flbqYgg< zYW@enlfW;4;`fW-YrwC8THggv@w~0z7^rz}0-p=M7d#)l9~2)y28X~^Fe$z-b~p-Z zJy(NT=N|BM@D-r=n+LVN1}J_Gf#-mS!Iyw{gI9pR0;QizS&Z;X@HFrxp!j+fsBvqc z*6~_Uj=o7_ZEI6w~x5;r$DuT5tKcB z9hCgO2Ws4(fU?h1FoqX^PXncoG0+E7Q1jgi%CGJN`NVq=lt26oTo0a3L2|qp6yICH z=Yi9p^nVj5y}Sn$A9sT4_eoIveFdBYzX^)}%P?-)$5r4aFb2;BkAnPpU*!i;dOrlU zj+0DbkGMkf@DE`0X$`69_r{99on-+;G zz0<+Vz_s8oI0woeZg==45LUe3f{4m{CWFhbF9u%s1Ro2&3zVGR3rfEq0_9KlgYSHd=lu()aSmYwu+mrK z>2(B@e_aM@{ZkH0pyYeN;p;)o|5i|PeK)9eA9dx2K+XRnQ0x8`D0^N5lN$GIhwDL_ zyo*7_lUIWJE^+NG@MOw2g3{N`;N!r%K+SuP!~4Khl)nnfF8;}te*jAVKLz>oPQ%Ew z{tG~TzYoOpya<&1ZvZ|Q1TmHXZ>>@ zDF6K%P;vSn96n~fmCG==lltA@Dc~IrKMZQ!p8&f!BSn$3I z%5HxLil1j-+~Ri_6hAKoWiN+7MD4u;RR6zr^$&s4&(A=u?>C^ne=0_>8r%d@*|33!B->*T%pEVa)`yK+HL^%L40q+1P zdEEiZejWhD&-X#e?{}c&w&p^M8$qpS7pV2V1=M$+2DPpSL9P4Ou6*`I)?PP(KJ~jm zmh2^<#{VFw`Tr7>oWBi<|9^GuKL@8MpZY?}e*nIS@-3kB@%Nzm{|r0}{7(>7cxx`U z@p~M63FY^Ln(rr|?C}(WtME)v-#-i739bbdzZ;Meule)myljJB1HBbG50an06OtTX59!%r!MhEVoX>#vKt6N? zN}yfPen`*9Efl|!ndI{7qQ>qoYbbx#)y+8kGw?3=F5i1MbS8Av)s?`TpwppwNcNy7 zv(WR48JN7{YFB$0-0t3Gf2hlQ8zkN9xeB_~ym{UZ@WarXU0HT;z`aW+H$a%Tu|HK0 zK#Hw@3bi0TAA;TwJy8Xo_d?S98=*U({CNj2AB8^YDio`(bnkxx-U97~E`zp0e*~Qb zy&c*B>A_XJ0J<4^2DB5>b1w8sNcQwxNO9$4=z1uBFiY=K&^>tt__40{I`7v&e*vxP zs;}}c`+hcb$km?%&O)DtJ_kJ=ilJlBYDj*g=Pl4F&}Qg%NO9*q&>utjGtEm48i8(f zl?`ws^g8Hn=qXSHT?AbV>G=rs0lo0t3ALdRS_|n>4EiASCg>GV|8pG`bA6SMrTki` z4806`8Z-{+xdIw9Z^TIOa`*mZunA2-3$E^c;6dmtXcDSG&w}0n?Ss}sdOo3_(LLM! zELjL+Z?sejYneZ}d%`azaXHGOBu+0?b<&74Kd98hpxp8g29>BBWMR2zp}kV}<0SK^ z!xfsNfX_%VtY?KS>Rg@lXNk>8o{{tWwVZBP@aCQ{Klnn&-@ma6&jeCEMT!?#-_@ zU>Ro&GGEhW{_sUF^rxdN_19f6>`%9{FkO%J$Fs#C^>8exWu>{Gs4+o7?s-09bPnTO zs;`d|bIw?y&%%$3{;oz|m9=W2w>?c8Vd`h~mIQ#+qVjGR6wx|EViqZ(^$ zb;*KhTnp3in{yFwrMa-QpplYh%q(+J%_kyMH9P^-_@Jin4-H@6H6lJZ+o%Vc&7WbI z5&s;bE|upq&0uY=cFrK4qG8M7Owg!c+nqtZok^LnhtKXJ0%>vPrEpx;<^^lps!>Sj zlq9KLxJ=N<=8}5U?lMjr7YPz+=IzO2Oa8)o6@+Xw4=NSoVrkK@r&;T^Gj_i2-Yncu zosZ{&6uV_}$S3L90rElIkk*re6vY$pjEu1WqYhJJwiOu#f+ZX`LTgtww<2G$LLnp3 z9^>tCjwx+g+xz{#e{_xwcSU$LUf;7dNk=(fk8a$qF9~^AUr-ptU_NBtAiG#rDRIiZ ze7xHT;)Ff=8l(&Di@BJ4XESRw_wI?L?lvVKuBy zBYU=vz1qRb{yv*L$?2^SRG)P=bX&~Vf+$GLFy9sPs}=h;aiDzZ<=&mn_Lq8!@s*Hu zT=+yC`qQix`W=jdo(1)&&SqG9m5}6at%*CqVPay3w#<5Xpb^zwWErhRSBEWsl<0(= zMkNy|y@_Zx&Nm2e!e((U(ihu~@u#rA^#nrf9V7K78q-x0l?f$vCZez_hvkv3ik^X7 zt8!+OCQh2Y0VSgbR%DE**z*bGQOu_7b`aBRgWps#kSjR6Hmk!wee$Spcbl1dQZ+G6 zG9tP3CJDkOO!3A5eVLnIPS{pu$<=^O-SjDxzJgKBhU{E2-a+4m8@6OWm<`x2HGYvD zbg|l#>#LIyS7#}-r@=wCsG`kfMNU6OwMe#*ppjgNgyEyuo^G;Y z2*+?1Rk%7J{3ync1qQ!3#5-p!{e?ru}N$0S0G+N*d+^NJO-n5V|Z_BJ~W-C}~Mz z`^g-Ui>POJc3A07LyLG0n>ml>z@;)L3!A{$Pu(2>Qy2FUVrea-cMmDU*NSy6p}FXr zZ{=F34wkmDP(yE&x0#MPM0B0*3)k&LbTfm?GjlhxPOC#B2}j2vT47cU(B=D4Je^!? z6dc8AR&ThQ88fh1>;KDe(^>381CCX_%7DF@0Ojh{i`g$d&in_Xq>*}^UCM@xWv~h*Q#0U1F@>!FjC_%!UJ#VNf0McZ}}3Vruk?aewpp&e82V zE*sstb?^AZ#EXl5BV1Cf-no6}c!%qagF~ywI7N|)4Je3@_!*)-lVLq&K|X8 zYI57aC7piaf%JJ`oKR8bBs=0?!X3nF!azN!3~Wp4)pW#bt$o7c@-F4XHfRS#|6IOJbkG-3cRaXapJd=Gz*pv zC;mK*ez1_Wnri1VP_IF0KJXXl$n{=CYRz3vQeHY7_-V9wo41Rqq#Os8u#Mgl*Rfn7 zzhi`1w*fc&h}$0wt>K3Q_Aaz<>YiCk^KS0Oe8F!VEd-V!D#cFHSJGXcWgd!f2$8c=5>MjeVD#*Hoi$=?0}-2;Ez;#EBK1!P7!L%#0j!y%{;|NwQ`X*2_zO zm5(x&u}`$ofVX=(EWx=OeXI1y4W~5OFU_g6v2+8w8^66`UZHBd+`^8y-xT!r9yc20 z1{nQ1^;%0pj#v!3l#x`ErTY*}v&EtVMAD3cazf?prO18c*@29eRgWK=T{>(nQ=QFM zsPFQ6u+VEs`B#<3G=gt8gO!-eO}sOZoy*;`!AJZ`VbzU}Y+D8p(L zJju@T`_QYxrQ0i!*|rSN^H>NIEZvT3GVUH*_)4uFG?BpuKV3*_5t7pcrM59FBJKhf zYu%z&Z-=uLCJ*X3sb)fG`Z~hb5{^*TqAw&jh z%p!1JO9`@?ufo}Uesd}tH+QGOeAZg;SxI!xMZN5Bvum<-3EetQT1%D=hoyFGGz!Cy z^nsC9C*WYEJ!@lzR*j&gf5ph1_qWn)@klLNI*eHB3AuK)<+qhqm{1m0{Wf05cyHs3m2-Okof;m)ijW*>5<5!6OwzyPe)#ubL^P z?}k=qZ&(q}ig&AGoqw|=RZOxH6S=xZC+Z~S)=XqJ0>nUM>z+&%MF{D7xBfy!pu5(f zD7K8q_P45>sEIv=R=g`aF)lXygAGe&am}=iQWqjIR)~24J2WA2S@*6!Zek*5fMCs# zD{fA9_T2f|=x_v$8#=x$|D)6V{~}pPmToAuTQ~>3f|%%Q$Hl3Peh9VvOKN`c2zo2E zGurJ==KbG3AM_?3O=RF-AaI*+mN09*PX_y_#xeTZWA;L;5$-rm$!t7%LGhG@c1zxu z%lCe=La$}6dY11>)m z&PW>O19)ggi$`#0J9|Lbs0G?f*g|NG`6miPXrHJ=^KNZ<-a^hnm@x@Cdxcw+3&lvp zgo`33+8Ep?ICs@yY`74nOYjJhRy^bh%cglGm+WQA^v3p9PEYz)VC3J<)u_PQiW{u2 z*U`GX-ey1j0nmEuloFpd|KO`2MoH4$qc%y?S4w%cfEBhCwgsb7lOK}&nSY!2_|Ay7hCC4}W8fItO1(_#x{fQ?_1>ttXmy*0 z;nP^=2ET3YT9r|lTUNKPcw5^T+CpQV-O;<8Eb~6LpgfRwl9aBzqMM~=%UqKZ-C@jZ z@Qp!#qEQKKi6NPA{YCZ5?0pyx2r-FvWW zFJ3VFXKvNXvgKYarLsELa8ujaPwd94%KYSlYUsYw%Csx1XJ7W&ncxH++CeQ!1AI#D z%h~F#ExPW}e+#V9vT}QPFuzpJ25I0N*%X!zcT2WyT(MhA{Cly^f3mW=zqWIKx_0H5 z_AqnUrkwv`nz&_TMUHZ!J#f&TwyepT6eYh9HF1JWu3+4aZyFNuhNR%|ZN6pT=dp>YW`MnOd@^Vga-G)>Qm+!wQPKQCA^t$?uI98U2m8njz zjx$>0w*u%sNp}xvq;sN1BjZOnZFkR{E4Wxi%SF~M?(#l_nf`7o2u40r9QL}WlI8b{ z!LGF3xiaWpsL`yl^WNOo((-;!&w>S}O!d$0dCtp;xe@42QrH!3zMGIgrwwk2(y+Rr zU{djsF1Z)x2OhhjDgo^TchZ^sY-)~0xGi@OlP1g46=6?iqYN&;n&1S10PiDmA30Gx z9z5ZWErTn(5d)JximW&eA30u4c4dc;da!hX1SDQSMoD=(O6sLH$;JQTE|+`D#oKCe z;OSm~j8r#p#olRjSgeV&sXg6Ep5b$Rl6zZbBbGrh_muwS@bK5WU25n_2tD~_SEF%p JbK}+W{s$j5;Di7G literal 0 HcmV?d00001 diff --git a/src/Locale/pl/Users.po b/src/Locale/pl/Users.po new file mode 100644 index 000000000..7c7834fe0 --- /dev/null +++ b/src/Locale/pl/Users.po @@ -0,0 +1,811 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-07-02 20:08+0200\n" +"PO-Revision-Date: 2017-07-02 20:08+0200\n" +"Last-Translator: \n" +"Language-Team: LANGUAGE \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 2.0.1\n" + +#: Auth/ApiKeyAuthenticate.php:73 +msgid "Type {0} is not valid" +msgstr "Typ {0} jest nieprawidłowy" + +#: Auth/ApiKeyAuthenticate.php:77 +msgid "Type {0} has no associated callable" +msgstr "Brak callable dla typu {0}" + +#: Auth/ApiKeyAuthenticate.php:86 +msgid "SSL is required for ApiKey Authentication" +msgstr "Uwierzytelnienie ApiKey wymaga SSL" + +#: Auth/SimpleRbacAuthorize.php:142 +msgid "" +"Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" +"Brak pliku konfiguracji: \"config/{0}.php\". Użyto domyślnych uprawnień" + +#: Auth/SocialAuthenticate.php:432 +msgid "Provider cannot be empty" +msgstr "Dostawca nie może być pusty" + +#: Auth/Rules/AbstractRule.php:78 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a " +"default table from the request" +msgstr "Alias tabeli jest pusty, zdefiniuj alias tabeli" + +#: Auth/Rules/Owner.php:67;70 +msgid "" +"Missing column {0} in table {1} while checking ownership permissions for " +"user {2}" +msgstr "" +"Nieistniejąca kolumna {0} w tabeli {0} podczas sprawdzania uprawnień dla " +"użytkownika {2}" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Konto zostało aktywowane" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Aktywacja konta nie powiodła się" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Nieprawidłowy token lub konto społecznościowe" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Konto społecznościowe jest już aktywne" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Aktywacja nie powiodła się" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "E-mail został wysłany" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "E-mail nie mógł zostać wysłany" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Nieprawidłowe konto" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Nie można wysłać wiadomości e-mail" + +#: Controller/Component/RememberMeComponent.php:69 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Nieprawidłowa sól aplikacji, sól aplikacji powinna mieć długość co najmniej " +"256 bitów (32 bajty)" + +#: Controller/Component/UsersAuthComponent.php:178 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Nie możesz włączyć potwierdzania kont przez e-mail jeśli opcja use_email = " +"false" + +#: Controller/Traits/LoginTrait.php:96 +msgid "Issues trying to log in with your social account" +msgstr "" +"Wystąpiły problemy z logowaniem za pośrednictwem konta społecznościowego" + +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Podaj swój adres e-mail" + +#: Controller/Traits/LoginTrait.php:108 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Twoje konto nie zostało jeszcze aktywowane. Sprawdź swoją skrzynkę odbiorczą" + +#: Controller/Traits/LoginTrait.php:110 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Konto społecznościowe nie zostało jeszcze aktywowane. Sprawdź swoją pocztę e-" +"mail." + +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +msgid "Invalid reCaptcha" +msgstr "Błąd reCaptcha" + +#: Controller/Traits/LoginTrait.php:171 +msgid "You are already logged in" +msgstr "Jesteś już zalogowany" + +#: Controller/Traits/LoginTrait.php:217 +msgid "Username or password is incorrect" +msgstr "Nazwa użytkownika lub hasło jest nieprawidłowe" + +#: Controller/Traits/LoginTrait.php:238 +msgid "You've successfully logged out" +msgstr "Wylogowano" + +#: Controller/Traits/PasswordManagementTrait.php:47;76 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "Konto użytkownika nie istnieje" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +msgid "Password could not be changed" +msgstr "Zmiana hasła nie powiodła się" + +#: Controller/Traits/PasswordManagementTrait.php:68 +msgid "Password has been changed successfully" +msgstr "Hasło zostało zmienione" + +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:120 +msgid "Please check your email to continue with password reset process" +msgstr "Aby dokończyć zmianę hasła, sprawdź swoją pocztę e-mail." + +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +msgid "The password token could not be generated. Please try again" +msgstr "Nie można wygenerować tokenu. Spróbuj ponownie" + +#: Controller/Traits/PasswordManagementTrait.php:129 +#: Controller/Traits/UserValidationTrait.php:100 +msgid "User {0} was not found" +msgstr "Nie znaleziono użytkownika {0}" + +#: Controller/Traits/PasswordManagementTrait.php:131 +msgid "The user is not active" +msgstr "Konto użytkownika nie jest aktywne" + +#: Controller/Traits/PasswordManagementTrait.php:133 +#: Controller/Traits/UserValidationTrait.php:95;104 +msgid "Token could not be reset" +msgstr "Nie można zresetować tokenu" + +#: Controller/Traits/ProfileTrait.php:53 +msgid "Not authorized, please login first" +msgstr "Wymagane logowanie" + +#: Controller/Traits/RegisterTrait.php:42 +msgid "You must log out to register a new user account" +msgstr "Wyloguj się aby utworzyć nowe konto" + +#: Controller/Traits/RegisterTrait.php:88 +msgid "The user could not be saved" +msgstr "Nie można utworzyć konta" + +#: Controller/Traits/RegisterTrait.php:122 +msgid "You have registered successfully, please log in" +msgstr "Rejestracja zakończona sukcesem, możesz się zalogować" + +#: Controller/Traits/RegisterTrait.php:124 +msgid "Please validate your account before log in" +msgstr "Potwierdź swoje konto przed logowaniem" + +#: Controller/Traits/SimpleCrudTrait.php:76;106 +msgid "The {0} has been saved" +msgstr "{0} został zapisany" + +#: Controller/Traits/SimpleCrudTrait.php:80;110 +msgid "The {0} could not be saved" +msgstr "{0} nie mógł zostać zapisany" + +#: Controller/Traits/SimpleCrudTrait.php:130 +msgid "The {0} has been deleted" +msgstr "{0} został usunięty" + +#: Controller/Traits/SimpleCrudTrait.php:132 +msgid "The {0} could not be deleted" +msgstr "{0} nie mógł zostać usunięty" + +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "Błąd walidacji reCaptcha" + +#: Controller/Traits/UserValidationTrait.php:42 +msgid "User account validated successfully" +msgstr "Konto użytkownika zostało aktywowane" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account could not be validated" +msgstr "Aktywacja konta nie powiodła się" + +#: Controller/Traits/UserValidationTrait.php:47 +msgid "User already active" +msgstr "Konto jest już aktywne" + +#: Controller/Traits/UserValidationTrait.php:53 +msgid "Reset password token was validated successfully" +msgstr "Token zmiany hasła został zatwierdzony" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "Błąd podczas walidacji tokenu zmiany hasła" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Invalid validation type" +msgstr "Nieprawidłowy typ walidacji" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token or user account already validated" +msgstr "Nieprawidłowy token lub konto jest już aktywne" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Token wygasł" + +#: Controller/Traits/UserValidationTrait.php:93 +msgid "Token has been reset successfully. Please check your email." +msgstr "Token został zresetowany. Sprawdź swoją pocztę e-mail." + +#: Controller/Traits/UserValidationTrait.php:102 +msgid "User {0} is already active" +msgstr "Użytkownik {0} jest już aktywny" + +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Twój link aktywacyjny" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0}Twój link zmiany hasła" + +#: Mailer/UsersMailer.php:78 +msgid "{0}Your social account validation link" +msgstr "{0} Twój link aktywacyjny" + +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "Wartość nie może być pusta" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "Parametr 'expiration' nie może być pusty" + +#: Model/Behavior/PasswordBehavior.php:67;116 +msgid "User not found" +msgstr "Nie odnaleziono użytkownika" + +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:111 +msgid "User account already validated" +msgstr "Konto użytkownika zostało już aktywowane" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "Użytkownik nie jest aktywny" + +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "Bieżące hasło nie jest prawidłowe" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "Nowe hasło nie może być takie same jak obecne" + +#: Model/Behavior/RegisterBehavior.php:89 +msgid "User not found for the given token and email." +msgstr "Nie odnaleziono użytkownika dla danego tokenu i adresu e-mail." + +#: Model/Behavior/RegisterBehavior.php:92 +msgid "Token has already expired user with no token" +msgstr "Token wygasł" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Konto zostało już aktywowane" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "Nie odnaleziono konta dla danego tokenu i adresu e-mail." + +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "Nie można zalogować użytkownika o loginie {0}" + +#: Model/Behavior/SocialBehavior.php:98 +msgid "Email not present" +msgstr "Brak adresu e-mail" + +#: Model/Table/UsersTable.php:82 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Podane hasła różnią się. Spróbuj ponownie." + +#: Model/Table/UsersTable.php:175 +msgid "Username already exists" +msgstr "Nazwa użytkownika już istnieje" + +#: Model/Table/UsersTable.php:181 +msgid "Email already exists" +msgstr "Adres e-mail już istnieje" + +#: Model/Table/UsersTable.php:214 +msgid "Missing 'username' in options data" +msgstr "Brak klucza 'username'" + +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Narzędzia dla CakeDC Users Plugin" + +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Aktywuj użytkownika" + +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "Dodaj konto administracyjne do celów testowych" + +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "Dodaj użytkownika" + +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Zmień rolę konkretnego użytkownika" + +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "Deaktywuj użytkownika" + +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Usuń użytkownika" + +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "Zresetuj hasło przez e-mail" + +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "Zresetuj hasło dla wszystkich użytkowników" + +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "Zresetuj hasło dla konkretnego użytkownika" + +#: Shell/UsersShell.php:98 +msgid "User added:" +msgstr "Dodano użytkownika:" + +#: Shell/UsersShell.php:99;127 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Username: {0}" +msgstr "Nazwa użytkownika: {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Email: {0}" +msgstr "E-mail: {0}" + +#: Shell/UsersShell.php:102;130 +msgid "Password: {0}" +msgstr "Hasło: {0}" + +#: Shell/UsersShell.php:126 +msgid "Superuser added:" +msgstr "Dodano super użytkownika:" + +#: Shell/UsersShell.php:132 +msgid "Superuser could not be added:" +msgstr "Nie można dodać super użytkownika:" + +#: Shell/UsersShell.php:135 +msgid "Field: {0} Error: {1}" +msgstr "Pole: {0} Błąd: {1}" + +#: Shell/UsersShell.php:153;179 +msgid "Please enter a password." +msgstr "Podaj hasło." + +#: Shell/UsersShell.php:157 +msgid "Password changed for all users" +msgstr "Zmieniono hasło dla wszystkich użytkowników" + +#: Shell/UsersShell.php:158;186 +msgid "New password: {0}" +msgstr "Nowe hasło: {0}" + +#: Shell/UsersShell.php:176;204;282;324 +msgid "Please enter a username." +msgstr "Podaj nazwę użytkownika." + +#: Shell/UsersShell.php:185 +msgid "Password changed for user: {0}" +msgstr "Zmieniono hasło dla użytkownika: {0}" + +#: Shell/UsersShell.php:207 +msgid "Please enter a role." +msgstr "Podaj rolę." + +#: Shell/UsersShell.php:213 +msgid "Role changed for user: {0}" +msgstr "Zmieniono rolę dla użytkownika: {0}" + +#: Shell/UsersShell.php:214 +msgid "New role: {0}" +msgstr "Nowa rola: {0}" + +#: Shell/UsersShell.php:229 +msgid "User was activated: {0}" +msgstr "Użytkownik został aktywowany: {0}" + +#: Shell/UsersShell.php:244 +msgid "User was de-activated: {0}" +msgstr "Użytkownik został zdeaktywowany: {0}" + +#: Shell/UsersShell.php:256 +msgid "Please enter a username or email." +msgstr "Podaj nazwę użytkownika lub hasło." + +#: Shell/UsersShell.php:264 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "Aby dokończyć zmianę hasła, sprawdź swoją pocztę e-mail" + +#: Shell/UsersShell.php:302 +msgid "The user was not found." +msgstr "Nie odnaleziono użytkownika." + +#: Shell/UsersShell.php:332 +msgid "The user {0} was not deleted. Please try again" +msgstr "Usuwanie użytkownika {0} nie powiodło się. Spróbuj ponownie" + +#: Shell/UsersShell.php:334 +msgid "The user {0} was deleted successfully" +msgstr "Użytkownik {0} został usunięty" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Witaj {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Kontynuuj zmianę hasła" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correcly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Jeśli link nie jest wyświetlony poprawnie, skopiuj łącze do paska adresu " +"przeglądarki {0}" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Dziękujemy" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Aktywuj konto" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Aktywuj konto" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Skopiuj łącze do paska adresu przeglądarki {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "Skopiuj łącze do paska adresu przeglądarki, aby aktywować konto {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 +msgid "Actions" +msgstr "Akcje" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 +#: Template/Users/view.ctp:19 +msgid "List Users" +msgstr "Użytkownicy" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:21 +msgid "List Accounts" +msgstr "Konta" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +msgid "Add User" +msgstr "Dodaj użytkownika" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 +#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Nazwa użytkownika" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "E-mail" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +msgid "First name" +msgstr "Imię" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Nazwisko" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Aktywny" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Wyślij" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Podaj nowe hasło" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Obecne hasło" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nowe hasło" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Potwierdź hasło" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:101 +msgid "Delete" +msgstr "Usuń" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:18;101 +msgid "Are you sure you want to delete # {0}?" +msgstr "Czy na pewno usunąć # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Edytuj użytkownika" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token wygasa" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Data aktywacji" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Data (TOS)" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nowy {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +msgid "View" +msgstr "Szczegóły" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Zmień hasło" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +msgid "Edit" +msgstr "Edytuj" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "poprzednia" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "następna" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Podaj nazwę użytkownika i hasło" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Zapamiętaj" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Rejestracja" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Zresetuj hasło" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Zaloguj" + +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:24 +msgid "Change Password" +msgstr "Zmień hasło" + +#: Template/Users/profile.ctp:34 +msgid "Social Accounts" +msgstr "Konta społecznościowe" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +msgid "Provider" +msgstr "Dostawca" + +#: Template/Users/profile.ctp:40 +msgid "Link" +msgstr "Link" + +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Link do {0}" + +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Hasło" + +#: Template/Users/register.ctp:28 +msgid "Accept TOS conditions?" +msgstr "Akceptuję warunki użytkowania" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "W celu zmiany hasła podaj adres e-mail" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Ponownie wyślij e-mail aktywacyjny" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "E-mail lub nazwa użytkownika" + +#: Template/Users/view.ctp:18 +msgid "Delete User" +msgstr "Usuń użytkownika" + +#: Template/Users/view.ctp:20 +msgid "New User" +msgstr "Nowy użytkownik" + +#: Template/Users/view.ctp:28;67 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:34 +msgid "First Name" +msgstr "Imię" + +#: Template/Users/view.ctp:36 +msgid "Last Name" +msgstr "Nazwisko" + +#: Template/Users/view.ctp:40 +msgid "Api Token" +msgstr "Api Token" + +#: Template/Users/view.ctp:48;74 +msgid "Token Expires" +msgstr "Token wygasa" + +#: Template/Users/view.ctp:50 +msgid "Activation Date" +msgstr "Data aktywacji" + +#: Template/Users/view.ctp:52 +msgid "Tos Date" +msgstr "Data (TOS)" + +#: Template/Users/view.ctp:54;77 +msgid "Created" +msgstr "Utworzono" + +#: Template/Users/view.ctp:56;78 +msgid "Modified" +msgstr "Zmodyfikowano" + +#: Template/Users/view.ctp:63 +msgid "Related Accounts" +msgstr "Powiązane konta" + +#: Template/Users/view.ctp:68 +msgid "User Id" +msgstr "Id użytkownika" + +#: Template/Users/view.ctp:71 +msgid "Reference" +msgstr "Reference" + +#: Template/Users/view.ctp:76 +msgid "Data" +msgstr "Dane" + +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Zaloguj się za pomocą" + +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:91 +msgid "Logout" +msgstr "Wyloguj" + +#: View/Helper/UserHelper.php:108 +msgid "Welcome, {0}" +msgstr "Witaj, {0}" + +#: View/Helper/UserHelper.php:131 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha nie zostało skonfigurowane! Skonfiguruj opcję Users.reCaptcha.key" + +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Pole wymagane" From 327e4fe83e7c2c546f5e9229b32bc904e8d1704d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 5 Jul 2017 19:32:37 +0100 Subject: [PATCH 0667/1476] Update Translations.md --- Docs/Documentation/Translations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index f6d98f83d..2e2553f3b 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -7,6 +7,7 @@ The Plugin is translated into several languages: * Spanish (es) by @florenciohernandez * Brazillian Portuguese (pt_BR) by @andtxr * French (fr_FR) by @jtraulle +* Polish (pl) by @joulbex **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 1414871e04aaecec21742074c4672e4918d3f648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 11 Jul 2017 11:50:16 +0100 Subject: [PATCH 0668/1476] Update 4.x-5.0.md --- Docs/Documentation/Migration/4.x-5.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Migration/4.x-5.0.md b/Docs/Documentation/Migration/4.x-5.0.md index 6cd858a23..1382c4331 100644 --- a/Docs/Documentation/Migration/4.x-5.0.md +++ b/Docs/Documentation/Migration/4.x-5.0.md @@ -2,7 +2,7 @@ Migration 4.x to 5.0 ====================== 5.0 is compatible with CakePHP ^3.4 and refactored some Auth objects into a new plugin -* Fix your Users configuration file for Auth object references +* Fix your Users configuration file, usually under `config/users.php` for Auth object references in `users.php` From 655b273060f629b6d471b78abc4102f3d4c0cf2b Mon Sep 17 00:00:00 2001 From: Aleksander Meloch Date: Sat, 15 Jul 2017 22:15:46 +0200 Subject: [PATCH 0669/1476] Improve logout events --- src/Controller/Traits/LoginTrait.php | 6 ++++-- tests/TestCase/Controller/Traits/LoginTraitTest.php | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 3a813c5cc..7ead3f08d 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -352,7 +352,9 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen */ public function logout() { - $eventBefore = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGOUT); + $user = (array)$this->Auth->user(); + + $eventBefore = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGOUT, ['user' => $user]); if (is_array($eventBefore->result)) { return $this->redirect($eventBefore->result); } @@ -360,7 +362,7 @@ public function logout() $this->request->session()->destroy(); $this->Flash->success(__d('CakeDC/Users', 'You\'ve successfully logged out')); - $eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT); + $eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT, ['user' => $user]); if (is_array($eventAfter->result)) { return $this->redirect($eventAfter->result); } diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 97031f7a3..0550b2711 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -253,7 +253,7 @@ public function testLogout() { $this->_mockDispatchEvent(new Event('event')); $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['logout']) + ->setMethods(['logout', 'user']) ->disableOriginalConstructor() ->getMock(); $redirectLogoutOK = '/'; From c8b54c5c3a922119094bdb0956e9ae8542f89d79 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 9 Aug 2017 11:24:02 +0000 Subject: [PATCH 0670/1476] Moving configuration from SocialLink to Oauth --- src/Controller/Traits/LinkSocialTrait.php | 18 ++- .../Controller/Traits/LinkSocialTraitTest.php | 140 ++++++++++++++---- 2 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 261eb0d3b..e3f8a11e6 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -121,29 +121,33 @@ protected function _mapSocialUser($alias, $data) protected function _getSocialProvider($alias) { $config = Configure::read('OAuth.providers.' . $alias); + if (!$config || !isset($config['options'], $config['options']['callbackLinkSocialUri'])) { + throw new NotFoundException; + } - $optionsLink = Configure::read('SocialLink.providers.' . $alias . '.options.redirectUri'); - - if (!$config || !$optionsLink) { + if (!isset($config['options']['clientId'], $config['options']['clientSecret'])) { throw new NotFoundException; } - return $this->_createSocialProvider($config, $optionsLink); + return $this->_createSocialProvider($config); } /** * Instantiates provider object. * * @param array $config for social provider. - * @param string $optionsLink to use as redirect. * * @throws \Cake\Network\Exception\NotFoundException * @return \League\OAuth2\Client\Provider\AbstractProvider */ - protected function _createSocialProvider($config, $optionsLink) + protected function _createSocialProvider($config) { $class = $config['className']; - $config['options']['redirectUri'] = $optionsLink; + $redirectUri = $config['options']['callbackLinkSocialUri']; + + unset($config['options']['callbackLinkSocialUri'], $config['options']['linkSocialUri']); + + $config['options']['redirectUri'] = $redirectUri; return new $class($config['options'], []); } diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index f1424be03..7f3e21657 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -25,6 +25,13 @@ class LinkSocialTraitTest extends BaseTraitTest { + /** + * Keep the original config for oauth + * + * @var array + */ + private $oauthConfig; + /** * Fixtures * @@ -42,6 +49,9 @@ 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']; @@ -66,6 +76,7 @@ public function setUp() */ public function tearDown() { + Configure::write('OAuth', $this->oauthConfig); parent::tearDown(); } @@ -98,7 +109,8 @@ protected function _mockRequestGet($withSession = false) */ public function testLinkSocialHappy() { - Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) @@ -135,10 +147,13 @@ public function testLinkSocialHappy() 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' ] - ]), - $this->equalTo('/callback-link-social/facebook') + ]) ) ->will($this->returnValue($ProviderMock)); @@ -156,8 +171,60 @@ public function testLinkSocialHappy() * * @return void */ - public function testLinkSocialNotDefineSocialLinkRedictUri() + public function testLinkSocialNotDefineLinkSocialRedirectUri() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + Configure::delete('OAuth.providers.facebook.options.callbackLinkSocialUri'); + + $result = false; + try { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + + $this->_mockDispatchEvent(new Event('event')); + + $this->Trait->linkSocial('facebook'); + } catch (NotFoundException $e) { + $result = true; + } + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testLinkSocialNotDefinedClientId() + { + Configure::delete('OAuth.providers.facebook.options.clientId'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + $result = false; + try { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + + $this->_mockDispatchEvent(new Event('event')); + + $this->Trait->linkSocial('facebook'); + } catch (NotFoundException $e) { + $result = true; + } + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testLinkSocialNotDefinedClientSecret() { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::delete('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); $result = false; try { $this->_mockRequestGet(); @@ -180,7 +247,8 @@ public function testLinkSocialNotDefineSocialLinkRedictUri() */ public function testCallbackLinkSocialHappy() { - Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); $Table = TableRegistry::get('CakeDC/Users.Users'); @@ -268,10 +336,13 @@ public function testCallbackLinkSocialHappy() 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' ] - ]), - $this->equalTo('/callback-link-social/facebook') + ]) ) ->will($this->returnValue($ProviderMock)); @@ -307,7 +378,8 @@ public function testCallbackLinkSocialHappy() */ public function testCallbackLinkSocialWithValidationErrors() { - Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + 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->errors([ 'social_accounts' => [ @@ -409,10 +481,13 @@ public function testCallbackLinkSocialWithValidationErrors() 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' ] - ]), - $this->equalTo('/callback-link-social/facebook') + ]) ) ->will($this->returnValue($ProviderMock)); @@ -429,7 +504,8 @@ public function testCallbackLinkSocialWithValidationErrors() */ public function testCallbackLinkSocialFailGettingAccessToken() { - Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); $Table = TableRegistry::get('CakeDC/Users.Users'); @@ -498,10 +574,13 @@ public function testCallbackLinkSocialFailGettingAccessToken() 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' ] - ]), - $this->equalTo('/callback-link-social/facebook') + ]) ) ->will($this->returnValue($ProviderMock)); @@ -518,7 +597,8 @@ public function testCallbackLinkSocialFailGettingAccessToken() */ public function testCallbackLinkSocialQueryHasErrors() { - Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); $Table = TableRegistry::get('CakeDC/Users.Users'); @@ -585,10 +665,13 @@ public function testCallbackLinkSocialQueryHasErrors() 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' ] - ]), - $this->equalTo('/callback-link-social/facebook') + ]) ) ->will($this->returnValue($ProviderMock)); @@ -602,7 +685,8 @@ public function testCallbackLinkSocialQueryHasErrors() */ public function testCallbackLinkSocialWrongState() { - Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); $Table = TableRegistry::get('CakeDC/Users.Users'); @@ -668,10 +752,13 @@ public function testCallbackLinkSocialWrongState() 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ 'graphApiVersion' => 'v2.5', - 'redirectUri' => '/auth/facebook' + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' ] - ]), - $this->equalTo('/callback-link-social/facebook') + ]) ) ->will($this->returnValue($ProviderMock)); @@ -685,7 +772,8 @@ public function testCallbackLinkSocialWrongState() */ public function testCallbackLinkSocialMissingCode() { - Configure::write('SocialLink.providers.facebook.options.redirectUri', '/callback-link-social/facebook'); + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); $Table = TableRegistry::get('CakeDC/Users.Users'); From d430cb23cc62f269c4987b0427aa422530ca8cc1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 9 Aug 2017 16:14:36 +0000 Subject: [PATCH 0671/1476] added function create coonect links --- config/Migrations/schema-dump-default.lock | Bin 0 -> 7938 bytes config/users.php | 10 ++ src/Template/Users/profile.ctp | 1 + src/View/Helper/UserHelper.php | 64 ++++++++ .../Controller/Traits/LinkSocialTraitTest.php | 2 +- tests/TestCase/View/Helper/UserHelperTest.php | 152 ++++++++++++++++++ 6 files changed, 228 insertions(+), 1 deletion(-) 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..e92a50d0b43b51221bbcc5509708a0c42e56a14e GIT binary patch literal 7938 zcmds6&vTnN6z<=`u_u$%+f=!Ad+DLOhwU*lj0|$B2}XpVl-}ieDV}!un7`NEz zDJBm|@AvyYA;p#0InrZ)2Kt6b%(`5lS( zwCsb3-n@O2;I&*uxBfOx#Bn1`O?}omLyNGz&ghZ1cqgLjd&#Tuv#v?x#2+Hc zRdHW^i*EnIBP2zg=h5v-Eb#bVM44L4IQ~gr~=PUEJQ?qZbU@Nf91_-6DV6+ zm1?I=LF=CR9WuL+8z><0#+J`&6@nJ7vbwkrRMO&Vxx|hyQ7g}7#n#2-<7$1A+^a%a znJ1~HZKvtZu3qaW1#ht>*c>6!aM4L-#EnKn@6Kcff>uiB{xy~}TI#{{ zn$l8{E3(wdZ{cNRi%cv1C@YMNgq%4xw$9^cnoTOT3M22BRKC8ttkyzPv9Tk0R93Gw zO|&62z?57WlPihJoh_9S*vh!ei#zA!Xez$cO(BQ^S`*P?IvfF%iV4=a#MPy;gsD!6 z;xAAS)6^n=jw_Y{$_qOsPwB?m9g>>~ClPA23JqzrT3+0dLPrx!o(4!8FugI^!4f`) zQk0iF8bX-rco$~5BppU+k-}R}m*lOmo zJ2s4iJkBdYVzVj$Li~epz1F6#;@sEg`v}D~r;aN1Zhz z_7yYaUb8(0!~XAB-jA`FrZGy+s6%LVD} zx&Pc|5EkL9jARPg9+)$8HVtlxN08%?YojmwNOD4LOu09r#zS{4KcCmeC-GV&BfKFe zH;|b#7!AZn!6!ubpyE@a+XLU1p%ek#5pL+?&mK4QfnZMn+d4!RFp?g|31ofL5D2|F z97qO}jg@I9*?xKitGa$12!38ygWY<`5=gzMc}y+d zkueXchhz*6;060;(0!F`shA&OoZ~eVT;I#Ot|tSCRA4-RJ)Rs`kSK literal 0 HcmV?d00001 diff --git a/config/users.php b/config/users.php index 318128ed7..2d3840472 100644 --- a/config/users.php +++ b/config/users.php @@ -154,23 +154,31 @@ 'options' => [ 'graphApiVersion' => 'v2.5', 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook', ] ], 'twitter' => [ 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/twitter', ] ], 'linkedIn' => [ 'className' => 'League\OAuth2\Client\Provider\LinkedIn', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/linkedIn', ] ], 'instagram' => [ 'className' => 'League\OAuth2\Client\Provider\Instagram', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/instagram', ] ], 'google' => [ @@ -178,6 +186,8 @@ 'options' => [ 'userFields' => ['url', 'aboutMe'], 'redirectUri' => Router::fullBaseUrl() . '/auth/google', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/google', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google', ] ], ], diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index 0922b3503..8b59d9ee2 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -31,6 +31,7 @@

    username) ?>

    email) ?>

    + User->socialConnectLinkList($user->social_accounts) ?> social_accounts)): ?> diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index c22688519..42688633a 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -191,4 +191,68 @@ public function isAuthorized($url = null) return $this->AuthLink->isAuthorized($url); } + /** + * Create links for all social providers enabled social link (connect) + * + * @param string $name Provider name in lowercase + * @param array $provider Provider configuration + * @param bool $isConnected User is connected with this provider + * + * @return string + */ + public function socialConnectLink($name, $provider, $isConnected = false) + { + $linkClass = __d( + 'CakeDC/Users', + 'btn btn-social btn-{0}' . Hash::get($provider['options'], 'class') ?: '', + strtolower($name) + ); + if ($isConnected) { + $title = __d('CakeDC/Users', 'Connected with {0}', Inflector::camelize($name)); + + return " $title"; + } + + $title = __d('CakeDC/Users', 'Connect with {0}', Inflector::camelize($name)); + + return $this->Html->link( + " $title", + "/link-social/$name", + [ + 'escape' => false, + 'class' => $linkClass + ] + ); + } + + /** + * Create links for all social providers enabled social link (connect) + * + * @param array $socialAccounts All social accounts connected by a user. + * + * @return string + */ + public function socialConnectLinkList($socialAccounts = []) + { + if (!Configure::read('Users.Social.login')) { + return ""; + } + $html = ""; + $connectedProviders = array_map(function ($item) { + return strtolower($item->provider); + }, (array)$socialAccounts); + + $providers = Configure::read('OAuth.providers'); + foreach ($providers as $name => $provider) { + if (!empty($provider['options']['callbackLinkSocialUri']) && + !empty($provider['options']['linkSocialUri']) && + !empty($provider['options']['clientId']) && + !empty($provider['options']['clientSecret']) + ) { + $html .= $this->socialConnectLink($name, $provider, in_array($name, $connectedProviders)); + } + } + + return $html; + } } diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 7f3e21657..6c4e18af8 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -25,7 +25,7 @@ class LinkSocialTraitTest extends BaseTraitTest { - /** + /** * Keep the original config for oauth * * @var array diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index e777b74f5..5f05f3e9a 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\View\Helper; +use CakeDC\Users\Model\Entity\SocialAccount; use CakeDC\Users\View\Helper\UserHelper; use Cake\Core\App; use Cake\Core\Configure; @@ -29,6 +30,19 @@ */ class UserHelperTest extends TestCase { + /** + * Keep the original config for oauth + * + * @var array + */ + private $oauthConfig; + + /** + * Keep original config Users.Social.login + * + * @var boolean + */ + private $socialLogin; /** * setUp method @@ -37,6 +51,11 @@ class UserHelperTest extends TestCase */ public function setUp() { + if ($this->oauthConfig === null) { + $this->oauthConfig = (array)Configure::read('OAuth'); + $this->socialLogin = Configure::read('Users.Social.login'); + } + parent::setUp(); Plugin::routes('CakeDC/Users'); $this->View = $this->getMockBuilder('Cake\View\View') @@ -62,6 +81,8 @@ public function setUp() */ public function tearDown() { + Configure::write('OAuth', $this->oauthConfig); + Configure::write('Users.Social.login', $this->socialLogin); unset($this->User); parent::tearDown(); @@ -224,4 +245,135 @@ public function testSocialLoginTranslation() $this->assertEquals('Iniciar sesión con Facebook', $result); I18n::locale('en_US'); } + + /** + * Test social connect link list + * + * @return void + */ + public function testSocialConnectLinkList() + { + Configure::write('Users.Social.login', true); + + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); + Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); + + $actual = $this->User->socialConnectLinkList(); + $expected = ' Connect with Facebook'; + $expected .= ' Connect with Google'; + $this->assertEquals($expected, $actual); + } + + /** + * Test social connect link list, user is connected with facebook + * + * @return void + */ + public function testSocialConnectLinkListIsConnectedWithFacebook() + { + Configure::write('Users.Social.login', true); + + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); + Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); + + $socialAccounts = [ + new SocialAccount([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Facebook', + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ]) + ]; + $actual = $this->User->socialConnectLinkList($socialAccounts); + $expected = ' Connected with Facebook'; + $expected .= ' Connect with Google'; + $this->assertEquals($expected, $actual); + } + + + /** + * Test social connect link list, social is not enabled + * + * @return void + */ + public function testSocialConnectLinkListSocialIsNotEnabled() + { + Configure::write('Users.Social.login', false); + + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); + Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); + + $socialAccounts = [ + new SocialAccount([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Facebook', + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ]) + ]; + $actual = $this->User->socialConnectLinkList($socialAccounts); + $expected = ''; + $this->assertEquals($expected, $actual); + } + + /** + * Test social connect link list, social is enabled but any provider was configured + * + * @return void + */ + public function testSocialConnectLinkListSocialEnabledButNotConfiguredProvider() + { + Configure::write('Users.Social.login', true); + + $socialAccounts = [ + new SocialAccount([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Facebook', + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ]) + ]; + $actual = $this->User->socialConnectLinkList($socialAccounts); + $expected = ''; + $this->assertEquals($expected, $actual); + } } From 88b704f21520191ff5fa7451c3e5098e58106558 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 9 Aug 2017 17:33:01 +0000 Subject: [PATCH 0672/1476] phpcs fixes --- src/Controller/Traits/LinkSocialTrait.php | 2 +- src/View/Helper/UserHelper.php | 6 ++-- .../Controller/Traits/LinkSocialTraitTest.php | 4 +-- tests/TestCase/View/Helper/UserHelperTest.php | 33 +++++++++---------- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index e3f8a11e6..128922243 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -144,7 +144,7 @@ protected function _createSocialProvider($config) { $class = $config['className']; $redirectUri = $config['options']['callbackLinkSocialUri']; - + unset($config['options']['callbackLinkSocialUri'], $config['options']['linkSocialUri']); $config['options']['redirectUri'] = $redirectUri; diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 42688633a..5cfa51b86 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -209,12 +209,12 @@ public function socialConnectLink($name, $provider, $isConnected = false) ); if ($isConnected) { $title = __d('CakeDC/Users', 'Connected with {0}', Inflector::camelize($name)); - + return " $title"; } $title = __d('CakeDC/Users', 'Connect with {0}', Inflector::camelize($name)); - + return $this->Html->link( " $title", "/link-social/$name", @@ -245,7 +245,7 @@ public function socialConnectLinkList($socialAccounts = []) $providers = Configure::read('OAuth.providers'); foreach ($providers as $name => $provider) { if (!empty($provider['options']['callbackLinkSocialUri']) && - !empty($provider['options']['linkSocialUri']) && + !empty($provider['options']['linkSocialUri']) && !empty($provider['options']['clientId']) && !empty($provider['options']['clientSecret']) ) { diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 6c4e18af8..043c1651c 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -191,7 +191,7 @@ public function testLinkSocialNotDefineLinkSocialRedirectUri() } $this->assertTrue($result); } - + /** * test * @@ -215,7 +215,7 @@ public function testLinkSocialNotDefinedClientId() } $this->assertTrue($result); } - + /** * test * diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 5f05f3e9a..955719672 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -36,7 +36,7 @@ class UserHelperTest extends TestCase * @var array */ private $oauthConfig; - + /** * Keep original config Users.Social.login * @@ -245,7 +245,7 @@ public function testSocialLoginTranslation() $this->assertEquals('Iniciar sesión con Facebook', $result); I18n::locale('en_US'); } - + /** * Test social connect link list * @@ -254,19 +254,19 @@ public function testSocialLoginTranslation() public function testSocialConnectLinkList() { Configure::write('Users.Social.login', true); - + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); - + $actual = $this->User->socialConnectLinkList(); $expected = ' Connect with Facebook'; $expected .= ' Connect with Google'; $this->assertEquals($expected, $actual); } - + /** * Test social connect link list, user is connected with facebook * @@ -275,13 +275,13 @@ public function testSocialConnectLinkList() public function testSocialConnectLinkListIsConnectedWithFacebook() { Configure::write('Users.Social.login', true); - + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); - + $socialAccounts = [ new SocialAccount([ 'id' => '00000000-0000-0000-0000-000000000001', @@ -305,8 +305,7 @@ public function testSocialConnectLinkListIsConnectedWithFacebook() $expected .= ' Connect with Google'; $this->assertEquals($expected, $actual); } - - + /** * Test social connect link list, social is not enabled * @@ -315,13 +314,13 @@ public function testSocialConnectLinkListIsConnectedWithFacebook() public function testSocialConnectLinkListSocialIsNotEnabled() { Configure::write('Users.Social.login', false); - + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); - + $socialAccounts = [ new SocialAccount([ 'id' => '00000000-0000-0000-0000-000000000001', @@ -344,8 +343,8 @@ public function testSocialConnectLinkListSocialIsNotEnabled() $expected = ''; $this->assertEquals($expected, $actual); } - - /** + + /** * Test social connect link list, social is enabled but any provider was configured * * @return void @@ -353,7 +352,7 @@ public function testSocialConnectLinkListSocialIsNotEnabled() public function testSocialConnectLinkListSocialEnabledButNotConfiguredProvider() { Configure::write('Users.Social.login', true); - + $socialAccounts = [ new SocialAccount([ 'id' => '00000000-0000-0000-0000-000000000001', From 01a465268236d61145edb46fe77a1bae25093e79 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 9 Aug 2017 14:46:07 -0300 Subject: [PATCH 0673/1476] [Doc] Connect Social Account --- Docs/Documentation/UserHelper.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md index 2191f4c1f..2f0757117 100644 --- a/Docs/Documentation/UserHelper.md +++ b/Docs/Documentation/UserHelper.md @@ -30,6 +30,20 @@ echo $this->User->socialLogin($provider); //provider is 'facebook', 'twitter', e We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. +Connect Social Account +----------------- + +You can use the helper included with the plugin to create some 'Connect with Facebook/Twitter' buttons: + +In templates, call socialConnectLinkList method to get links for all social providers enabled +```php +echo $this->User->socialConnectLinkList($user->social_accounts); +``` + +We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. + +The user must be allowed to access the urls "/link-social" and "/callback-link-social/[provider]". + Logout link ----------------- From f6e1149296c8948737a69aeac08c1f8897ed7816 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 9 Aug 2017 14:46:47 -0300 Subject: [PATCH 0674/1476] Update UserHelper.md --- Docs/Documentation/UserHelper.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md index 2f0757117..920f37f98 100644 --- a/Docs/Documentation/UserHelper.md +++ b/Docs/Documentation/UserHelper.md @@ -42,7 +42,7 @@ echo $this->User->socialConnectLinkList($user->social_accounts); We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. -The user must be allowed to access the urls "/link-social" and "/callback-link-social/[provider]". +The user must be allowed to access the urls "/link-social/[provider]" and "/callback-link-social/[provider]". Logout link ----------------- From 0c943146dcf1dcfef8ddd57f4096f2a4c4873c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Wed, 9 Aug 2017 19:54:23 +0200 Subject: [PATCH 0675/1476] Allow upgrade to CakePHP 3.5.x Change Tilde Version Range to Caret Version Range to allow upgrading to CakePHP 3.5.x --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a5148c7ef..0cd012dc8 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "~3.4.0", + "cakephp/cakephp": "^3.4.0", "cakedc/auth": "^1.0" }, "require-dev": { From 087b0469c6264b2d281d47d4f53fff1188324121 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Fri, 11 Aug 2017 14:04:22 -0500 Subject: [PATCH 0676/1476] feat(resend-validation-email): Create method on RegisterBehavior to send user validation email Based on the register method, allow for a new registration token to be created as well as resetting the token registration time based on the option for token_expiration in seconds. Add a test to check that when this method is called, the token expiration is changed. --- src/Model/Behavior/RegisterBehavior.php | 18 +++++++++++++ .../Model/Behavior/RegisterBehaviorTest.php | 25 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 77e3ad82b..5015f799c 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -197,4 +197,22 @@ public function getRegisterValidators($options) return $validator; } + + /** + * @param EntityInterface $user User information + * @param array $options ['tokenExpiration] + * @return bool|EntityInterface + */ + public function resendValidationEmail($user, $options) + { + $tokenExpiration = Hash::get($options, 'token_expiration'); + $emailClass = Hash::get($options, 'email_class'); + $user = $this->_updateActive($user, true, $tokenExpiration); + $userSaved = $this->_table->saveOrFail($user); + if ($userSaved) { + $this->Email->sendValidationEmail($userSaved, $emailClass); + } + + return $userSaved; + } } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index bc5eec74f..85af340a0 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -315,4 +315,29 @@ 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, 'email_class' => $this->Email]); + $this->assertFalse($result->active); + $originalExpiration = $result->token_expires; + $updatedResult = $this->Table->resendValidationEmail($result, ['token_expiration' => 3600, 'email_class' => $this->Email]); + $this->assertNotEmpty($updatedResult); + $this->assertFalse($updatedResult->active); + $this->assertNotEquals($updatedResult->token_expires, $originalExpiration); + } } From 86897ed35123480164b165601bfa6b56e0eace57 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Mon, 14 Aug 2017 09:09:16 -0500 Subject: [PATCH 0677/1476] fix(tests): Ensure timestamp is different For test to pass in php <= php 7.0, token_expiration must be a different value in the test environment for the end values to be different, because the test takes less than a second. --- tests/TestCase/Model/Behavior/RegisterBehaviorTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 85af340a0..f7aa0671b 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -335,9 +335,10 @@ public function testResendValidationEmail() $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); $this->assertFalse($result->active); $originalExpiration = $result->token_expires; - $updatedResult = $this->Table->resendValidationEmail($result, ['token_expiration' => 3600, 'email_class' => $this->Email]); + $updatedResult = $this->Table->resendValidationEmail($result, ['token_expiration' => 4000, 'email_class' => $this->Email]); $this->assertNotEmpty($updatedResult); $this->assertFalse($updatedResult->active); - $this->assertNotEquals($updatedResult->token_expires, $originalExpiration); + $newExpiration = $updatedResult->token_expires; + $this->assertNotEquals($originalExpiration, $newExpiration); } } From 8031c9e25259c0de927002a2ff821eef6bad82cf Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Mon, 14 Aug 2017 09:28:38 -0500 Subject: [PATCH 0678/1476] fix(lint): Remove space at end of line. --- tests/TestCase/Model/Behavior/RegisterBehaviorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index f7aa0671b..cd30777b2 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -322,7 +322,7 @@ public function testRegisterUsingCustomRole() * @return void */ public function testResendValidationEmail() - { + { $user = [ 'username' => 'testuser', 'email' => 'testuser@test.com', From c6874599b9363f44b06d49633b292d755807cecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Tue, 15 Aug 2017 11:33:47 +0200 Subject: [PATCH 0679/1476] Prevent conflict between CsrfComponent and CsrfProtectionMiddleware --- src/Controller/AppController.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 1b0933342..40b1bf4bd 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -28,7 +28,9 @@ public function initialize() { parent::initialize(); $this->loadComponent('Security'); - $this->loadComponent('Csrf'); + if ($this->request->getParam('_csrfToken') === false) { + $this->loadComponent('Csrf'); + } $this->loadComponent('CakeDC/Users.UsersAuth'); } } From af7f4b84ba4a31613a5fad854f19a6e06d0be99d Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 15 Aug 2017 11:51:51 -0500 Subject: [PATCH 0680/1476] fix(validation): Throw e if user already validated --- src/Model/Behavior/RegisterBehavior.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 5015f799c..adaea5067 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -205,6 +205,10 @@ public function getRegisterValidators($options) */ public function resendValidationEmail($user, $options) { + if ($user->active) { + throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); + } + $tokenExpiration = Hash::get($options, 'token_expiration'); $emailClass = Hash::get($options, 'email_class'); $user = $this->_updateActive($user, true, $tokenExpiration); From 663616cbdc2b5b3aaaa2d9bbd8a0da9272b506fa Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 15 Aug 2017 11:58:36 -0500 Subject: [PATCH 0681/1476] test(register-behavior): Ensure resend validation throws exception --- .../Model/Behavior/RegisterBehaviorTest.php | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index cd30777b2..a5468266c 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -16,6 +16,7 @@ use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; +use CakeDC\Users\Exception\UserAlreadyActiveException; use InvalidArgumentException; /** @@ -341,4 +342,28 @@ public function testResendValidationEmail() $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, 'email_class' => $this->Email]); + $this->assertFalse($result->active); + $activeUser = $this->Table->activateUser($result); + $this->assertTrue($result->active); + $this->expectException(UserAlreadyActiveException::class); + $updatedResult = $this->Table->resendValidationEmail($result, ['token_expiration' => 4000, 'email_class' => $this->Email]); + } } From db33b87f3e815e8b631b70e2a3b6877e8be3e9f5 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 15 Aug 2017 12:02:46 -0500 Subject: [PATCH 0682/1476] fix(typo): Clean up test --- tests/TestCase/Model/Behavior/RegisterBehaviorTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index a5468266c..d1f248583 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -362,8 +362,8 @@ public function testResendValidationEmailThrows() $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); $this->assertFalse($result->active); $activeUser = $this->Table->activateUser($result); - $this->assertTrue($result->active); + $this->assertTrue($activeUser->active); $this->expectException(UserAlreadyActiveException::class); - $updatedResult = $this->Table->resendValidationEmail($result, ['token_expiration' => 4000, 'email_class' => $this->Email]); + $updatedResult = $this->Table->resendValidationEmail($activeUser, ['token_expiration' => 4000, 'email_class' => $this->Email]); } } From 6f46cdcb82337f57852547147105dbf8199db5b0 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 15 Aug 2017 12:03:59 -0500 Subject: [PATCH 0683/1476] fix(typo): Clean up test --- tests/TestCase/Model/Behavior/RegisterBehaviorTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index d1f248583..8ddec4e34 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -360,9 +360,7 @@ public function testResendValidationEmailThrows() 'tos' => 1 ]; $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); - $this->assertFalse($result->active); $activeUser = $this->Table->activateUser($result); - $this->assertTrue($activeUser->active); $this->expectException(UserAlreadyActiveException::class); $updatedResult = $this->Table->resendValidationEmail($activeUser, ['token_expiration' => 4000, 'email_class' => $this->Email]); } From 2dab5ff3de997a283af99d878f703f20ac86b471 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 15 Aug 2017 12:37:06 -0500 Subject: [PATCH 0684/1476] fix(lint): Order classes alphabetically --- tests/TestCase/Model/Behavior/RegisterBehaviorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 8ddec4e34..79c316b0e 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -12,11 +12,11 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; +use CakeDC\Users\Exception\UserAlreadyActiveException; use Cake\Core\Configure; use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; -use CakeDC\Users\Exception\UserAlreadyActiveException; use InvalidArgumentException; /** From 4a9318fc108b980769d20fb3e4c958dc98e13ecc Mon Sep 17 00:00:00 2001 From: George Constantinou Date: Fri, 18 Aug 2017 18:08:41 +0300 Subject: [PATCH 0685/1476] Extend CakePHP Migrations instead of Phinx Utilize `src/Table.php` from CakePHP Migrations plugin, which has extra functionality like setting default collation and encoding etc. See this PR for more info: https://github.com/cakephp/migrations/pull/302 The above was merged to CakePHP Migrations v1.7.0. --- config/Migrations/20150513201111_initial.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php index 1fc12e917..55b00f094 100644 --- a/config/Migrations/20150513201111_initial.php +++ b/config/Migrations/20150513201111_initial.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -use Phinx\Migration\AbstractMigration; +use Migrations\AbstractMigration; class Initial extends AbstractMigration { From c2d5d7d3a5d37f566344f048d749f902a0bb6fd9 Mon Sep 17 00:00:00 2001 From: "Jeffrey L. Roberts" Date: Sun, 20 Aug 2017 21:47:34 -0400 Subject: [PATCH 0686/1476] Update to cakephp 3.5.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a5148c7ef..c43c43c7a 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "~3.4.0", + "cakephp/cakephp": "~3.5.0", "cakedc/auth": "^1.0" }, "require-dev": { From f218d26e5ede37270b002e2e2457785a8a38757b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Wed, 23 Aug 2017 18:06:13 +0200 Subject: [PATCH 0687/1476] PR cakedc/users#489 rebased from develop and fixed test --- src/Controller/Component/RememberMeComponent.php | 3 +++ .../TestCase/Controller/Component/RememberMeComponentTest.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 5c791829c..079c8f3bc 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -106,6 +106,9 @@ public function setLoginCookie(Event $event) return; } $user['user_agent'] = $this->getController()->request->getHeaderLine('User-Agent'); + if (!(bool)$this->getController()->request->getData(Configure::read('Users.Key.Data.rememberMe'))) { + return; + } $this->Cookie->write($this->_cookieName, $user); } diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 0fff648cf..4cb357034 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -121,7 +121,7 @@ public function testSetLoginCookie() ->setMethods(['write']) ->disableOriginalConstructor() ->getMock(); - $this->rememberMeComponent->request = (new ServerRequest('/'))->env('HTTP_USER_AGENT', 'user-agent'); + $this->rememberMeComponent->request = (new ServerRequest('/'))->env('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']); From 02e41e3a8ba5f445082a1586eada5b70ce637fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Wed, 23 Aug 2017 18:11:04 +0200 Subject: [PATCH 0688/1476] Replacing tab char with spaces --- src/Controller/Component/RememberMeComponent.php | 2 +- .../TestCase/Controller/Component/RememberMeComponentTest.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 079c8f3bc..0e1d5a8b4 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -106,7 +106,7 @@ public function setLoginCookie(Event $event) return; } $user['user_agent'] = $this->getController()->request->getHeaderLine('User-Agent'); - if (!(bool)$this->getController()->request->getData(Configure::read('Users.Key.Data.rememberMe'))) { + if (!(bool)$this->getController()->request->getData(Configure::read('Users.Key.Data.rememberMe'))) { return; } $this->Cookie->write($this->_cookieName, $user); diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 4cb357034..5d14787ba 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -121,7 +121,8 @@ public function testSetLoginCookie() ->setMethods(['write']) ->disableOriginalConstructor() ->getMock(); - $this->rememberMeComponent->request = (new ServerRequest('/'))->env('HTTP_USER_AGENT', 'user-agent')->withData(Configure::read('Users.Key.Data.rememberMe'), '1'); + $this->rememberMeComponent->request = (new ServerRequest('/'))->env('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']); From e75c1eff467ebaae2f011aa3082f25139b72aaf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 24 Aug 2017 11:04:00 +0100 Subject: [PATCH 0689/1476] update changelog --- .semver | 4 ++-- CHANGELOG.md | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.semver b/.semver index 75bf20832..262596eca 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 5 -:minor: 0 -:patch: 3 +:minor: 1 +:patch: 0 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 39f171a84..49207f43f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ Changelog Releases for CakePHP 3 ------------- +* 5.1.0 + * New resend validation method in RegisterBehavior + * Allow upgrade to CakePHP 3.5.x + * New feature connect social account + * New polish translations + * Fixed bugs reported + * 5.0.3 * Implemented event dispatching on social login * Fixed bugs reported From f4fc0d7ba2023d83bdfc352ec5bc71efd68c366e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 24 Aug 2017 11:40:02 +0100 Subject: [PATCH 0690/1476] update cakedc/auth to use ^2.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0cd012dc8..fd48c4a72 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ }, "require": { "cakephp/cakephp": "^3.4.0", - "cakedc/auth": "^1.0" + "cakedc/auth": "^2.0" }, "require-dev": { "phpunit/phpunit": "^5.0", From 3d2e32406b164c32a1f2c0876f7fc395842e97b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 24 Aug 2017 11:49:30 +0100 Subject: [PATCH 0691/1476] fix tests for 3.5 --- .../Component/GoogleAuthenticatorComponentTest.php | 1 - tests/TestCase/Shell/UsersShellTest.php | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index b94cd798a..0c95f31eb 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -93,7 +93,6 @@ public function tearDown() */ public function testInitialize() { - $this->Registry->unload('GoogleAuthenticator'); $this->Controller->GoogleAuthenticator = new GoogleAuthenticatorComponent($this->Registry); $this->assertInstanceOf('CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent', $this->Controller->GoogleAuthenticator); } diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 29047c69e..c4bfcffa0 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -272,15 +272,13 @@ public function testResetAllPasswords() /** * Reset all passwords - * + * + * @expectedException \Cake\Console\Exception\StopException + * @expectedExceptionMessage Please enter a password. * @return void */ public function testResetAllPasswordsNoPassingParams() { - $this->Shell->expects($this->once()) - ->method('abort') - ->with('Please enter a password.'); - $this->Shell->runCommand(['resetAllPasswords']); } From 7cc953f8922252e88c51f45ea802ff6738bfcdc9 Mon Sep 17 00:00:00 2001 From: Jorge Gonzalez Date: Thu, 24 Aug 2017 23:42:40 +0100 Subject: [PATCH 0692/1476] remove EmailSender class in favor of the UsersMailer --- src/Email/EmailSender.php | 104 ----------- src/Mailer/UsersMailer.php | 27 +-- src/Model/Behavior/PasswordBehavior.php | 17 +- src/Model/Behavior/RegisterBehavior.php | 31 ++-- src/Model/Behavior/SocialAccountBehavior.php | 22 +-- tests/TestCase/Email/EmailSenderTest.php | 161 ------------------ tests/TestCase/Mailer/UsersMailerTest.php | 53 +----- .../Model/Behavior/PasswordBehaviorTest.php | 3 - tests/TestCase/Model/Table/UsersTableTest.php | 3 +- tests/TestCase/Shell/UsersShellTest.php | 7 +- 10 files changed, 50 insertions(+), 378 deletions(-) delete mode 100644 src/Email/EmailSender.php delete mode 100644 tests/TestCase/Email/EmailSenderTest.php diff --git a/src/Email/EmailSender.php b/src/Email/EmailSender.php deleted file mode 100644 index 0d6067a62..000000000 --- a/src/Email/EmailSender.php +++ /dev/null @@ -1,104 +0,0 @@ -getMailer( - 'CakeDC/Users.Users', - $this->_getEmailInstance($email) - ) - ->send('validation', [$user, __d('CakeDC/Users', 'Your account validation link')]); - } - - /** - * Send the reset password email - * - * @param EntityInterface $user User entity - * @param Email $email instance, if null the default email configuration with the - * @param string $template email template - * Users.validation template will be used, so set a ->template() if you pass an Email - * instance - * @return array email send result - */ - public function sendResetPasswordEmail( - EntityInterface $user, - Email $email = null, - $template = 'CakeDC/Users.reset_password' - ) { - return $this - ->getMailer( - 'CakeDC/Users.Users', - $this->_getEmailInstance($email) - ) - ->send('resetPassword', [$user, $template]); - } - - /** - * Send social validation email to the user - * - * @param EntityInterface $socialAccount social account - * @param EntityInterface $user user - * @param Email $email Email instance or null to use 'default' configuration - * @return mixed - */ - public function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user, Email $email = null) - { - if (empty($email)) { - $template = 'CakeDC/Users.social_account_validation'; - } else { - $template = $email->getTemplate(); - } - - return $this - ->getMailer( - 'CakeDC/Users.Users', - $this->_getEmailInstance($email) - ) - ->send('socialAccountValidation', [$user, $socialAccount, $template]); - } - - /** - * Get or initialize the email instance. Used for mocking. - * - * @param Email $email if email provided, we'll use the instance instead of creating a new one - * @return Email - */ - protected function _getEmailInstance(Email $email = null) - { - if ($email === null) { - $email = new Email('default'); - $email->setEmailFormat('both'); - } - - return $email; - } -} diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 3383586fb..a3fa5cfc9 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -24,32 +24,27 @@ class UsersMailer extends Mailer * Send the templated email to the user * * @param EntityInterface $user User entity - * @param string $subject Subject, note the first_name of the user will be prepended if exist - * @param string $template string, note the first_name of the user will be prepended if exists - * - * @return array email send result */ - protected function validation(EntityInterface $user, $subject, $template = 'CakeDC/Users.validation') + protected function validation(EntityInterface $user) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $user->hiddenProperties(['password', 'token_expires', 'api_token']); - + $subject = __d('CakeDC/Users', 'Your account validation link'); $this ->to($user['email']) ->setSubject($firstName . $subject) ->setViewVars($user->toArray()) - ->setTemplate($template); + ->setTemplate('CakeDC/Users.validation'); } /** * Send the reset password email to the user * * @param EntityInterface $user User entity - * @param string $template string, note the first_name of the user will be prepended if exists * * @return array email send result */ - protected function resetPassword(EntityInterface $user, $template = 'CakeDC/Users.reset_password') + protected function resetPassword(EntityInterface $user) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $subject = __d('CakeDC/Users', '{0}Your reset password link', $firstName); @@ -59,7 +54,7 @@ protected function resetPassword(EntityInterface $user, $template = 'CakeDC/User ->to($user['email']) ->setSubject($subject) ->setViewVars($user->toArray()) - ->setTemplate($template); + ->setTemplate('CakeDC/Users.resetPassword'); } /** @@ -67,22 +62,18 @@ protected function resetPassword(EntityInterface $user, $template = 'CakeDC/User * * @param EntityInterface $user User entity * @param EntityInterface $socialAccount SocialAccount entity - * @param string $template string, note the first_name of the user will be prepended if exists * * @return array email send result */ - protected function socialAccountValidation( - EntityInterface $user, - EntityInterface $socialAccount, - $template = 'CakeDC/Users.social_account_validation' - ) { + protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount) + { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - //note: we control the space after the username in the previous line + // note: we control the space after the username in the previous line $subject = __d('CakeDC/Users', '{0}Your social account validation link', $firstName); $this ->to($user['email']) ->setSubject($subject) ->setViewVars(compact('user', 'socialAccount')) - ->setTemplate($template); + ->setTemplate('CakeDC/Users.socialAccountValidation'); } } diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 5e6caf98f..d436c8da5 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Model\Behavior; +use Cake\Core\Configure; use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotActiveException; @@ -26,17 +27,6 @@ */ class PasswordBehavior extends BaseTokenBehavior { - /** - * Constructor hook method. - * - * @param array $config The configuration settings provided to this behavior. - * @return void - */ - public function initialize(array $config) - { - parent::initialize($config); - $this->Email = new EmailSender(); - } /** * Resets user token * @@ -78,9 +68,10 @@ public function resetToken($reference, array $options = []) } $user->updateToken($expiration); $saveResult = $this->_table->save($user); - $template = !empty($options['emailTemplate']) ? $options['emailTemplate'] : 'CakeDC/Users.reset_password'; if (Hash::get($options, 'sendEmail')) { - $this->Email->sendResetPasswordEmail($saveResult, null, $template); + $this + ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') + ->send('resetPassword', [$user]); } return $saveResult; diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index adaea5067..5458ef056 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -11,24 +11,24 @@ namespace CakeDC\Users\Model\Behavior; -use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\TokenExpiredException; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; -use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Event\Event; +use Cake\Mailer\MailerAwareTrait; use Cake\Utility\Hash; use Cake\Validation\Validator; -use DateTime; -use InvalidArgumentException; /** * Covers the user registration */ class RegisterBehavior extends BaseTokenBehavior { + + use MailerAwareTrait; + /** * Constructor hook method. * @@ -40,7 +40,6 @@ public function initialize(array $config) parent::initialize($config); $this->validateEmail = (bool)Configure::read('Users.Email.validate'); $this->useTos = (bool)Configure::read('Users.Tos.required'); - $this->Email = new EmailSender(); } /** @@ -50,7 +49,6 @@ public function initialize(array $config) * @param array $data User information * @param array $options ['tokenExpiration] * @return bool|EntityInterface - * @throws InvalidArgumentException */ public function register($user, $data, $options) { @@ -69,7 +67,7 @@ public function register($user, $data, $options) $this->_table->isValidateEmail = $validateEmail; $userSaved = $this->_table->save($user); if ($userSaved && $validateEmail) { - $this->Email->sendValidationEmail($user, $emailClass); + $this->_sendValidationEmail($user, $emailClass); } return $userSaved; @@ -82,7 +80,7 @@ public function register($user, $data, $options) * @param null $callback function that will be returned. * @throws TokenExpiredException when token has expired. * @throws UserNotFoundException when user isn't found. - * @return User $user + * @return EntityInterface $user */ public function validate($token, $callback = null) { @@ -115,7 +113,7 @@ public function activateUser(EntityInterface $user) if ($user->active) { throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); } - $user->activation_date = new DateTime(); + $user->activation_date = new \DateTime(); $user->token_expires = null; $user->active = true; $result = $this->_table->save($user); @@ -214,9 +212,22 @@ public function resendValidationEmail($user, $options) $user = $this->_updateActive($user, true, $tokenExpiration); $userSaved = $this->_table->saveOrFail($user); if ($userSaved) { - $this->Email->sendValidationEmail($userSaved, $emailClass); + $this->_sendValidationEmail($userSaved, $emailClass); } return $userSaved; } + + /** + * Wrapper for mailer + * + * @param $user + */ + protected function _sendValidationEmail($user) + { + $mailer = Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users'; + $this + ->getMailer($mailer) + ->send('validation', [$user]); + } } diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 2210d1ee4..1ab405ab3 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -11,8 +11,6 @@ namespace CakeDC\Users\Model\Behavior; -use ArrayObject; -use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\AccountAlreadyActiveException; use CakeDC\Users\Model\Entity\SocialAccount; use CakeDC\Users\Model\Entity\User; @@ -20,7 +18,7 @@ use Cake\Datasource\EntityInterface; use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Event\Event; -use Cake\Mailer\Email; +use Cake\Mailer\MailerAwareTrait; use Cake\ORM\Behavior; use Cake\ORM\Entity; @@ -30,6 +28,8 @@ */ class SocialAccountBehavior extends Behavior { + use MailerAwareTrait; + /** * Initialize, attaching belongsTo Users association * @@ -44,7 +44,6 @@ public function initialize(array $config) 'joinType' => 'INNER', 'className' => Configure::read('Users.table') ]); - $this->Email = new EmailSender(); } /** @@ -52,7 +51,7 @@ public function initialize(array $config) * * @param Event $event event * @param Entity $entity entity - * @param ArrayObject $options options + * @param \ArrayObject $options options * @return mixed */ public function afterSave(Event $event, Entity $entity, $options) @@ -73,16 +72,13 @@ public function afterSave(Event $event, Entity $entity, $options) * * @param EntityInterface $socialAccount social account * @param EntityInterface $user user - * @param Email $email Email instance or null to use 'default' configuration * @return void */ - public function sendSocialValidationEmail( - EntityInterface $socialAccount, - EntityInterface $user, - Email $email = null - ) { - $this->Email = new EmailSender(); - $this->Email->sendSocialValidationEmail($socialAccount, $user, $email); + protected function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user) + { + return $this + ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') + ->send('socialAccountValidation', [$user, $socialAccount]); } /** diff --git a/tests/TestCase/Email/EmailSenderTest.php b/tests/TestCase/Email/EmailSenderTest.php deleted file mode 100644 index 725f2ba73..000000000 --- a/tests/TestCase/Email/EmailSenderTest.php +++ /dev/null @@ -1,161 +0,0 @@ -EmailSender = $this->getMockBuilder('CakeDC\Users\Email\EmailSender') - ->setMethods(['_getEmailInstance', 'getMailer']) - ->getMock(); - - $this->UserMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') - ->setMethods(['send']) - ->getMock(); - - $this->fullBaseBackup = Router::fullBaseUrl(); - Router::fullBaseUrl('http://users.test'); - - Email::setConfigTransport('test', [ - 'className' => 'Debug' - ]); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - Email::drop('default'); - Email::dropTransport('test'); - parent::tearDown(); - } - - /** - * test sendValidationEmail - * - * @return void - */ - public function testSendEmailValidation() - { - $table = TableRegistry::get('CakeDC/Users.Users'); - $user = $table->newEntity([ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]); - - $email = new Email([ - 'from' => 'test@example.com', - 'transport' => 'test', - 'emailFormat' => 'both', - ]); - - $this->EmailSender->expects($this->once()) - ->method('getMailer') - ->with('CakeDC/Users.Users') - ->will($this->returnValue($this->UserMailer)); - - $this->UserMailer->expects($this->once()) - ->method('send') - ->with('validation', [$user, 'Your account validation link']); - - $this->EmailSender->sendValidationEmail($user, $email); - } - - /** - * test sendResetPasswordEmail - * - * @return void - */ - public function testSendResetPasswordEmailMailer() - { - $table = TableRegistry::get('CakeDC/Users.Users'); - $user = $table->newEntity([ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]); - - $email = new Email([ - 'from' => 'test@example.com', - 'transport' => 'test', - 'template' => 'CakeDC/Users.reset_password', - 'emailFormat' => 'both', - ]); - - $this->EmailSender->expects($this->once()) - ->method('getMailer') - ->with('CakeDC/Users.Users') - ->will($this->returnValue($this->UserMailer)); - - $this->UserMailer->expects($this->once()) - ->method('send') - ->with('resetPassword', [$user, 'CakeDC/Users.reset_password']); - - $this->EmailSender->sendResetPasswordEmail($user, $email); - } - - /** - * test sendSocialValidationEmail - * - * @return void - */ - public function testSendSocialValidationEmailMailer() - { - $this->Table = TableRegistry::get('CakeDC/Users.SocialAccounts'); - $user = $this->Table->find()->contain('Users')->first(); - $email = new Email([ - 'from' => 'test@example.com', - 'transport' => 'test', - 'template' => 'CakeDC/Users.my_template', - 'emailFormat' => 'both', - ]); - - $this->EmailSender->expects($this->once()) - ->method('getMailer') - ->with('CakeDC/Users.Users') - ->will($this->returnValue($this->UserMailer)); - - $this->UserMailer->expects($this->once()) - ->method('send') - ->with('socialAccountValidation', [$user->user, $user, 'CakeDC/Users.my_template']); - - $this->EmailSender->sendSocialValidationEmail($user, $user->user, $email); - } -} diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index b053c9f93..4197fdb5b 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -81,7 +81,7 @@ public function testValidation() $this->Email->expects($this->once()) ->method('setSubject') - ->with('FirstName, Validate your Account') + ->with('FirstName, Your account validation link') ->will($this->returnValue($this->Email)); $this->Email->expects($this->once()) @@ -89,49 +89,7 @@ public function testValidation() ->with($data) ->will($this->returnValue($this->Email)); - $this->Email->expects($this->once()) - ->method('setTemplate') - ->with('CakeDC/Users.validation') - ->will($this->returnValue($this->Email)); - - $this->invokeMethod($this->UsersMailer, 'validation', [$user, 'Validate your Account']); - } - - /** - * test sendValidationEmail including 'template' - * - * @return void - */ - public function testValidationWithTemplate() - { - $table = TableRegistry::get('CakeDC/Users.Users'); - $data = [ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]; - $user = $table->newEntity($data); - $this->UsersMailer->expects($this->once()) - ->method('to') - ->with($user['email']) - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setSubject') - ->with('FirstName, Validate your Account') - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setViewVars') - ->with($data) - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setTemplate') - ->with('myTemplate') - ->will($this->returnValue($this->Email)); - - $this->invokeMethod($this->UsersMailer, 'validation', [$user, 'Validate your Account', 'myTemplate']); + $this->invokeMethod($this->UsersMailer, 'validation', [$user]); } /** @@ -191,12 +149,7 @@ public function testResetPassword() ->with($data) ->will($this->returnValue($this->Email)); - $this->Email->expects($this->once()) - ->method('setTemplate') - ->with('myTemplate') - ->will($this->returnValue($this->Email)); - - $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user, 'myTemplate']); + $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user]); } /** diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 19bdd0178..3d2e06243 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -46,9 +46,6 @@ public function setUp() ->setMethods(['sendResetPasswordEmail']) ->setConstructorArgs([$this->table]) ->getMock(); - $this->Behavior->Email = $this->getMockBuilder('CakeDC\Users\Email\EmailSender') - ->setMethods(['sendResetPasswordEmail']) - ->getMock(); } /** diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index d21f75d22..a7f705033 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -150,7 +150,8 @@ public function testValidateRegisterTosRequired() /** * Test register method - testValidateRegisterValidateEmail */ + * testValidateRegisterValidateEmail + */ public function testValidateRegisterNoTosRequired() { $user = [ diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index 29047c69e..bb1e4484f 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -273,14 +273,11 @@ public function testResetAllPasswords() /** * Reset all passwords * - * @return void + * @expectedException \Cake\Console\Exception\StopException + * @expectedExceptionMessage Please enter a password. */ public function testResetAllPasswordsNoPassingParams() { - $this->Shell->expects($this->once()) - ->method('abort') - ->with('Please enter a password.'); - $this->Shell->runCommand(['resetAllPasswords']); } From 7adb3ed461f1b902c13f769967fef1070c6a1af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 27 Aug 2017 10:02:57 +0100 Subject: [PATCH 0693/1476] refs #478-custom-emails WIP add tests for custom mailer feature --- src/Mailer/UsersMailer.php | 6 ++-- src/Model/Behavior/PasswordBehavior.php | 29 ++++++++++----- src/Model/Behavior/RegisterBehavior.php | 6 ++-- tests/App/Mailer/OverrideMailer.php | 34 ++++++++++++++++++ .../text/custom_template_in_app_namespace.ctp | 1 + .../Template/Layout/Email/html/default.ctp | 2 ++ .../Template/Layout/Email/text/default.ctp | 2 ++ .../Model/Behavior/PasswordBehaviorTest.php | 35 +++++++++++++++---- .../Model/Behavior/RegisterBehaviorTest.php | 32 +++++++++-------- tests/TestCase/Model/Table/UsersTableTest.php | 3 -- tests/bootstrap.php | 4 +++ 11 files changed, 116 insertions(+), 38 deletions(-) create mode 100644 tests/App/Mailer/OverrideMailer.php create mode 100644 tests/App/Template/Email/text/custom_template_in_app_namespace.ctp create mode 100644 tests/App/Template/Layout/Email/html/default.ctp create mode 100644 tests/App/Template/Layout/Email/text/default.ctp diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index a3fa5cfc9..c3660566f 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -28,7 +28,8 @@ class UsersMailer extends Mailer protected function validation(EntityInterface $user) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $user->hiddenProperties(['password', 'token_expires', 'api_token']); + // 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'); $this ->to($user['email']) @@ -48,7 +49,8 @@ protected function resetPassword(EntityInterface $user) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; $subject = __d('CakeDC/Users', '{0}Your reset password link', $firstName); - $user->hiddenProperties(['password', 'token_expires', 'api_token']); + // un-hide the token to be able to send it in the email content + $user->setHidden(['password', 'token_expires', 'api_token']); $this ->to($user['email']) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index d436c8da5..65753e3d7 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -11,22 +11,23 @@ namespace CakeDC\Users\Model\Behavior; -use Cake\Core\Configure; -use CakeDC\Users\Email\EmailSender; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; +use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Datasource\Exception\RecordNotFoundException; +use Cake\Mailer\MailerAwareTrait; use Cake\Utility\Hash; -use InvalidArgumentException; /** * Covers the password management features */ class PasswordBehavior extends BaseTokenBehavior { + use MailerAwareTrait; + /** * Resets user token * @@ -34,19 +35,19 @@ class PasswordBehavior extends BaseTokenBehavior * @param array $options checkActive, sendEmail, expiration * * @return string - * @throws InvalidArgumentException + * @throws \InvalidArgumentException * @throws UserNotFoundException * @throws UserAlreadyActiveException */ public function resetToken($reference, array $options = []) { if (empty($reference)) { - throw new InvalidArgumentException(__d('CakeDC/Users', "Reference cannot be null")); + throw new \InvalidArgumentException(__d('CakeDC/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('CakeDC/Users', "Token expiration cannot be empty")); } $user = $this->_getUser($reference); @@ -69,14 +70,24 @@ public function resetToken($reference, array $options = []) $user->updateToken($expiration); $saveResult = $this->_table->save($user); if (Hash::get($options, 'sendEmail')) { - $this - ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') - ->send('resetPassword', [$user]); + $this->sendResetPasswordEmail($user); } return $saveResult; } + /** + * Send the reset password related email link + * + * @param $user + */ + protected function sendResetPasswordEmail($user) + { + $this + ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') + ->send('resetPassword', [$user]); + } + /** * Get the user by email or username * diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 5458ef056..205abd65b 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -54,7 +54,6 @@ public function register($user, $data, $options) { $validateEmail = Hash::get($options, 'validate_email'); $tokenExpiration = Hash::get($options, 'token_expiration'); - $emailClass = Hash::get($options, 'email_class'); $user = $this->_table->patchEntity( $user, $data, @@ -67,7 +66,7 @@ public function register($user, $data, $options) $this->_table->isValidateEmail = $validateEmail; $userSaved = $this->_table->save($user); if ($userSaved && $validateEmail) { - $this->_sendValidationEmail($user, $emailClass); + $this->_sendValidationEmail($user); } return $userSaved; @@ -208,11 +207,10 @@ public function resendValidationEmail($user, $options) } $tokenExpiration = Hash::get($options, 'token_expiration'); - $emailClass = Hash::get($options, 'email_class'); $user = $this->_updateActive($user, true, $tokenExpiration); $userSaved = $this->_table->saveOrFail($user); if ($userSaved) { - $this->_sendValidationEmail($userSaved, $emailClass); + $this->_sendValidationEmail($userSaved); } return $userSaved; diff --git a/tests/App/Mailer/OverrideMailer.php b/tests/App/Mailer/OverrideMailer.php new file mode 100644 index 000000000..5e7a1c052 --- /dev/null +++ b/tests/App/Mailer/OverrideMailer.php @@ -0,0 +1,34 @@ +setSubject('This is the new subject'); + $this->setTemplate('custom-template-in-app-namespace'); + } +} diff --git a/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp b/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp new file mode 100644 index 000000000..1619a4eb2 --- /dev/null +++ b/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp @@ -0,0 +1 @@ +some custom template here \ No newline at end of file diff --git a/tests/App/Template/Layout/Email/html/default.ctp b/tests/App/Template/Layout/Email/html/default.ctp new file mode 100644 index 000000000..21c7e0044 --- /dev/null +++ b/tests/App/Template/Layout/Email/html/default.ctp @@ -0,0 +1,2 @@ +fetch('content'); diff --git a/tests/App/Template/Layout/Email/text/default.ctp b/tests/App/Template/Layout/Email/text/default.ctp new file mode 100644 index 000000000..21c7e0044 --- /dev/null +++ b/tests/App/Template/Layout/Email/text/default.ctp @@ -0,0 +1,2 @@ +fetch('content'); diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 3d2e06243..4a3728a9f 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -11,16 +11,17 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; -use CakeDC\Users\Exception\UserAlreadyActiveException; -use CakeDC\Users\Model\Table\UsersTable; +use Cake\Core\Configure; use Cake\Mailer\Email; use Cake\ORM\TableRegistry; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; +use CakeDC\Users\Model\Behavior\PasswordBehavior; +use CakeDC\Users\Test\App\Mailer\OverrideMailer; use InvalidArgumentException; /** * Test Case + * @property \CakeDC\Users\Model\Behavior\PasswordBehavior Behavior */ class PasswordBehaviorTest extends TestCase { @@ -46,6 +47,15 @@ public function setUp() ->setMethods(['sendResetPasswordEmail']) ->setConstructorArgs([$this->table]) ->getMock(); + Email::setConfigTransport('test', [ + 'className' => 'Debug' + ]); + //$this->configEmail = Email::getConfig('default'); + Email::setConfig('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + } /** @@ -56,6 +66,8 @@ public function setUp() public function tearDown() { unset($this->table, $this->Behavior); + Email::drop('default'); + Email::dropTransport('test'); parent::tearDown(); } @@ -67,7 +79,7 @@ public function testResetToken() { $user = $this->table->findByUsername('user-1')->first(); $token = $user->token; - $this->Behavior->Email->expects($this->never()) + $this->Behavior->expects($this->never()) ->method('sendResetPasswordEmail') ->with($user); $result = $this->Behavior->resetToken('user-1', [ @@ -88,7 +100,7 @@ public function testResetTokenSendEmail() $user = $this->table->findByUsername('user-1')->first(); $token = $user->token; $tokenExpires = $user->token_expires; - $this->Behavior->Email->expects($this->once()) + $this->Behavior->expects($this->once()) ->method('sendResetPasswordEmail'); $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, @@ -161,7 +173,7 @@ public function testResetTokenUserAlreadyActive() */ public function testResetTokenUserNotActive() { - $user = TableRegistry::get('CakeDC/Users.Users')->findByUsername('user-1')->first(); + $user = $this->table->findByUsername('user-1')->first(); $this->Behavior->resetToken('user-1', [ 'ensureActive' => true, 'expiration' => 3600 @@ -193,4 +205,15 @@ public function testChangePassword() $result = $this->Behavior->changePassword($user); } + + public function testEmailOverride() + { + Configure::write('Users.Email.mailerClass', OverrideMailer::class); + $this->Behavior = new PasswordBehavior($this->table); + $this->Behavior->resetToken('user-1', [ + 'expiration' => 3600, + 'checkActive' => true, + 'sendEmail' => true + ]); + } } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 79c316b0e..c09f38f42 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; +use Cake\Routing\Router; use CakeDC\Users\Exception\UserAlreadyActiveException; use Cake\Core\Configure; use Cake\Mailer\Email; @@ -49,7 +50,11 @@ public function setUp() Email::setConfigTransport('test', [ 'className' => 'Debug' ]); - $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); + //$this->configEmail = Email::getConfig('default'); + Email::setConfig('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); } /** @@ -60,6 +65,7 @@ public function setUp() public function tearDown() { unset($this->Table, $this->Behavior); + Email::drop('default'); Email::dropTransport('test'); parent::tearDown(); } @@ -80,7 +86,7 @@ public function testValidateRegisterNoValidateEmail() 'last_name' => 'user', 'tos' => 1 ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0, 'email_class' => $this->Email]); + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); $this->assertTrue($result->active); } @@ -92,7 +98,7 @@ public function testValidateRegisterNoValidateEmail() public function testValidateRegisterEmptyUser() { $user = []; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $this->assertFalse($result); } @@ -112,7 +118,7 @@ public function testValidateRegisterValidateEmailAndTos() 'last_name' => 'user', 'tos' => 1 ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $this->assertNotEmpty($result); $this->assertFalse($result->active); $this->assertNotEmpty($result->tos_date); @@ -161,7 +167,7 @@ public function testValidateRegisterValidatorOption() ->with($entityUser) ->will($this->returnValue($entityUser)); - $result = $this->Behavior->register($this->Table->newEntity(), $user, ['validator' => 'custom', 'validate_email' => 1, 'email_class' => $this->Email]); + $result = $this->Behavior->register($this->Table->newEntity(), $user, ['validator' => 'custom', 'validate_email' => 1]); $this->assertNotEmpty($result->tos_date); } @@ -179,7 +185,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, 'email_class' => $this->Email]); + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); $this->assertFalse($result); } @@ -198,7 +204,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, 'email_class' => $this->Email]); + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); $this->assertNotEmpty($result); } @@ -286,8 +292,7 @@ public function testRegisterUsingDefaultRole() Configure::write('Users.Registration.defaultRole', false); $result = $this->Table->register($this->Table->newEntity(), $user, [ 'token_expiration' => 3600, - 'validate_email' => 0, - 'email_class' => $this->Email + 'validate_email' => 0 ]); $this->assertSame('user', $result['role']); } @@ -312,7 +317,6 @@ public function testRegisterUsingCustomRole() $result = $this->Table->register($this->Table->newEntity(), $user, [ 'token_expiration' => 3600, 'validate_email' => 0, - 'email_class' => $this->Email ]); $this->assertSame('emperor', $result['role']); } @@ -333,10 +337,10 @@ public function testResendValidationEmail() 'last_name' => 'user', 'tos' => 1 ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); + $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, 'email_class' => $this->Email]); + $updatedResult = $this->Table->resendValidationEmail($result, ['token_expiration' => 4000]); $this->assertNotEmpty($updatedResult); $this->assertFalse($updatedResult->active); $newExpiration = $updatedResult->token_expires; @@ -359,9 +363,9 @@ public function testResendValidationEmailThrows() 'last_name' => 'user', 'tos' => 1 ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'email_class' => $this->Email]); + $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, 'email_class' => $this->Email]); + $updatedResult = $this->Table->resendValidationEmail($activeUser, ['token_expiration' => 4000]); } } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index a7f705033..fcf798304 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -52,12 +52,10 @@ public function setUp() Email::setConfigTransport('test', [ 'className' => 'Debug' ]); - //$this->configEmail = Email::getConfig('default'); Email::setConfig('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' ]); - $this->Email = new Email(['from' => 'test@example.com', 'transport' => 'test']); Plugin::routes('CakeDC/Users'); } @@ -72,7 +70,6 @@ public function tearDown() Router::fullBaseUrl($this->fullBaseBackup); Email::drop('default'); Email::dropTransport('test'); - //Email::setConfig('default', $this->configEmail); parent::tearDown(); } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index fe9ee7352..e94978c62 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -124,3 +124,7 @@ class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\Ap // 'init' => [], 'timezone' => 'UTC' ]); + +\Cake\Core\Configure::write('App.paths.templates', [ + APP . 'Template/', +]); From 0ccd8d0af52c021f0a0abae9513a08e94f5fc84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 27 Aug 2017 10:03:00 +0100 Subject: [PATCH 0694/1476] fix cs --- src/Model/Behavior/RegisterBehavior.php | 1 - tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 205abd65b..5ae86d592 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -26,7 +26,6 @@ */ class RegisterBehavior extends BaseTokenBehavior { - use MailerAwareTrait; /** diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 4a3728a9f..1d75b22d1 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -55,7 +55,6 @@ public function setUp() 'transport' => 'test', 'from' => 'cakedc@example.com' ]); - } /** From 11c780318c84cb43888b5215e26c2d10b9090b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 29 Aug 2017 08:49:16 +0100 Subject: [PATCH 0695/1476] refs #478-custom-emails add tests to custom mailer --- .../Model/Behavior/PasswordBehaviorTest.php | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 1d75b22d1..088375eec 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -136,7 +136,7 @@ public function testResetTokenNoExpiration() /** * Test resetToken * - * @expectedException CakeDC\Users\Exception\UserNotFoundException + * @expectedException \CakeDC\Users\Exception\UserNotFoundException */ public function testResetTokenNotExistingUser() { @@ -148,7 +148,7 @@ public function testResetTokenNotExistingUser() /** * Test resetToken * - * @expectedException CakeDC\Users\Exception\UserAlreadyActiveException + * @expectedException \CakeDC\Users\Exception\UserAlreadyActiveException */ public function testResetTokenUserAlreadyActive() { @@ -168,7 +168,7 @@ public function testResetTokenUserAlreadyActive() /** * Test resetToken * - * @expectedException CakeDC\Users\Exception\UserNotActiveException + * @expectedException \CakeDC\Users\Exception\UserNotActiveException */ public function testResetTokenUserNotActive() { @@ -205,10 +205,27 @@ public function testChangePassword() $result = $this->Behavior->changePassword($user); } + /** + * test Email Override + */ public function testEmailOverride() { + $overrideMailer = $this->getMockBuilder(OverrideMailer::class) + ->setMethods(['send']) + ->getMock(); Configure::write('Users.Email.mailerClass', OverrideMailer::class); - $this->Behavior = new PasswordBehavior($this->table); + $this->Behavior = $this->getMockBuilder(PasswordBehavior::class) + ->setConstructorArgs([$this->table]) + ->setMethods(['getMailer']) + ->getMock(); + $overrideMailer->expects($this->once()) + ->method('send') + ->with('resetPassword') + ->willReturn(true); + $this->Behavior->expects($this->once()) + ->method('getMailer') + ->with(OverrideMailer::class) + ->willReturn($overrideMailer); $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, 'checkActive' => true, From f5a38f28d3383b6de54517ba3c056e465316f980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 29 Aug 2017 09:07:53 +0100 Subject: [PATCH 0696/1476] refs #478-custom-emails better logging of exceptions --- 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 09a2027fb..b079d2188 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -83,6 +83,7 @@ public function changePassword() $this->Flash->error(__d('CakeDC/Users', '{0}', $wpe->getMessage())); } catch (Exception $exception) { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); + $this->log($exception->getMessage()); } } $this->set(compact('user')); @@ -136,6 +137,7 @@ public function requestResetPassword() $this->Flash->error(__d('CakeDC/Users', 'The user is not active')); } catch (Exception $exception) { $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); + $this->log($exception->getMessage()); } } From 552062bd28f6249b03e4cd18c2347e9b66b9529d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 29 Aug 2017 09:22:50 +0100 Subject: [PATCH 0697/1476] refs #478-custom-emails add documentation to the mailer override feature --- Docs/Documentation/Extending-the-Plugin.md | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index 6a05b9014..20d6faa4b 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -156,5 +156,38 @@ 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 +Updating the Emails +------------------- + +Extend the `\CakeDC\Users\Mailer\UsersMailer` class and override the email configuration to change the way the +emails are sent by the Plugin. We currently have: +* validation, sent with a link to validate new users registered +* resetPassword, sent with a link to access the reset password feature +* socialAccountValidation, sent with a link to validate the social account used for login + +Example, to override the validation email you would need to: +* Create a new class in your application +```php +namespace App\Mailer; + +use Cake\Datasource\EntityInterface; +use CakeDC\Users\Mailer\UsersMailer; + +class MyUsersMailer extends UsersMailer +{ + public function resetPassword(EntityInterface $user) + { + parent::resetPassword($user); + $this->setSubject('This is the new subject'); + $this->setTemplate('custom-template-in-app-namespace'); + } +} +``` +* Configure the Plugin to use this new mailer class in bootstrap or users.php +`Configure::write('Users.Email.mailerClass', \App\Mailer\MyUsersMailer::class);` + +* Create the file `src/Template/Email/text/custom_template_in_app_namespace.ctp` +with your custom contents. Note you can also prepare an html version of the file, +change the template, or do any other customization in the `MyUsersMailer` method. From 584dfbef77879a983b1b00956a192864c09a27cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 29 Aug 2017 09:28:43 +0100 Subject: [PATCH 0698/1476] refs #478-custom-emails fix phpcs --- src/Mailer/UsersMailer.php | 5 +++-- src/Model/Behavior/PasswordBehavior.php | 3 ++- src/Model/Behavior/RegisterBehavior.php | 3 ++- tests/App/Mailer/OverrideMailer.php | 2 +- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 4 ++-- tests/TestCase/Model/Behavior/RegisterBehaviorTest.php | 2 -- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index c3660566f..fabfbfcb1 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -24,6 +24,7 @@ class UsersMailer extends Mailer * Send the templated email to the user * * @param EntityInterface $user User entity + * @return void */ protected function validation(EntityInterface $user) { @@ -43,7 +44,7 @@ protected function validation(EntityInterface $user) * * @param EntityInterface $user User entity * - * @return array email send result + * @return void */ protected function resetPassword(EntityInterface $user) { @@ -65,7 +66,7 @@ protected function resetPassword(EntityInterface $user) * @param EntityInterface $user User entity * @param EntityInterface $socialAccount SocialAccount entity * - * @return array email send result + * @return void */ protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount) { diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 65753e3d7..852ca9a7f 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -79,7 +79,8 @@ public function resetToken($reference, array $options = []) /** * Send the reset password related email link * - * @param $user + * @param EntityInterface $user user + * @return void */ protected function sendResetPasswordEmail($user) { diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 5ae86d592..fc3243a2f 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -218,7 +218,8 @@ public function resendValidationEmail($user, $options) /** * Wrapper for mailer * - * @param $user + * @param EntityInterface $user user + * @return void */ protected function _sendValidationEmail($user) { diff --git a/tests/App/Mailer/OverrideMailer.php b/tests/App/Mailer/OverrideMailer.php index 5e7a1c052..3affd4dc0 100644 --- a/tests/App/Mailer/OverrideMailer.php +++ b/tests/App/Mailer/OverrideMailer.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Test\App\Mailer; -use Cake\Datasource\EntityInterface; use CakeDC\Users\Mailer\UsersMailer; +use Cake\Datasource\EntityInterface; /** * Override default mailer class to test customization diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 088375eec..aa1cf5308 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; +use CakeDC\Users\Model\Behavior\PasswordBehavior; +use CakeDC\Users\Test\App\Mailer\OverrideMailer; use Cake\Core\Configure; use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; -use CakeDC\Users\Model\Behavior\PasswordBehavior; -use CakeDC\Users\Test\App\Mailer\OverrideMailer; use InvalidArgumentException; /** diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index c09f38f42..e81bbf2a0 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -12,13 +12,11 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; -use Cake\Routing\Router; use CakeDC\Users\Exception\UserAlreadyActiveException; use Cake\Core\Configure; use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; -use InvalidArgumentException; /** * Test Case From a80687a9e7a1d7d6522a6839fe6a25e0e3db4e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 6 Sep 2017 17:14:59 +0100 Subject: [PATCH 0699/1476] fix review comments --- src/Controller/Traits/PasswordManagementTrait.php | 2 +- tests/TestCase/Model/Behavior/RegisterBehaviorTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index c575c2800..a07c0e38c 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -138,7 +138,7 @@ public function requestResetPassword() $this->Flash->error(__d('CakeDC/Users', 'The user is not active')); } catch (Exception $exception) { $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); - Log::error($exception->getMessage()); + $this->log($exception->getMessage()); } } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index e81bbf2a0..f0e4b9707 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -48,7 +48,6 @@ public function setUp() Email::setConfigTransport('test', [ 'className' => 'Debug' ]); - //$this->configEmail = Email::getConfig('default'); Email::setConfig('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com' From d5c935a1a14c5f3e0c3696f93cb9fb8817607cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 6 Sep 2017 17:56:23 +0100 Subject: [PATCH 0700/1476] fix failing test --- .../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 06ec65d1d..a47d91e57 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -27,7 +27,7 @@ class PasswordManagementTraitTest extends BaseTraitTest public function setUp() { $this->traitClassName = 'CakeDC\Users\Controller\Traits\PasswordManagementTrait'; - $this->traitMockMethods = ['set', 'redirect', 'validate']; + $this->traitMockMethods = ['set', 'redirect', 'validate', 'log']; $this->mockDefaultEmail = true; parent::setUp(); } From a7189f3f3471cbb2e5e8b5aeed835917f89c2aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Thu, 7 Sep 2017 10:44:39 +0100 Subject: [PATCH 0701/1476] fix travis mysql --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 40c825cdf..a8348d5da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ before_script: - composer self-update - composer install --prefer-dist --no-interaction - - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test;'; fi" + - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test; GRANT ALL PRIVILEGES ON cakephp_test.* TO travis@localhost;'; fi" - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi" - sh -c "if [ '$PHPCS' = '1' ]; then composer require 'cakephp/cakephp-codesniffer:@stable'; fi" From 25850577ed34ef7e1517f5bd1e799355ea1812d0 Mon Sep 17 00:00:00 2001 From: Jorge Gonzalez Date: Fri, 8 Sep 2017 00:38:18 +0100 Subject: [PATCH 0702/1476] simplify validation rule for password check --- src/Model/Table/UsersTable.php | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index e604839d9..cc3714307 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -72,19 +72,15 @@ public function validationPasswordConfirm(Validator $validator) ->requirePresence('password_confirm', 'create') ->notEmpty('password_confirm'); - $validator->add('password', 'custom', [ - 'rule' => function ($value, $context) { - $confirm = Hash::get($context, 'data.password_confirm'); - if (!is_null($confirm) && $value != $confirm) { - return false; - } - - return true; - }, - 'message' => __d('CakeDC/Users', 'Your password does not match your confirm password. Please try again'), - 'on' => ['create', 'update'], - 'allowEmpty' => false - ]); + $validator + ->requirePresence('password', 'create') + ->notEmpty('password') + ->add('password', [ + 'password_confirm_check' => [ + 'rule' => ['compareWith', 'password_confirm'], + 'message' => __d('CakeDC/Users', 'Your password does not match your confirm password. Please try again'), + 'allowEmpty' => false + ]]); return $validator; } From 1b2a3dd91dee19881ebe5944ea3d9ad5562405cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 8 Sep 2017 09:07:53 +0100 Subject: [PATCH 0703/1476] refs #428-compare-with fix cs --- src/Model/Table/UsersTable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index cc3714307..d8e1919f7 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -79,8 +79,8 @@ public function validationPasswordConfirm(Validator $validator) 'password_confirm_check' => [ 'rule' => ['compareWith', 'password_confirm'], 'message' => __d('CakeDC/Users', 'Your password does not match your confirm password. Please try again'), - 'allowEmpty' => false - ]]); + 'allowEmpty' => false + ]]); return $validator; } From 5e97495ecc8398ac07a929e733f3822c68c36f39 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 8 Sep 2017 13:07:14 +0200 Subject: [PATCH 0704/1476] Remove deprecated --- Docs/Documentation/Overview.md | 3 +- config/Migrations/schema-dump-default.lock | Bin 7938 -> 7938 bytes src/Auth/SocialAuthenticate.php | 16 ++++----- .../Component/RememberMeComponent.php | 6 ++-- src/Controller/Traits/LoginTrait.php | 32 +++++++++--------- .../Traits/PasswordManagementTrait.php | 2 +- src/Controller/Traits/SocialTrait.php | 4 +-- src/Controller/Traits/UserValidationTrait.php | 2 +- src/Model/Behavior/LinkSocialBehavior.php | 4 +-- src/Shell/UsersShell.php | 4 +-- src/View/Helper/UserHelper.php | 4 +-- .../GoogleAuthenticatorComponentTest.php | 2 +- .../Component/RememberMeComponentTest.php | 14 +++----- .../Component/UsersAuthComponentTest.php | 2 +- .../Controller/Traits/LinkSocialTraitTest.php | 2 +- tests/TestCase/Model/Entity/UserTest.php | 4 +-- .../View/Helper/AuthLinkHelperTest.php | 2 +- tests/TestCase/View/Helper/UserHelperTest.php | 4 +-- 18 files changed, 52 insertions(+), 55 deletions(-) diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md index 4e2e392ba..cc47d0159 100644 --- a/Docs/Documentation/Overview.md +++ b/Docs/Documentation/Overview.md @@ -8,11 +8,12 @@ The plugin itself is already capable of: * User registration * Account verification by a token sent via email * User login (email / password) -* Social login (Twitter, Facebook) +* Social login (Twitter, Facebook, Google, Instagram, LinkedIn) * Password reset based on requesting a token by email and entering a new password * User management (add / edit / delete) * Simple roles management * Simple Rbac and SuperUser Authorize * RememberMe using cookie feature * reCaptcha for user registration and login +* Two Factor authentication diff --git a/config/Migrations/schema-dump-default.lock b/config/Migrations/schema-dump-default.lock index e92a50d0b43b51221bbcc5509708a0c42e56a14e..f4f542a7347d46742ad58d60b1b7e1b6ff262461 100644 GIT binary patch delta 21 ccmZp&YqDcav@)`)-Yg{Wo^K;7uK;5$07%CMD*ylh delta 21 ccmZp&YqDcav@)`)-u#7+S70OSdp^cm08R-93jhEB diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 4ce4fb648..965e67005 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -228,7 +228,7 @@ protected function _validate(ServerRequest $request) return false; } - $session = $request->session(); + $session = $request->getSession(); $sessionKey = 'oauth2state'; $state = $request->getQuery('state'); @@ -279,7 +279,7 @@ public function unauthenticated(ServerRequest $request, Response $response) } if ($this->getConfig('options.state')) { - $request->session()->write('oauth2state', $provider->getState()); + $request->getSession()->write('oauth2state', $provider->getState()); } $response = $response->withLocation($provider->getAuthorizationUrl()); @@ -381,14 +381,14 @@ protected function _touch(array $data) */ public function getUser(ServerRequest $request) { - $data = $request->session()->read(Configure::read('Users.Key.Session.social')); + $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->session()->delete(Configure::read('Users.Key.Session.social')); + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); } else { if (empty($data) && !$rawData = $this->_authenticate($request)) { return false; @@ -401,11 +401,11 @@ public function getUser(ServerRequest $request) try { $user = $this->_mapUser($provider, $rawData); } catch (MissingProviderException $ex) { - $request->session()->delete(Configure::read('Users.Key.Session.social')); + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); throw $ex; } if ($user['provider'] === SocialAccountsTable::PROVIDER_TWITTER) { - $request->session()->write(Configure::read('Users.Key.Session.social'), $user); + $request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); } } @@ -417,8 +417,8 @@ public function getUser(ServerRequest $request) return false; } - if ($request->session()->check(Configure::read('Users.Key.Session.social'))) { - $request->session()->delete(Configure::read('Users.Key.Session.social')); + if ($request->getSession()->check(Configure::read('Users.Key.Session.social'))) { + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); } return $result; diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index 0e1d5a8b4..eecfa8f34 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -63,7 +63,7 @@ public function initialize(array $config) */ protected function _validateConfig() { - if (mb_strlen(Security::salt(), '8bit') < 32) { + 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') ); @@ -77,7 +77,7 @@ protected function _validateConfig() */ protected function _attachEvents() { - $eventManager = $this->getController()->eventManager(); + $eventManager = $this->getController()->getEventManager(); $eventManager->on(UsersAuthComponent::EVENT_AFTER_LOGIN, [], [$this, 'setLoginCookie']); $eventManager->on(UsersAuthComponent::EVENT_BEFORE_LOGOUT, [], [$this, 'destroy']); } @@ -137,7 +137,7 @@ public function beforeFilter(Event $event) if (!empty($user) || $this->getController()->request->is(['post', 'put']) || $this->getController()->request->getParam('action') === 'logout' || - $this->getController()->request->session()->check(Configure::read('Users.Key.Session.social')) || + $this->getController()->request->getSession()->check(Configure::read('Users.Key.Session.social')) || $this->getController()->request->getParam('provider')) { return; } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 7ead3f08d..c6a4ab71b 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -49,14 +49,14 @@ public function twitterLogin() $oauthToken = $this->request->getQuery('oauth_token'); $oauthVerifier = $this->request->getQuery('oauth_verifier'); if (!empty($oauthToken) && !empty($oauthVerifier)) { - $temporaryCredentials = $this->request->session()->read('temporary_credentials'); + $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->session()->write(Configure::read('Users.Key.Session.social'), $user); + $this->request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); try { $user = $this->Auth->identify(); $this->_afterIdentifyUser($user, true); @@ -71,13 +71,13 @@ public function twitterLogin() if (!empty($exception)) { return $this->failedSocialLogin( $exception, - $this->request->session()->read(Configure::read('Users.Key.Session.social')), + $this->request->getSession()->read(Configure::read('Users.Key.Session.social')), true ); } } else { $temporaryCredentials = $server->getTemporaryCredentials(); - $this->request->session()->write('temporary_credentials', $temporaryCredentials); + $this->request->getSession()->write('temporary_credentials', $temporaryCredentials); $url = $server->getAuthorizationUrl($temporaryCredentials); return $this->redirect($url); @@ -108,7 +108,7 @@ public function failedSocialLogin($exception, $data, $flash = false) if ($flash) { $this->Flash->success(__d('CakeDC/Users', 'Please enter your email')); } - $this->request->session()->write(Configure::read('Users.Key.Session.social'), $data); + $this->request->getSession()->write(Configure::read('Users.Key.Session.social'), $data); return $this->redirect([ 'plugin' => 'CakeDC/Users', @@ -131,7 +131,7 @@ public function failedSocialLogin($exception, $data, $flash = false) if ($flash) { $this->Auth->setConfig('authError', $msg); $this->Auth->setConfig('flash.params', ['class' => 'success']); - $this->request->session()->delete(Configure::read('Users.Key.Session.social')); + $this->request->getSession()->delete(Configure::read('Users.Key.Session.social')); $this->Flash->success(__d('CakeDC/Users', $msg)); } @@ -147,7 +147,7 @@ public function failedSocialLogin($exception, $data, $flash = false) public function socialLogin() { $socialProvider = $this->request->getParam('provider'); - $socialUser = $this->request->session()->read(Configure::read('Users.Key.Session.social')); + $socialUser = $this->request->getSession()->read(Configure::read('Users.Key.Session.social')); if (empty($socialProvider) && empty($socialUser)) { throw new NotFoundException(); @@ -218,10 +218,10 @@ public function verify() // storing user's session in the temporary one // until the GA verification is checked $temporarySession = $this->Auth->user(); - $this->request->session()->delete('Auth.User'); + $this->request->getSession()->delete('Auth.User'); if (!empty($temporarySession)) { - $this->request->session()->write('temporarySession', $temporarySession); + $this->request->getSession()->write('temporarySession', $temporarySession); } if (array_key_exists('secret', $temporarySession)) { @@ -243,7 +243,7 @@ public function verify() ->where(['id' => $temporarySession['id']]); $query->execute(); } catch (\Exception $e) { - $this->request->session()->destroy(); + $this->request->getSession()->destroy(); $message = __d('CakeDC/Users', $e->getMessage()); $this->Flash->error($message, 'default', [], 'auth'); @@ -260,7 +260,7 @@ public function verify() if ($this->request->is('post')) { $codeVerified = false; $verificationCode = $this->request->getData('code'); - $user = $this->request->session()->read('temporarySession'); + $user = $this->request->getSession()->read('temporarySession'); $entity = $this->getUsersTable()->get($user['id']); if (!empty($entity['secret'])) { @@ -277,13 +277,13 @@ public function verify() ->execute(); } - $this->request->session()->delete('temporarySession'); - $this->request->session()->write('Auth.User', $user); + $this->request->getSession()->delete('temporarySession'); + $this->request->getSession()->write('Auth.User', $user); $url = $this->Auth->redirectUrl(); return $this->redirect($url); } else { - $this->request->session()->destroy(); + $this->request->getSession()->destroy(); $message = __d('CakeDC/Users', 'Verification code is invalid. Try again'); $this->Flash->error($message, 'default', [], 'auth'); @@ -359,7 +359,7 @@ public function logout() return $this->redirect($eventBefore->result); } - $this->request->session()->destroy(); + $this->request->getSession()->destroy(); $this->Flash->success(__d('CakeDC/Users', 'You\'ve successfully logged out')); $eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT, ['user' => $user]); @@ -379,7 +379,7 @@ public function logout() protected function _isSocialLogin() { return Configure::read('Users.Social.login') && - $this->request->session()->check(Configure::read('Users.Key.Session.social')); + $this->request->getSession()->check(Configure::read('Users.Key.Session.social')); } /** diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index a07c0e38c..a07354a35 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -43,7 +43,7 @@ public function changePassword() //@todo add to the documentation: list of routes used $redirect = Configure::read('Users.Profile.route'); } else { - $user->id = $this->request->session()->read(Configure::read('Users.Key.Session.resetPasswordUserId')); + $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')); diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 665d9ec74..7fd6b197e 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -29,10 +29,10 @@ trait SocialTrait */ public function socialEmail() { - if (!$this->request->session()->check(Configure::read('Users.Key.Session.social'))) { + if (!$this->request->getSession()->check(Configure::read('Users.Key.Session.social'))) { throw new NotFoundException(); } - $this->request->session()->delete('Flash.auth'); + $this->request->getSession()->delete('Flash.auth'); if ($this->request->is('post')) { $validPost = $this->_validateRegisterPost(); diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 037ba1090..d9ba30a73 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -52,7 +52,7 @@ public function validate($type = null, $token = null) $result = $this->getUsersTable()->validate($token); if (!empty($result)) { $this->Flash->success(__d('CakeDC/Users', 'Reset password token was validated successfully')); - $this->request->session()->write( + $this->request->getSession()->write( Configure::read('Users.Key.Session.resetPasswordUserId'), $result->id ); diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php index 926f31f02..68f48608c 100644 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -48,7 +48,7 @@ public function linkSocialAccount(EntityInterface $user, $data) ])->first(); if ($socialAccount && $user->id !== $socialAccount->user_id) { - $user->errors([ + $user->setErrors([ 'social_accounts' => [ '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') ] @@ -95,7 +95,7 @@ protected function createOrUpdateSocialAccount(EntityInterface $user, $data, $so } $user->social_accounts = $accounts; - if ($result && !$result->errors()) { + if ($result && !$result->getErrors()) { return $user; } diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index a97e8b56e..292dc71b3 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -317,7 +317,7 @@ protected function _createUser($template) } else { $this->out(__d('CakeDC/Users', 'User could not be added:')); - collection($userEntity->errors())->each(function ($error, $field) { + collection($userEntity->getErrors())->each(function ($error, $field) { $this->out(__d('CakeDC/Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); }); } @@ -338,7 +338,7 @@ protected function _updateUser($username, $data) } $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { - return !$user->accessible($field); + return !$user->isAccessible($field); })->each(function ($value, $field) use (&$user) { $user->{$field} = $value; }); diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 5cfa51b86..56cfec3b4 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -114,13 +114,13 @@ public function logout($message = null, $options = []) */ public function welcome() { - $userId = $this->request->session()->read('Auth.User.id'); + $userId = $this->request->getSession()->read('Auth.User.id'); if (empty($userId)) { return; } $profileUrl = Configure::read('Users.Profile.route'); - $label = __d('CakeDC/Users', 'Welcome, {0}', $this->AuthLink->link($this->request->session()->read('Auth.User.first_name') ?: $this->request->session()->read('Auth.User.username'), $profileUrl)); + $label = __d('CakeDC/Users', 'Welcome, {0}', $this->AuthLink->link($this->request->getSession()->read('Auth.User.first_name') ?: $this->request->getSession()->read('Auth.User.username'), $profileUrl)); return $this->Html->tag('span', $label, ['class' => 'welcome']); } diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index 0c95f31eb..868c449da 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -56,7 +56,7 @@ public function setUp() 'action' => 'edit' ]); - Security::salt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); + Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); Configure::write('App.namespace', 'Users'); Configure::write('Users.GoogleAuthenticator.login', true); diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 5d14787ba..e6b117686 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -13,13 +13,9 @@ use CakeDC\Users\Controller\Component\RememberMeComponent; use Cake\Controller\ComponentRegistry; -use Cake\Controller\Component\AuthComponent; -use Cake\Controller\Component\CookieComponent; -use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Event\Event; use Cake\Http\ServerRequest; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\Utility\Security; use InvalidArgumentException; @@ -40,7 +36,7 @@ class RememberMeComponentTest extends TestCase public function setUp() { parent::setUp(); - Security::salt('2a20bac195a9eb2e28f05b7ac7090afe599365a8fe480b7d8a5ce0f79687346e'); + Security::setSalt('2a20bac195a9eb2e28f05b7ac7090afe599365a8fe480b7d8a5ce0f79687346e'); $this->request = new ServerRequest('controller_posts/index'); $this->request = $this->request->withParam('pass', []); $this->controller = $this->getMockBuilder('Cake\Controller\Controller') @@ -90,15 +86,15 @@ public function testInitialize() */ public function testInitializeException() { - $salt = Security::salt(); - Security::salt('too small'); + $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::salt($salt); + Security::setSalt($salt); } /** @@ -121,7 +117,7 @@ public function testSetLoginCookie() ->setMethods(['write']) ->disableOriginalConstructor() ->getMock(); - $this->rememberMeComponent->request = (new ServerRequest('/'))->env('HTTP_USER_AGENT', 'user-agent') + $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') diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 5f85dbf75..11ef64357 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -64,7 +64,7 @@ public function setUp() 'controller' => 'Users', 'action' => 'edit' ]); - Security::salt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); + Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); Configure::write('App.namespace', 'Users'); $this->request = $this->getMockBuilder('Cake\Network\Request') ->setMethods(['is', 'method']) diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 043c1651c..97363cf0e 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -381,7 +381,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->errors([ + $user->setErrors([ 'social_accounts' => [ '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') ] diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index 0ec9cb9d0..03165a769 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -91,14 +91,14 @@ public function testTokenExpired() */ public function testTokenExpiredLocale() { - I18n::locale('es_AR'); + I18n::setLocale('es_AR'); $this->User->token_expires = '+1 day'; $isExpired = $this->User->tokenExpired(); $this->assertFalse($isExpired); $this->User->token_expires = '-1 day'; $isExpired = $this->User->tokenExpired(); $this->assertTrue($isExpired); - I18n::locale('en_US'); + I18n::setLocale('en_US'); } /** diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index ee0f0da5e..3817c10ef 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -122,7 +122,7 @@ public function testLinkAuthorizedAllowedFalse() $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') ->setMethods(['dispatch']) ->getMock(); - $view->eventManager($eventManagerMock); + $view->getEventManager($eventManagerMock); $this->AuthLink = new AuthLinkHelper($view); $result = new Event('dispatch-result'); $eventManagerMock->expects($this->never()) diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 955719672..a995c72ca 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -240,10 +240,10 @@ public function testSocialLoginLink() */ public function testSocialLoginTranslation() { - I18n::locale('es_ES'); + I18n::setLocale('es_ES'); $result = $this->User->socialLogin('facebook'); $this->assertEquals('Iniciar sesión con Facebook', $result); - I18n::locale('en_US'); + I18n::setLocale('en_US'); } /** From 0c2c6fb7126078e6f4970cfb88a544bbbba11c9b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 8 Sep 2017 13:47:35 +0200 Subject: [PATCH 0705/1476] Remove orWhere --- src/Model/Behavior/AuthFinderBehavior.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index bc906831c..dc7bb9817 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -48,11 +48,13 @@ public function findAuth(Query $query, array $options = []) if (empty($identifier)) { throw new \BadMethodCallException(__d('CakeDC/Users', 'Missing \'username\' in options data')); } - + $where = $query->clause('where'); $query - ->orWhere([$this->_table->aliasField('email') => $identifier]) + ->where(function ($exp) use ($identifier, $where) { + $or = $exp->or_([$this->_table->aliasField('email') => $identifier]); + return $or->add($where); + }, [], true) ->find('active', $options); - return $query; } } From fbe05463574d83ce84beb6c1da02f3022a05f616 Mon Sep 17 00:00:00 2001 From: Jorge Gonzalez Date: Tue, 12 Sep 2017 23:02:33 +0100 Subject: [PATCH 0706/1476] refs #608 use randomBytes to generate token --- src/Model/Entity/User.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 98c0ddfe0..e4c8b8520 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -14,8 +14,7 @@ use Cake\Core\Configure; use Cake\I18n\Time; use Cake\ORM\Entity; -use Cake\Utility\Text; -use DateTime; +use Cake\Utility\Security; /** * User Entity. @@ -159,7 +158,6 @@ public function updateToken($tokenExpiration = 0) { $expiration = new Time('now'); $this->token_expires = $expiration->addSeconds($tokenExpiration); - - $this->token = str_replace('-', '', Text::uuid()); + $this->token = bin2hex(Security::randomBytes(16)); } } From ee74795101ac2831efa9cb52e1337bf0c2074aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 16 Sep 2017 21:03:22 +0100 Subject: [PATCH 0707/1476] refs #remove-deprecated fix failing tests --- src/Model/Behavior/AuthFinderBehavior.php | 2 +- tests/TestCase/Auth/SocialAuthenticateTest.php | 4 ++-- .../Controller/Traits/SocialTraitTest.php | 16 ++++++++-------- tests/TestCase/View/Helper/UserHelperTest.php | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index dc7bb9817..01a845e5d 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -48,7 +48,7 @@ public function findAuth(Query $query, array $options = []) if (empty($identifier)) { throw new \BadMethodCallException(__d('CakeDC/Users', 'Missing \'username\' in options data')); } - $where = $query->clause('where'); + $where = $query->clause('where') ?: []; $query ->where(function ($exp) use ($identifier, $where) { $or = $exp->or_([$this->_table->aliasField('email') => $identifier]); diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index f3c86b866..47dc9e4a3 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -253,10 +253,10 @@ public function testGetUserSessionData() ->with('Users.social'); $this->Request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session']) + ->setMethods(['getSession']) ->getMock(); $this->Request->expects($this->any()) - ->method('session') + ->method('getSession') ->will($this->returnValue($session)); $this->SocialAuthenticate->expects($this->once()) diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 0fb464c38..683a23d81 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -58,10 +58,10 @@ public function testSocialEmail() ->with('Flash.auth'); $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session']) + ->setMethods(['getSession']) ->getMock(); $this->controller->Trait->request->expects($this->any()) - ->method('session') + ->method('getSession') ->will($this->returnValue($session)); $this->controller->Trait->socialEmail(); @@ -83,10 +83,10 @@ public function testSocialEmailInvalid() ->will($this->returnValue(null)); $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session']) + ->setMethods(['getSession']) ->getMock(); $this->controller->Trait->request->expects($this->once()) - ->method('session') + ->method('getSession') ->will($this->returnValue($session)); $this->controller->Trait->socialEmail(); @@ -107,10 +107,10 @@ public function testSocialEmailPostValidateFalse() ->with('Flash.auth'); $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session', 'is']) + ->setMethods(['getSession', 'is']) ->getMock(); $this->controller->Trait->request->expects($this->any()) - ->method('session') + ->method('getSession') ->will($this->returnValue($session)); $this->controller->Trait->request->expects($this->once()) @@ -149,10 +149,10 @@ public function testSocialEmailPostValidateTrue() ->with('Flash.auth'); $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session', 'is']) + ->setMethods(['getSession', 'is']) ->getMock(); $this->controller->Trait->request->expects($this->any()) - ->method('session') + ->method('getSession') ->will($this->returnValue($session)); $this->controller->Trait->request->expects($this->once()) diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index a995c72ca..b63521935 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -145,10 +145,10 @@ public function testWelcome() ->will($this->returnValue('david')); $this->User->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session']) + ->setMethods(['getSession']) ->getMock(); $this->User->request->expects($this->any()) - ->method('session') + ->method('getSession') ->will($this->returnValue($session)); $expected = 'Welcome, david'; @@ -172,10 +172,10 @@ public function testWelcomeNotLoggedInUser() ->will($this->returnValue(null)); $this->User->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['session']) + ->setMethods(['getSession']) ->getMock(); $this->User->request->expects($this->any()) - ->method('session') + ->method('getSession') ->will($this->returnValue($session)); $result = $this->User->welcome(); From 58448db3c232cb8bbd0ea2c5886e339676f18f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 16 Sep 2017 21:03:24 +0100 Subject: [PATCH 0708/1476] fix cs --- src/Model/Behavior/AuthFinderBehavior.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index 01a845e5d..ef51d1fc9 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -52,9 +52,11 @@ public function findAuth(Query $query, array $options = []) $query ->where(function ($exp) use ($identifier, $where) { $or = $exp->or_([$this->_table->aliasField('email') => $identifier]); + return $or->add($where); }, [], true) ->find('active', $options); + return $query; } } From 24f24734cb1bb0d5e044c5f790583e3fd793e7e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 16 Sep 2017 21:06:58 +0100 Subject: [PATCH 0709/1476] refs #remove-deprecated upgrade cakephp version due to new API used --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fd48c4a72..90489899e 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "^3.4.0", + "cakephp/cakephp": "^3.5.0", "cakedc/auth": "^2.0" }, "require-dev": { From d3bea20dda336370dd2f88de2b3d2b66b318016f Mon Sep 17 00:00:00 2001 From: Peter Moraes Date: Tue, 19 Sep 2017 18:40:43 -0300 Subject: [PATCH 0710/1476] refs #573 fixing unit tests --- src/Model/Behavior/SocialBehavior.php | 27 +++++++-------- .../Model/Behavior/SocialBehaviorTest.php | 33 +++++++++++++++++++ 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 6b969a8dd..8e51e450a 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -85,24 +85,20 @@ public function socialLogin(array $data, array $options) $user = $existingAccount->user; } if (!empty($existingAccount)) { - if ($existingAccount->active) { - if ($user->active) { - return $user; - } else { - throw new UserNotActiveException([ - $existingAccount->provider, - $existingAccount->$user - ]); - } - } else { + if (!$existingAccount->active) { throw new AccountNotActiveException([ $existingAccount->provider, $existingAccount->reference ]); } + if (!$user->active) { + throw new UserNotActiveException([ + $existingAccount->provider, + $existingAccount->$user + ]); + } } - - return false; + return $user; } /** @@ -124,8 +120,8 @@ protected function _createSocialUser($data, $options = []) throw new MissingEmailException(__d('CakeDC/Users', 'Email not present')); } else { $existingUser = $this->_table->find() - ->where([$this->_table->aliasField('email') => $email]) - ->first(); + ->where([$this->_table->aliasField('email') => $email]) + ->first(); } $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); @@ -204,6 +200,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['username'] = preg_replace('/[^A-Za-z0-9]/i', '', Hash::get($userData, 'username')); } } + $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); if ($useEmail) { $userData['email'] = Hash::get($data, 'email'); @@ -246,7 +243,7 @@ public function generateUniqueUsername($username) $i = 0; while (true) { $existingUsername = $this->_table->find() - ->where([$this->_table->aliasField('username') => $username]) + ->where([$this->_table->aliasField($this->_username) => $username]) ->count(); if ($existingUsername > 0) { $username = $username . $i; diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php index 497e2816c..0582eac9b 100644 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -86,6 +86,39 @@ public function testSocialLoginFacebookProvider($data, $options, $dataUser) $this->assertEquals($result, $user); } + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerFacebookSocialLogin + */ + public function testSocialLoginFacebookProviderUsingEmail($data, $options, $dataUser) + { + $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); + $user->password = '$2y$10$0QzszaIEpW1pYpoKJVf4DeqEAHtg9whiLTX/l3TcHAoOLF1bC9U.6'; + + $this->Behavior->expects($this->once()) + ->method('generateUniqueUsername') + ->with('email') + ->will($this->returnValue('username')); + + $this->Behavior->expects($this->once()) + ->method('randomString') + ->will($this->returnValue('password')); + + $this->Behavior->expects($this->once()) + ->method('_updateActive') + ->will($this->returnValue($user)); + + $this->Table->expects($this->once()) + ->method('save') + ->with($user) + ->will($this->returnValue($user)); + + $this->Behavior->initialize(['username' => 'email']); + $result = $this->Behavior->socialLogin($data, $options); + $this->assertEquals($result, $user); + } + /** * Provider for socialLogin with facebook and not existing user * From 2712979edfe02c24130a34f36c77baeb69445f50 Mon Sep 17 00:00:00 2001 From: Peter Moraes Date: Tue, 19 Sep 2017 18:45:57 -0300 Subject: [PATCH 0711/1476] refs #573 fixing phpcs --- src/Model/Behavior/SocialBehavior.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 8e51e450a..7fdd2c0f0 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -98,6 +98,7 @@ public function socialLogin(array $data, array $options) ]); } } + return $user; } From 3f035d55d620fa482306094935e94f6bccf6376c Mon Sep 17 00:00:00 2001 From: Peter Moraes Date: Thu, 21 Sep 2017 16:29:16 -0300 Subject: [PATCH 0712/1476] refs #573 adding custom username to the documentation --- Docs/Documentation/SocialAuthenticate.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index f8648a649..ed1f4391f 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -72,3 +72,17 @@ We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-soci Social Authentication was inspired by [UseMuffin/OAuth2](https://github.com/UseMuffin/OAuth2) library. +Custom username field +--------------------- + +You can custom the username field in the SocialBehavior. It's pretty simple. + +In your `UsersCustomTable` you just need to add the SocialBehavior in this way. + +```php +$this->addBehavior('CakeDC.Users/Social', [ + 'username' => 'email' +]); +``` + +By default it will use `username` field. \ No newline at end of file From ef439c2430138015c3344b2365bbbc5f086c9c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 22 Sep 2017 08:22:42 +0100 Subject: [PATCH 0713/1476] Update SocialAuthenticate.md --- Docs/Documentation/SocialAuthenticate.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index ed1f4391f..d251c33ca 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -75,9 +75,7 @@ Social Authentication was inspired by [UseMuffin/OAuth2](https://github.com/UseM Custom username field --------------------- -You can custom the username field in the SocialBehavior. It's pretty simple. - -In your `UsersCustomTable` you just need to add the SocialBehavior in this way. +In your customized users table, add the SocialBehavior with the following configuration: ```php $this->addBehavior('CakeDC.Users/Social', [ @@ -85,4 +83,4 @@ $this->addBehavior('CakeDC.Users/Social', [ ]); ``` -By default it will use `username` field. \ No newline at end of file +By default it will use `username` field. From 2f76541b913ca950ba7939e6d468fab58d3b92c8 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 22 Sep 2017 14:08:43 +0200 Subject: [PATCH 0714/1476] Fix twitter avatar --- src/Auth/Social/Mapper/Twitter.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Auth/Social/Mapper/Twitter.php b/src/Auth/Social/Mapper/Twitter.php index 294b4c4c5..3dccfa45f 100644 --- a/src/Auth/Social/Mapper/Twitter.php +++ b/src/Auth/Social/Mapper/Twitter.php @@ -48,4 +48,12 @@ protected function _link() { return self::TWITTER_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); } + + /** + * @return string + */ + protected function _avatar() + { + return str_replace('normal', 'bigger', Hash::get($this->_rawData, $this->_mapFields['avatar'])); + } } From 8d7d450c1e7e760b2d3a56b6cb51c53f52b17535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 4 Oct 2017 13:10:58 +0100 Subject: [PATCH 0715/1476] fix warning for missing key --- src/Controller/Traits/LoginTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 7ead3f08d..531a386f9 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -228,7 +228,7 @@ public function verify() $secret = $temporarySession['secret']; } - $secretVerified = $temporarySession['secret_verified']; + $secretVerified = Hash::get((array)$temporarySession, 'secret_verified'); // showing QR-code until shared secret is verified if (!$secretVerified) { @@ -251,7 +251,7 @@ public function verify() } } $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( - Hash::get($temporarySession, 'email'), + Hash::get((array)$temporarySession, 'email'), $secret ); $this->set(compact('secretDataUri')); From 3ed198639621f5d7aae724e960b059208b846cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 4 Oct 2017 15:41:05 +0100 Subject: [PATCH 0716/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 262596eca..e9855cbaa 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 5 -:minor: 1 +:minor: 2 :patch: 0 :special: '' From b44828e3a679574fdbc5bd91ead1c98f56ae1461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 4 Oct 2017 15:46:49 +0100 Subject: [PATCH 0717/1476] Update CHANGELOG.md --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49207f43f..b16c8ad66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ Changelog Releases for CakePHP 3 ------------- +* 5.2.0 + * Compatible with 3.5, deprecations will be removed in next major version of the plugin + * Username is now custom in SocialBehavior + * Better handling of the RememberMe checkbox + * Updated CakeDC/Auth to use ^2.0 + * Use of UsersMailer class, and allow override of the emails sent by the plugin + * Better token generation via randomBytes + * Improved documentation + * Fixed bugs reported + * 5.1.0 * New resend validation method in RegisterBehavior * Allow upgrade to CakePHP 3.5.x From 7ec8dc390d5639524c9e7f9367944f30aeb03036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 4 Oct 2017 15:55:29 +0100 Subject: [PATCH 0718/1476] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8c397f8ac..dd818848b 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,9 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.1.2 | Note CakePHP 2.7 is currently not supported, we are working on it now | -| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.0.3 | stable | +| 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.1.2 | Note CakePHP 2.7 is currently not supported | +| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.2.0 | stable | | 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| 3.0 | [3.0.x](https://github.com/cakedc/users/tree/3.0.x) | 3.0.0 | stable | -| 3.1 | [3.1.x](https://github.com/cakedc/users/tree/3.1.x) | 3.1.0 | stable | | 3.3 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.0 | stable | The **Users** plugin is back! From f482037c4290c11dadb68a02ee1740091ec51b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 4 Oct 2017 15:55:56 +0100 Subject: [PATCH 0719/1476] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dd818848b..777b7210b 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.1.2 | Note CakePHP 2.7 is currently not supported | | 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.2.0 | stable | | 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 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.1.2 | Note CakePHP 2.7 is currently not supported | The **Users** plugin is back! From c8f7c35dbf2b4da09a7950f8c61226beb283f23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 4 Oct 2017 15:57:53 +0100 Subject: [PATCH 0720/1476] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 777b7210b..1080b6ece 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Versions and branches | :-------------: | :------------------------: | :--: | :---- | | 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.2.0 | stable | | 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | +| 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.1.2 | Note CakePHP 2.7 is currently not supported | From 9331762ae1e76c00931b3d687040fe57645d13fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 4 Oct 2017 16:00:11 +0100 Subject: [PATCH 0721/1476] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1080b6ece..4624e27cf 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| 3.4+ | [master](https://github.com/cakedc/users/tree/master) | 5.2.0 | stable | -| 3.4+ | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | +| ^3.4 | [master](https://github.com/cakedc/users/tree/master) | 5.2.0 | stable | +| ^3.5 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 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.1.2 | Note CakePHP 2.7 is currently not supported | From 090cec188ce61bcb5f3c18f408f4e0094abf2f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Mon, 9 Oct 2017 13:35:17 +0100 Subject: [PATCH 0722/1476] update migration docs for permissions load --- Docs/Documentation/Migration/4.x-5.0.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Migration/4.x-5.0.md b/Docs/Documentation/Migration/4.x-5.0.md index 1382c4331..9aba06bd3 100644 --- a/Docs/Documentation/Migration/4.x-5.0.md +++ b/Docs/Documentation/Migration/4.x-5.0.md @@ -4,7 +4,7 @@ Migration 4.x to 5.0 5.0 is compatible with CakePHP ^3.4 and refactored some Auth objects into a new plugin * Fix your Users configuration file, usually under `config/users.php` for Auth object references -in `users.php` +in `config/users.php` ```php $config = [ @@ -28,7 +28,7 @@ $config = [ * Add a new configuration key to specify the controller name you are using to handle auth in your project -in `users.php` +in `config/users.php` ```php $config = [ @@ -39,3 +39,18 @@ $config = [ // ... ``` +* If you are using simple RBAC, set `CakeDC/Auth.SimpleRbac.permissions` configuration key to `null` if you want to load permissions from the file `config/permissions.php`. + +in `config/users.php` + +```php +$config = [ + 'Auth.authorize' => [ + 'CakeDC/Auth.SimpleRbac' => [ + 'autoload_config' => 'permissions', + 'permissions' => null, + ], + ], +``` + +If the value is false or empty array, now it is assumed there is no permissions for the user. \ No newline at end of file From 32a72a9ae221d3ee7609d73459e34679d4a32425 Mon Sep 17 00:00:00 2001 From: madbbb Date: Tue, 10 Oct 2017 19:02:53 +0300 Subject: [PATCH 0723/1476] Input labels translation --- src/Template/Users/login.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 60b36c2af..440f01270 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -17,8 +17,8 @@ use Cake\Core\Configure; Form->create() ?>
    - Form->input('username', ['required' => true]) ?> - Form->input('password', ['required' => true]) ?> + Form->input('username', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> + Form->input('password', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> User->addReCaptcha(); From 15490d22938c6925866c480d4fc46df964994d6e Mon Sep 17 00:00:00 2001 From: madbbb Date: Tue, 10 Oct 2017 19:11:47 +0300 Subject: [PATCH 0724/1476] Input labels translation --- src/Template/Users/login.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 440f01270..9fe1fbed6 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -18,7 +18,7 @@ use Cake\Core\Configure;
    Form->input('username', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> - Form->input('password', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> + Form->input('password', ['label' => __d('CakeDC/Users', 'Password'), 'required' => true]) ?> User->addReCaptcha(); From 557e369dfc2ac9c2e4a6c5ba95f397f96b62dbe7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 14 Oct 2017 20:57:51 -0300 Subject: [PATCH 0725/1476] Update Users.pot with 'bin/cake i18n extract' --- src/Locale/Users.pot | 481 ++++++++++++++++++++++--------------------- 1 file changed, 245 insertions(+), 236 deletions(-) diff --git a/src/Locale/Users.pot b/src/Locale/Users.pot index e34d1e324..6d82471e0 100644 --- a/src/Locale/Users.pot +++ b/src/Locale/Users.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2016-10-26 09:23+0000\n" +"POT-Creation-Date: 2017-10-14 23:45+0000\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" @@ -14,34 +14,10 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: Auth/ApiKeyAuthenticate.php:73 -msgid "Type {0} is not valid" -msgstr "" - -#: Auth/ApiKeyAuthenticate.php:77 -msgid "Type {0} has no associated callable" -msgstr "" - -#: Auth/ApiKeyAuthenticate.php:86 -msgid "SSL is required for ApiKey Authentication" -msgstr "" - -#: Auth/SimpleRbacAuthorize.php:142 -msgid "Missing configuration file: \"config/{0}.php\". Using default permissions" -msgstr "" - -#: Auth/SocialAuthenticate.php:432 +#: Auth/SocialAuthenticate.php:456 msgid "Provider cannot be empty" msgstr "" -#: Auth/Rules/AbstractRule.php:78 -msgid "Table alias is empty, please define a table alias, we could not extract a default table from the request" -msgstr "" - -#: Auth/Rules/Owner.php:67;70 -msgid "Missing column {0} in table {1} while checking ownership permissions for user {2}" -msgstr "" - #: Controller/SocialAccountsController.php:52 msgid "Account validated successfully" msgstr "" @@ -78,378 +54,406 @@ msgstr "" msgid "Email could not be resent" msgstr "" -#: Controller/Component/RememberMeComponent.php:69 +#: Controller/Component/RememberMeComponent.php:68 msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" msgstr "" -#: Controller/Component/UsersAuthComponent.php:178 +#: Controller/Component/UsersAuthComponent.php:204 msgid "You can't enable email validation workflow if use_email is false" msgstr "" -#: Controller/Traits/LoginTrait.php:96 +#: 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:101 +#: Controller/Traits/LoginTrait.php:109 #: Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "" -#: Controller/Traits/LoginTrait.php:108 +#: Controller/Traits/LoginTrait.php:120 msgid "Your user has not been validated yet. Please check your inbox for instructions" msgstr "" -#: Controller/Traits/LoginTrait.php:110 +#: 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:161 -#: Controller/Traits/RegisterTrait.php:81 +#: Controller/Traits/LoginTrait.php:180 +#: Controller/Traits/RegisterTrait.php:82 msgid "Invalid reCaptcha" msgstr "" -#: Controller/Traits/LoginTrait.php:171 +#: Controller/Traits/LoginTrait.php:191 msgid "You are already logged in" msgstr "" -#: Controller/Traits/LoginTrait.php:217 +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "" + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "" + +#: Controller/Traits/LoginTrait.php:340 msgid "Username or password is incorrect" msgstr "" -#: Controller/Traits/LoginTrait.php:238 +#: Controller/Traits/LoginTrait.php:363 msgid "You've successfully logged out" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:47;76 -#: Controller/Traits/ProfileTrait.php:49 +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 msgid "User was not found" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 msgid "Password could not be changed" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:68 +#: Controller/Traits/PasswordManagementTrait.php:74 msgid "Password has been changed successfully" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:78 +#: Controller/Traits/PasswordManagementTrait.php:84 msgid "{0}" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:120 +#: Controller/Traits/PasswordManagementTrait.php:127 msgid "Please check your email to continue with password reset process" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:123 -#: Shell/UsersShell.php:267 +#: 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:129 -#: Controller/Traits/UserValidationTrait.php:100 +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 msgid "User {0} was not found" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:131 +#: Controller/Traits/PasswordManagementTrait.php:138 msgid "The user is not active" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:133 -#: Controller/Traits/UserValidationTrait.php:95;104 +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 msgid "Token could not be reset" msgstr "" -#: Controller/Traits/ProfileTrait.php:53 +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "" + +#: Controller/Traits/ProfileTrait.php:54 msgid "Not authorized, please login first" msgstr "" -#: Controller/Traits/RegisterTrait.php:42 +#: Controller/Traits/RegisterTrait.php:43 msgid "You must log out to register a new user account" msgstr "" -#: Controller/Traits/RegisterTrait.php:88 +#: Controller/Traits/RegisterTrait.php:89 msgid "The user could not be saved" msgstr "" -#: Controller/Traits/RegisterTrait.php:122 +#: Controller/Traits/RegisterTrait.php:123 msgid "You have registered successfully, please log in" msgstr "" -#: Controller/Traits/RegisterTrait.php:124 +#: Controller/Traits/RegisterTrait.php:125 msgid "Please validate your account before log in" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:76;106 +#: Controller/Traits/SimpleCrudTrait.php:77;107 msgid "The {0} has been saved" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:80;110 +#: Controller/Traits/SimpleCrudTrait.php:81;111 msgid "The {0} could not be saved" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:130 +#: Controller/Traits/SimpleCrudTrait.php:131 msgid "The {0} has been deleted" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:132 +#: Controller/Traits/SimpleCrudTrait.php:133 msgid "The {0} could not be deleted" msgstr "" -#: Controller/Traits/SocialTrait.php:39 +#: Controller/Traits/SocialTrait.php:40 msgid "The reCaptcha could not be validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:42 +#: Controller/Traits/UserValidationTrait.php:43 msgid "User account validated successfully" msgstr "" -#: Controller/Traits/UserValidationTrait.php:44 +#: Controller/Traits/UserValidationTrait.php:45 msgid "User account could not be validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:47 +#: Controller/Traits/UserValidationTrait.php:48 msgid "User already active" msgstr "" -#: Controller/Traits/UserValidationTrait.php:53 +#: Controller/Traits/UserValidationTrait.php:54 msgid "Reset password token was validated successfully" msgstr "" -#: Controller/Traits/UserValidationTrait.php:58 +#: Controller/Traits/UserValidationTrait.php:62 msgid "Reset password token could not be validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:62 +#: Controller/Traits/UserValidationTrait.php:66 msgid "Invalid validation type" msgstr "" -#: Controller/Traits/UserValidationTrait.php:65 +#: Controller/Traits/UserValidationTrait.php:69 msgid "Invalid token or user account already validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:67 +#: Controller/Traits/UserValidationTrait.php:71 msgid "Token already expired" msgstr "" -#: Controller/Traits/UserValidationTrait.php:93 +#: Controller/Traits/UserValidationTrait.php:97 msgid "Token has been reset successfully. Please check your email." msgstr "" -#: Controller/Traits/UserValidationTrait.php:102 +#: Controller/Traits/UserValidationTrait.php:109 msgid "User {0} is already active" msgstr "" -#: Email/EmailSender.php:39 +#: Mailer/UsersMailer.php:34 msgid "Your account validation link" msgstr "" -#: Mailer/UsersMailer.php:55 +#: Mailer/UsersMailer.php:52 msgid "{0}Your reset password link" msgstr "" -#: Mailer/UsersMailer.php:78 +#: Mailer/UsersMailer.php:75 msgid "{0}Your social account validation link" msgstr "" -#: Model/Behavior/PasswordBehavior.php:56 +#: 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:61 +#: Model/Behavior/PasswordBehavior.php:50 msgid "Token expiration cannot be empty" msgstr "" -#: Model/Behavior/PasswordBehavior.php:67;116 +#: Model/Behavior/PasswordBehavior.php:56;117 msgid "User not found" msgstr "" -#: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:111 +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 msgid "User account already validated" msgstr "" -#: Model/Behavior/PasswordBehavior.php:78 +#: Model/Behavior/PasswordBehavior.php:67 msgid "User not active" msgstr "" -#: Model/Behavior/PasswordBehavior.php:121 +#: Model/Behavior/PasswordBehavior.php:122 msgid "The current password does not match" msgstr "" -#: Model/Behavior/PasswordBehavior.php:124 +#: Model/Behavior/PasswordBehavior.php:125 msgid "You cannot use the current password as the new one" msgstr "" -#: Model/Behavior/RegisterBehavior.php:89 +#: Model/Behavior/RegisterBehavior.php:90 msgid "User not found for the given token and email." msgstr "" -#: Model/Behavior/RegisterBehavior.php:92 +#: Model/Behavior/RegisterBehavior.php:93 msgid "Token has already expired user with no token" msgstr "" -#: Model/Behavior/SocialAccountBehavior.php:102;129 +#: Model/Behavior/SocialAccountBehavior.php:103;130 msgid "Account already validated" msgstr "" -#: Model/Behavior/SocialAccountBehavior.php:105;132 +#: Model/Behavior/SocialAccountBehavior.php:106;133 msgid "Account not found for the given token and email." msgstr "" -#: Model/Behavior/SocialBehavior.php:56 +#: Model/Behavior/SocialBehavior.php:82 msgid "Unable to login user with reference {0}" msgstr "" -#: Model/Behavior/SocialBehavior.php:98 +#: Model/Behavior/SocialBehavior.php:121 msgid "Email not present" msgstr "" -#: Model/Table/UsersTable.php:82 +#: Model/Table/UsersTable.php:81 msgid "Your password does not match your confirm password. Please try again" msgstr "" -#: Model/Table/UsersTable.php:175 +#: Model/Table/UsersTable.php:173 msgid "Username already exists" msgstr "" -#: Model/Table/UsersTable.php:181 +#: Model/Table/UsersTable.php:179 msgid "Email already exists" msgstr "" -#: Model/Table/UsersTable.php:214 -msgid "Missing 'username' in options data" -msgstr "" - -#: Shell/UsersShell.php:54 +#: Shell/UsersShell.php:58 msgid "Utilities for CakeDC Users Plugin" msgstr "" -#: Shell/UsersShell.php:55 +#: Shell/UsersShell.php:60 msgid "Activate an specific user" msgstr "" -#: Shell/UsersShell.php:56 +#: Shell/UsersShell.php:63 msgid "Add a new superadmin user for testing purposes" msgstr "" -#: Shell/UsersShell.php:57 +#: Shell/UsersShell.php:66 msgid "Add a new user" msgstr "" -#: Shell/UsersShell.php:58 +#: Shell/UsersShell.php:69 msgid "Change the role for an specific user" msgstr "" -#: Shell/UsersShell.php:59 +#: Shell/UsersShell.php:72 msgid "Deactivate an specific user" msgstr "" -#: Shell/UsersShell.php:60 +#: Shell/UsersShell.php:75 msgid "Delete an specific user" msgstr "" -#: Shell/UsersShell.php:61 +#: Shell/UsersShell.php:78 msgid "Reset the password via email" msgstr "" -#: Shell/UsersShell.php:62 +#: Shell/UsersShell.php:81 msgid "Reset the password for all users" msgstr "" -#: Shell/UsersShell.php:63 +#: Shell/UsersShell.php:84 msgid "Reset the password for an specific user" msgstr "" -#: Shell/UsersShell.php:98 -msgid "User added:" +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." msgstr "" -#: Shell/UsersShell.php:99;127 -msgid "Id: {0}" +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" msgstr "" -#: Shell/UsersShell.php:100;128 -msgid "Username: {0}" +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" msgstr "" -#: Shell/UsersShell.php:101;129 -msgid "Email: {0}" +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." msgstr "" -#: Shell/UsersShell.php:102;130 -msgid "Password: {0}" +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" msgstr "" -#: Shell/UsersShell.php:126 -msgid "Superuser added:" +#: Shell/UsersShell.php:187 +msgid "Please enter a role." msgstr "" -#: Shell/UsersShell.php:132 -msgid "Superuser could not be added:" +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" msgstr "" -#: Shell/UsersShell.php:135 -msgid "Field: {0} Error: {1}" +#: Shell/UsersShell.php:194 +msgid "New role: {0}" msgstr "" -#: Shell/UsersShell.php:153;179 -msgid "Please enter a password." +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" msgstr "" -#: Shell/UsersShell.php:157 -msgid "Password changed for all users" +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" msgstr "" -#: Shell/UsersShell.php:158;186 -msgid "New password: {0}" +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." msgstr "" -#: Shell/UsersShell.php:176;204;282;324 -msgid "Please enter a username." +#: Shell/UsersShell.php:244 +msgid "Please ask the user to check the email to continue with password reset process" msgstr "" -#: Shell/UsersShell.php:185 -msgid "Password changed for user: {0}" +#: Shell/UsersShell.php:308 +msgid "Superuser added:" msgstr "" -#: Shell/UsersShell.php:207 -msgid "Please enter a role." +#: Shell/UsersShell.php:310 +msgid "User added:" msgstr "" -#: Shell/UsersShell.php:213 -msgid "Role changed for user: {0}" +#: Shell/UsersShell.php:312 +msgid "Id: {0}" msgstr "" -#: Shell/UsersShell.php:214 -msgid "New role: {0}" +#: Shell/UsersShell.php:313 +msgid "Username: {0}" msgstr "" -#: Shell/UsersShell.php:229 -msgid "User was activated: {0}" +#: Shell/UsersShell.php:314 +msgid "Email: {0}" msgstr "" -#: Shell/UsersShell.php:244 -msgid "User was de-activated: {0}" +#: Shell/UsersShell.php:315 +msgid "Role: {0}" msgstr "" -#: Shell/UsersShell.php:256 -msgid "Please enter a username or email." +#: Shell/UsersShell.php:316 +msgid "Password: {0}" msgstr "" -#: Shell/UsersShell.php:264 -msgid "Please ask the user to check the email to continue with password reset process" +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" msgstr "" -#: Shell/UsersShell.php:302 +#: Shell/UsersShell.php:337 msgid "The user was not found." msgstr "" -#: Shell/UsersShell.php:332 +#: Shell/UsersShell.php:367 msgid "The user {0} was not deleted. Please try again" msgstr "" -#: Shell/UsersShell.php:334 +#: Shell/UsersShell.php:369 msgid "The user {0} was deleted successfully" msgstr "" @@ -469,15 +473,15 @@ 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 correcly displayed, please copy the following address in your web browser {0}" +msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" msgstr "" -#: Template/Email/html/reset_password.ctp:30 -#: Template/Email/html/social_account_validation.ctp:35 -#: Template/Email/html/validation.ctp:30 -#: Template/Email/text/reset_password.ctp:24 -#: Template/Email/text/social_account_validation.ctp:26 -#: Template/Email/text/validation.ctp:24 +#: 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 "" @@ -499,71 +503,70 @@ msgid "Please copy the following address in your web browser to activate your so msgstr "" #: Template/Users/add.ctp:13 -#: Template/Users/edit.ctp:15 +#: Template/Users/edit.ctp:16 #: Template/Users/index.ctp:13;26 -#: Template/Users/view.ctp:15;79 +#: Template/Users/view.ctp:15 msgid "Actions" msgstr "" #: Template/Users/add.ctp:15 -#: Template/Users/edit.ctp:26 -#: Template/Users/view.ctp:19 -msgid "List Users" -msgstr "" - -#: Template/Users/add.ctp:16 #: Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:21 -msgid "List Accounts" +#: Template/Users/view.ctp:23 +msgid "List Users" msgstr "" -#: Template/Users/add.ctp:22 -#: Template/Users/register.ctp:16 +#: Template/Users/add.ctp:21 +#: Template/Users/register.ctp:17 msgid "Add User" msgstr "" -#: Template/Users/add.ctp:24 +#: Template/Users/add.ctp:23 #: Template/Users/edit.ctp:35 #: Template/Users/index.ctp:22 -#: Template/Users/profile.ctp:27 -#: Template/Users/register.ctp:18 -#: Template/Users/view.ctp:30;70 +#: Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 +#: Template/Users/view.ctp:33 msgid "Username" msgstr "" -#: Template/Users/add.ctp:25 +#: Template/Users/add.ctp:24 #: Template/Users/edit.ctp:36 #: Template/Users/index.ctp:23 -#: Template/Users/profile.ctp:29 -#: Template/Users/register.ctp:19 -#: Template/Users/view.ctp:32 +#: 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:25 +#: 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:26 +#: Template/Users/register.ctp:27 msgid "Last name" msgstr "" #: Template/Users/add.ctp:30 #: Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:44;75 +#: 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:35 +#: 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 @@ -583,19 +586,18 @@ msgid "New password" msgstr "" #: Template/Users/change_password.ctp:21 -#: Template/Users/register.ctp:23 +#: Template/Users/register.ctp:24 msgid "Confirm password" msgstr "" -#: Template/Users/edit.ctp:20 +#: Template/Users/edit.ctp:21 #: Template/Users/index.ctp:40 -#: Template/Users/view.ctp:101 msgid "Delete" msgstr "" -#: Template/Users/edit.ctp:22 +#: Template/Users/edit.ctp:23 #: Template/Users/index.ctp:40 -#: Template/Users/view.ctp:18;101 +#: Template/Users/view.ctp:21 msgid "Are you sure you want to delete # {0}?" msgstr "" @@ -605,7 +607,7 @@ msgid "Edit User" msgstr "" #: Template/Users/edit.ctp:39 -#: Template/Users/view.ctp:38;73 +#: Template/Users/view.ctp:43 msgid "Token" msgstr "" @@ -625,12 +627,19 @@ msgstr "" msgid "TOS date" msgstr "" +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "" + #: Template/Users/index.ctp:15 msgid "New {0}" msgstr "" #: Template/Users/index.ctp:37 -#: Template/Users/view.ctp:97 msgid "View" msgstr "" @@ -639,7 +648,6 @@ msgid "Change password" msgstr "" #: Template/Users/index.ctp:39 -#: Template/Users/view.ctp:99 msgid "Edit" msgstr "" @@ -671,42 +679,39 @@ msgstr "" msgid "Login" msgstr "" -#: Template/Users/profile.ctp:18 -#: View/Helper/UserHelper.php:51 +#: Template/Users/profile.ctp:21 +#: View/Helper/UserHelper.php:54 msgid "{0} {1}" msgstr "" -#: Template/Users/profile.ctp:24 +#: Template/Users/profile.ctp:27 msgid "Change Password" msgstr "" -#: Template/Users/profile.ctp:34 +#: Template/Users/profile.ctp:38 +#: Template/Users/view.ctp:68 msgid "Social Accounts" msgstr "" -#: Template/Users/profile.ctp:38 -#: Template/Users/view.ctp:72 +#: Template/Users/profile.ctp:42 +#: Template/Users/view.ctp:73 msgid "Avatar" msgstr "" -#: Template/Users/profile.ctp:39 -#: Template/Users/view.ctp:69 +#: Template/Users/profile.ctp:43 +#: Template/Users/view.ctp:72 msgid "Provider" msgstr "" -#: Template/Users/profile.ctp:40 +#: Template/Users/profile.ctp:44 msgid "Link" msgstr "" -#: Template/Users/profile.ctp:47 +#: Template/Users/profile.ctp:51 msgid "Link to {0}" msgstr "" -#: Template/Users/register.ctp:20 -msgid "Password" -msgstr "" - -#: Template/Users/register.ctp:28 +#: Template/Users/register.ctp:29 msgid "Accept TOS conditions?" msgstr "" @@ -722,91 +727,95 @@ msgstr "" msgid "Email or username" msgstr "" -#: Template/Users/view.ctp:18 +#: 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:20 +#: Template/Users/view.ctp:24 msgid "New User" msgstr "" -#: Template/Users/view.ctp:28;67 +#: Template/Users/view.ctp:31 msgid "Id" msgstr "" -#: Template/Users/view.ctp:34 +#: Template/Users/view.ctp:37 msgid "First Name" msgstr "" -#: Template/Users/view.ctp:36 +#: Template/Users/view.ctp:39 msgid "Last Name" msgstr "" -#: Template/Users/view.ctp:40 +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "" + +#: Template/Users/view.ctp:45 msgid "Api Token" msgstr "" -#: Template/Users/view.ctp:48;74 +#: Template/Users/view.ctp:53 msgid "Token Expires" msgstr "" -#: Template/Users/view.ctp:50 +#: Template/Users/view.ctp:55 msgid "Activation Date" msgstr "" -#: Template/Users/view.ctp:52 +#: Template/Users/view.ctp:57 msgid "Tos Date" msgstr "" -#: Template/Users/view.ctp:54;77 +#: Template/Users/view.ctp:59;75 msgid "Created" msgstr "" -#: Template/Users/view.ctp:56;78 +#: Template/Users/view.ctp:61;76 msgid "Modified" msgstr "" -#: Template/Users/view.ctp:63 -msgid "Related Accounts" -msgstr "" - -#: Template/Users/view.ctp:68 -msgid "User Id" -msgstr "" - -#: Template/Users/view.ctp:71 -msgid "Reference" -msgstr "" - -#: Template/Users/view.ctp:76 -msgid "Data" -msgstr "" - -#: View/Helper/UserHelper.php:46 +#: View/Helper/UserHelper.php:45 msgid "Sign in with" msgstr "" -#: View/Helper/UserHelper.php:49 +#: View/Helper/UserHelper.php:48 msgid "fa fa-{0}" msgstr "" -#: View/Helper/UserHelper.php:52 +#: View/Helper/UserHelper.php:57 msgid "btn btn-social btn-{0} " msgstr "" -#: View/Helper/UserHelper.php:91 +#: View/Helper/UserHelper.php:106 msgid "Logout" msgstr "" -#: View/Helper/UserHelper.php:108 +#: View/Helper/UserHelper.php:123 msgid "Welcome, {0}" msgstr "" -#: View/Helper/UserHelper.php:131 +#: View/Helper/UserHelper.php:146 msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" msgstr "" -#: Model/Behavior/RegisterBehavior.php:148 -msgid "This field is required" +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" msgstr "" From 23806a1989ff6aec78554e058ad87c3cffe0adbd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 14 Oct 2017 21:51:59 -0300 Subject: [PATCH 0726/1476] Updated pt_BR translation --- src/Locale/pt_BR/Users.mo | Bin 15158 -> 15088 bytes src/Locale/pt_BR/Users.po | 560 +++++++++++++++++++++----------------- 2 files changed, 306 insertions(+), 254 deletions(-) diff --git a/src/Locale/pt_BR/Users.mo b/src/Locale/pt_BR/Users.mo index 787c09266da5993ebcf6db06844c54eae8f144fe..5cbc087b8fb6ad1fc6defdce71a871a71909e486 100644 GIT binary patch delta 5485 zcmZ|Q4R93Y9mnzK00jaHBm@Nn)(}G=@0f%VK!{)!louhqh$t?1OLB0zjeB>&XyGi@ zBB)?p6{>=~SOhCnIkgnDgQnJLoza;x+B%N!ueH`%huW&6^!vNpsEo3c|9zf)?soV8 z{GaF9Jl_6ED*al1k2?*=A>u6Jqf?Ce5})Y92gja%#>~LI*c*@GAp9B!V_|<|hGP|0 z9`n`Kombe(@8=98_-@{_gKSLg2hUVuiNB+ztJ}P;>nL|UFrcpm!heL4->c)?vig6gvz-O@s zzK%-h9i(XHV;qRbP$TYLko)~eBnLAgaAwfI6!Un#Sw*7|*Qx`z1n$Bb&iA7dc>}xQ z`>2FJL>oUvjl7AcPs0f6fqQWz9>yws9W{V{Jggc=VOk?tL_;n^jVy*5@ztn=R-;CE z6DpC7ScG??rs`neQ`ndDKcf=(E1rgbM;jzZOp!D@xA5VHm{{T!*^B zew>9*;AHH>Fc#v)I39Q5XnYmV#GZUGSYzSYScmFg$cOIVhWylQJd^rsk?p2q6uyXK z@GDe?rA#DEQxiA?)gMMxD2BSxHE7{&sKxpSmf;ap=|2j-KZ`A(=S)KFHYZI(4_J#T z{XNK^+0KWibf(@Qfs9OHFb5!bepND z-(7|ldb#h@#-~wE#|~6R&!aNVV>l{R0cvCu_)zAH1J|IYU?;Kx%zo4Zo<>#X71UJx z11sd=Bb<;S%bvMYNR;jp!h9t$7-!;|F*uj%6We zuE(RM-~t?t^H6iW8nxPQMLlpE*5M)%IR|1nZb^9A?1rtV z%-XOOuR$g99xlbtP^*0bZz+{}1*&43PzgPT+C@jPH}>N#BnP7s7>P=_6gBX4J&imX z7h)friyGmTLH`=m1?z+J&8UQS1|C2S;AtF-&!H;zHI`!!K2-7=)LNQ{s+5O3H*IdA z5v5}@&c#rLF;`&|szi_Bx%dfcgvGptv`Ej#YFvs;r@0N4_(9Za{~Kxz9K$Lc!-rhV zhZ5d^!?pi?8WtS~P^CJGnu1qR4}2F@;_f`{G#rgT!f~j?+E7z*KQadMCsYETp|)#2 z?`KtH45|{KfXe~FqZRcS7vow1Jah&jY!LdS1%Q2*dK4{rCEbi&b+!|cah#IFc#xy?iY@euJC5g~MFamI+LI^o!m<2#=`pURsl#LS@k z#z4W=&%REzHu|cA;}W7R+sgf0W>=a`!TADA25moZ9BOKGXpLM+>?VFf?9upl63Yo~ zF&%dkdBjb`R-)^;oyIoeK+vHTJtJt}ioYP5h-t)+iJueQ2_4lrvWqiJTkjL?ko4@} zi_*YesMl#NaSCxg(RFC6Wr$yQb>P0B{UEL)t{~!s7H8LS4~==m*~FTlvjlnVr_G}@ z9AXG@HE}=DhZs$C9oi8W2PdcE7DC&v>*%17ASM&*iMxnyL_M*Vcz_s4tRxzU>xhHI zUcLXf)6j7rv6^Tm$_O3(i5cl#t2k}#45wV0AOk7Clm`+@f zZROq@*&FCQpSYHoPqY#`?#+>X(=DX!5*G0@;xeLw(D8^qCMMeKxD}4siNvI$=2%Bt zOEm1pt#4WtF}JxQ8ZWYJFKSn`L?aO=KB*{K;H8|R^Cnj5>hr7xju&0tk=fF3PiU;? zSRHQ4N~D6uDm$LElCI@B2}g~UPTX4VdR8jocvjJM)vJsANdvCB)Q!iTaMD^8O}1Ec znyI-CC-U8{R4ih}-K0gbZa8Wu9m@`f-BdhTZnec6JKjomjj3dd6Hi9Nc9O^E5?N&@$TS>w5{c!hSga$LrT;>Hd1gt$s*wNYz;T%a zg%#Z_dl`55!5b})dWmFZ=EXB+hWzruL;XdAONad651TY}zhm&f&M|Xc?iOybS znuIpT%T9pJd`22f)9iUxgnF7Ll3J+=q~%zdBSSZYe0$j2{+i(xerEW(0;(O%!7_@U zy*N`lq9IhT6`;~aSv*tSh-0#AqN^uNj}=W=(RjNZi$*G~rrbPbR#+w7Pp_%2sHwHa zp4(7cS5{r^ZyPzJPtaA8mMlL` zvS#T%an+Kc=f74wtgqv>x(SOk=O^6ESH=56=>=}M^Fb@=v|3@uOFGxu*3~J8UnHCr zHVY-sm=CmPEv_f=MFFGT0D`3%mXKz#&$btduC=TVtZD?iMQCMF_v_^ z@13ztv^2;f)#|@eGHQ{lUBS=7Zfn=JP)CFn+|@O!bC=5^idt=MBGI|8-C@Dx7Kmrr z{3@Qb%Na$S-4b`(?N+raZy!~d89J&eG(Jc^;+|x6b6?M4oGe6sqi3>T*eI*0Yzp~zRF(Nht4c?zlAe{_ zAJ$0{$^5UXXUPA&dSu=lyUmH^cF5eCg|m52ByB7EI*3^-I(Jx3BFSe^frw2B+*H#0 zc3w@5b~$ge(Jk*b$+I9N3XbQ-PZZ2|7J}= z=HmJrL$jxLW+KsMS5wv=?19b)_?0=?7gpz9ZG+Ao>;spLaN@*dUKqE%oBvQzU;o;M Ke1BuZp8o@vABoxk delta 5371 zcmZA233OD|9mnxI0YZQnAYn_`9&3yVAqj*fKq0c3qM!tDMR}QdAx|=kvxMCNmx_W| z9Tl;*il8h-DolgQkwe?KRc#No)}FdlrFA>4tsXtcLQiYIznPaD>^u3-=e|2{x%Yqn zck)Hzcw6$%h20-89M2KMh`;tQ=HGa@4<8&4^);p!?#4m57mM)(j=(pu3cvEs$M!R( zC+Blf*Db;lbZ{hYK`u3qWlfr=Y2?!J3(Uipu@X;X0e*`bKtX?F#^Vsw^|MhATHv_? z$8z3`++wz)2J(n^z7M-|-i|}@1m>EgF>le(WZ%QV_!;U#Ut#vexkyq>KOBIAP%|q> zT|XbW#jNxUd;MFnH~qVDAnxLXPF&vvvYrF;Zfc>}_ z+i^B_XL?uSJe-b?;1GNZ8Ke0pj>7JAs((BmdhTrGE3*<+TL~=1eM89qMKoTgLnHeJ z`O7S@Qdi7E>wFCA`qesnI0sv>0X2bRs2X`5XW$1o7Kbqk znkHFKgY24>sF}o3FWiAj)iLDHe8>myHvdJ9yqLG@z8cR4RPC%nEnPFR+$N5?{w}m| zulM~6Si$?v8#FYsZ&5RtK|yH5^H2|HL8b0yR53k?{Fx(s=(^u{eu-L=fg_D!W0+B> zjMbu+WY+TRE9D*Oj7#)a%14d6l4njS&D@LALV zPhvg3gxxTYv?x>gs5Ksd+ErC}hmReE8tD5JLQ*sTI}Q0Ql0{QU0Zhkg)J)c(9(X(I z`@2!w?J#nS`6cT9k3G*~56<&>tNII3&l`uTp&L*W*)X2`bFI0Jj$Ay1TEnBBCsAwv zYt&kPiMi;bQ`hC8UNitnmMOuWI1{xy<{_(RmZR=Vpq{e{b>EIs@~>3f=Uw3!6M!Q3Gg04S1vHou~}#!rpiQm9aD`Bd1U`mVBSa5*pLW zvlnhdJt*a!??H|9u;=rb$NB46gMUD!GOr@DpG^U3DQ2K*WhE+uo3J-Nh%WBIrP}{} zCS?EHU5|BqaSAo#bEsW0gkPa5tVLGAG^1v)6IIm z95s**ycj=5O`weR;Wx+B;1FDad}YG5O8C2$}f^ZH*wJ?}$LGc`M~k*NDGMlDt2RPuizjWu-W0r#U`d-r3>FW-(V2$z6PC?K+R2(O5`m zls_c&lG((A#3*7bq2qg5%)_V|E3L|mMf`w>5KD-w2pvbVbbT^@ZR@02)zy{#C!zIz z*6UmC`4sN++FGuM2-U++y}kh6Noc#SA?6S|5?Q|US<9JfM%mT-&8?s{(!r0JYQ@}3 z=*L3GBI1Ee%b3e>Ke5w0Ux87tt@^l~U^8X5o4O|u*AY(;8weeHiAM<)zTR(sM5qSt zAbvu09{1BYNF4P#RM8Dydk3b7MxvgWPuxc25cd%kgpSEX6LB|DOe`jJ=m+e2BH5FV zF$6zynSUfVW9LCJn`6YG&JH|$UOPtnTH+Z(KVY3lh{jSvzoMJG&e7OHq>1N~d+|X*vA8t(qL)ONs&6XRo;&xN3V{NS7 zY^`l^Y57|m{~BEuUK?_vu@*OCMVx3*_l83;t2rFC5-}%gZLHaBF6(+?sM%eeh}vr)_@fX$E_yE^1fZRq|pj60<$cW8N1cBV|u3(jKtSh zSdmu8jyV>ya6{bVaMDbX~)(noS$y38V@~ zRCaF&nB}Q22aHHvGa{J&V8mo!da*USTR~OLgqkT<^_04r>IqeoQa6t&=~FdnLRGa@ zHNCF3I=y#Hk*~D6a$4oo%Ie-`S$K^TA}3b;efEPb}L+Lv<5wx-vWz39uOR^oOn zRa@SWoJ)0v?97C17A+KaEKW(B(@HO8YKN^hC+aq{(9zB!>S%XjB-x5Y!;z@#1Z>)Y zFol}v*b{ZbnPRPvQZsE~U6w6P>a}Bk$6hj;eNU!l%l@xum&fc7Px7`v<~FJg0eSMZX%}%uAP>7{T9i3QFM4p%uOWbPv*%fwx`Mo=_EL~pJ-IuDZ z9zI2-+;K2l15sD+u%qNC5ziKJc4!gm+uvfhF`Z2MD^u51UzzGwGb*{nie>BCn_@^a ziG-P*cBdV1vu_R8k?^>!g)&R5Y%%jFFP{`&#~!L>gBzx@c~`UD7LHbAtJ}5`!OlAz z?~V#9)RCsfI%@T{M8FA#*%_*Hm*0h8*Mq$rY1Em$8gn!ANmtbD_Z82Nv8aAK7zrx@ z;ijm&+KzXmqi*VVlfIt0%%xxTo|#eH2`T|W^4D4U0o#1{8XnTtv4@Her(T#mrJy08 jHSS#d)Y-|8r%%;x@};*=eKaRkUN<~viIuvf?!f;5lt5cg diff --git a/src/Locale/pt_BR/Users.po b/src/Locale/pt_BR/Users.po index ccf0d9fa8..760b5c903 100644 --- a/src/Locale/pt_BR/Users.po +++ b/src/Locale/pt_BR/Users.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2017-02-26 16:21-0300\n" -"PO-Revision-Date: 2017-02-26 17:44-0300\n" +"POT-Creation-Date: 2017-10-14 23:45+0000\n" +"PO-Revision-Date: 2017-10-14 21:49-0300\n" "Last-Translator: Livio Ribeiro \n" "Language-Team: CakeDC \n" "Language: pt_BR\n" @@ -13,46 +13,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 1.8.7.1\n" +"X-Generator: Poedit 2.0.4\n" -#: Auth/ApiKeyAuthenticate.php:73 -msgid "Type {0} is not valid" -msgstr "Tipo {0} não é válido" - -#: Auth/ApiKeyAuthenticate.php:77 -msgid "Type {0} has no associated callable" -msgstr "Tipo {0} não tem chamada associada" - -#: Auth/ApiKeyAuthenticate.php:86 -msgid "SSL is required for ApiKey Authentication" -msgstr "SSL é requerido para autenticação por chave da API." - -#: Auth/SimpleRbacAuthorize.php:142 -msgid "" -"Missing configuration file: \"config/{0}.php\". Using default permissions" -msgstr "" -"Arquivo de configuração ausente: \"config/{0}.php\". Usando permissões padrão" - -#: Auth/SocialAuthenticate.php:432 +#: Auth/SocialAuthenticate.php:456 msgid "Provider cannot be empty" msgstr "O provedor não pode ser vazio" -#: Auth/Rules/AbstractRule.php:78 -msgid "" -"Table alias is empty, please define a table alias, we could not extract a " -"default table from the request" -msgstr "" -"O alias da tabela está vazio, por favor, defina um alias de tabela, nós não " -"pudemos extrair uma tabela padrão da requisição" - -#: Auth/Rules/Owner.php:67;70 -msgid "" -"Missing column {0} in table {1} while checking ownership permissions for " -"user {2}" -msgstr "" -"Coluna {0} ausente na tabela {1} ao verificar permissões de propriedade do " -"usuário {2}" - #: Controller/SocialAccountsController.php:52 msgid "Account validated successfully" msgstr "Conta validada com êxito" @@ -89,26 +55,34 @@ msgstr "Conta inválida" msgid "Email could not be resent" msgstr "O email não pode ser reenviado" -#: Controller/Component/RememberMeComponent.php:69 +#: Controller/Component/RememberMeComponent.php:68 msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" msgstr "" "Salt da aplicação inválido, o salt da aplicação deve ser de pelo menos 256 " "bits (32 bytes)" -#: Controller/Component/UsersAuthComponent.php:178 +#: Controller/Component/UsersAuthComponent.php:204 msgid "You can't enable email validation workflow if use_email is false" msgstr "" "Você não pode habilitar o fluxo de validação por email se use_email for false" -#: Controller/Traits/LoginTrait.php:96 +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "Não foi possível associar a conta, tente novamente." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "A conta social foi associada." + +#: Controller/Traits/LoginTrait.php:104 msgid "Issues trying to log in with your social account" msgstr "Problemas ao tentar autenticar a partir da sua conta social" -#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "Por favor indique seu email" -#: Controller/Traits/LoginTrait.php:108 +#: Controller/Traits/LoginTrait.php:120 msgid "" "Your user has not been validated yet. Please check your inbox for " "instructions" @@ -116,7 +90,7 @@ msgstr "" "Seu usuário ainda não foi validado. Por favor, verifique sua caixa de " "entrada para instruções" -#: Controller/Traits/LoginTrait.php:110 +#: Controller/Traits/LoginTrait.php:125 msgid "" "Your social account has not been validated yet. Please check your inbox for " "instructions" @@ -124,342 +98,326 @@ msgstr "" "Sua conta social ainda não foi validada. Por favor, verifique sua caixa de " "entrada para instruções" -#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 msgid "Invalid reCaptcha" msgstr "ReCaptcha inválido" -#: Controller/Traits/LoginTrait.php:171 +#: Controller/Traits/LoginTrait.php:191 msgid "You are already logged in" msgstr "Você já está autenticado" -#: Controller/Traits/LoginTrait.php:217 +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "Por favor habilite o Google Authenticator primeiro." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Código de verificação é inválido. Tente novamente" + +#: Controller/Traits/LoginTrait.php:340 msgid "Username or password is incorrect" msgstr "Nome de usuário e/ou senha incorreto(s)" -#: Controller/Traits/LoginTrait.php:238 +#: Controller/Traits/LoginTrait.php:363 msgid "You've successfully logged out" msgstr "Você desconectou-se com êxito" -#: Controller/Traits/PasswordManagementTrait.php:47;76 -#: Controller/Traits/ProfileTrait.php:49 +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 msgid "User was not found" msgstr "O usuário não foi encontrado" -#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 msgid "Password could not be changed" msgstr "A senha não pode ser alterada" -#: Controller/Traits/PasswordManagementTrait.php:68 +#: Controller/Traits/PasswordManagementTrait.php:74 msgid "Password has been changed successfully" msgstr "Senha alterada com êxito" -#: Controller/Traits/PasswordManagementTrait.php:78 +#: Controller/Traits/PasswordManagementTrait.php:84 msgid "{0}" msgstr "{0}" -#: Controller/Traits/PasswordManagementTrait.php:120 +#: Controller/Traits/PasswordManagementTrait.php:127 msgid "Please check your email to continue with password reset process" msgstr "" "Por favor, verifique seu email para continuar o processo de redefinição de " "senha" -#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 msgid "The password token could not be generated. Please try again" msgstr "O token de senha não pode ser gerado. Por favor, tente novamente" -#: Controller/Traits/PasswordManagementTrait.php:129 -#: Controller/Traits/UserValidationTrait.php:100 +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 msgid "User {0} was not found" msgstr "O usuário {0} não foi encontrado" -#: Controller/Traits/PasswordManagementTrait.php:131 +#: Controller/Traits/PasswordManagementTrait.php:138 msgid "The user is not active" msgstr "O usuário não está ativo" -#: Controller/Traits/PasswordManagementTrait.php:133 -#: Controller/Traits/UserValidationTrait.php:95;104 +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 msgid "Token could not be reset" msgstr "O token não pode ser redefinido" -#: Controller/Traits/ProfileTrait.php:53 +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "O token do Google Authenticator foi reiniciado com sucesso" + +#: Controller/Traits/ProfileTrait.php:54 msgid "Not authorized, please login first" msgstr "Não autorizado, por favor, autentique-se primeiro" -#: Controller/Traits/RegisterTrait.php:42 +#: Controller/Traits/RegisterTrait.php:43 msgid "You must log out to register a new user account" msgstr "Você deve deslogar para registrar uma nova conta de usuário" -#: Controller/Traits/RegisterTrait.php:88 +#: Controller/Traits/RegisterTrait.php:89 msgid "The user could not be saved" msgstr "O usuário não pode ser salvo" -#: Controller/Traits/RegisterTrait.php:122 +#: Controller/Traits/RegisterTrait.php:123 msgid "You have registered successfully, please log in" msgstr "Você registrou-se com sucesso, por favor, autentique-se" -#: Controller/Traits/RegisterTrait.php:124 +#: Controller/Traits/RegisterTrait.php:125 msgid "Please validate your account before log in" msgstr "Por favor, valide sua conta antes de autenticar" -#: Controller/Traits/SimpleCrudTrait.php:76;106 +#: Controller/Traits/SimpleCrudTrait.php:77;107 msgid "The {0} has been saved" msgstr "O {0} foi salvo" -#: Controller/Traits/SimpleCrudTrait.php:80;110 +#: Controller/Traits/SimpleCrudTrait.php:81;111 msgid "The {0} could not be saved" msgstr "O {0} não pode ser salvo" -#: Controller/Traits/SimpleCrudTrait.php:130 +#: Controller/Traits/SimpleCrudTrait.php:131 msgid "The {0} has been deleted" msgstr "O {0} foi deletado" -#: Controller/Traits/SimpleCrudTrait.php:132 +#: Controller/Traits/SimpleCrudTrait.php:133 msgid "The {0} could not be deleted" msgstr "O {0} não pode ser deletado" -#: Controller/Traits/SocialTrait.php:39 +#: Controller/Traits/SocialTrait.php:40 msgid "The reCaptcha could not be validated" msgstr "O reCaptcha não pode ser validado" -#: Controller/Traits/UserValidationTrait.php:42 +#: Controller/Traits/UserValidationTrait.php:43 msgid "User account validated successfully" msgstr "Conta de usuário validada com êxito" -#: Controller/Traits/UserValidationTrait.php:44 +#: Controller/Traits/UserValidationTrait.php:45 msgid "User account could not be validated" msgstr "A conta de usuário não pode ser validada" -#: Controller/Traits/UserValidationTrait.php:47 +#: Controller/Traits/UserValidationTrait.php:48 msgid "User already active" msgstr "Usuário já ativo" -#: Controller/Traits/UserValidationTrait.php:53 +#: Controller/Traits/UserValidationTrait.php:54 msgid "Reset password token was validated successfully" msgstr "Token de redefinição de senha validado com êxito" -#: Controller/Traits/UserValidationTrait.php:58 +#: Controller/Traits/UserValidationTrait.php:62 msgid "Reset password token could not be validated" msgstr "O token de redefinição de senha não pode ser validado" -#: Controller/Traits/UserValidationTrait.php:62 +#: Controller/Traits/UserValidationTrait.php:66 msgid "Invalid validation type" msgstr "Tipo de validação inválido" -#: Controller/Traits/UserValidationTrait.php:65 +#: Controller/Traits/UserValidationTrait.php:69 msgid "Invalid token or user account already validated" msgstr "Token inválido ou conta já validada" -#: Controller/Traits/UserValidationTrait.php:67 +#: Controller/Traits/UserValidationTrait.php:71 msgid "Token already expired" msgstr "Token expirado" -#: Controller/Traits/UserValidationTrait.php:93 +#: Controller/Traits/UserValidationTrait.php:97 msgid "Token has been reset successfully. Please check your email." msgstr "O token foi redefinido com êxito. Por favor, verifique seu email." -#: Controller/Traits/UserValidationTrait.php:102 +#: Controller/Traits/UserValidationTrait.php:109 msgid "User {0} is already active" msgstr "O usuário {0} já está ativo" -#: Email/EmailSender.php:39 +#: Mailer/UsersMailer.php:34 msgid "Your account validation link" msgstr "Seu link de validação da conta" -#: Mailer/UsersMailer.php:55 +#: Mailer/UsersMailer.php:52 msgid "{0}Your reset password link" msgstr "{0}Seu link de redefinição de senha" -#: Mailer/UsersMailer.php:78 +#: Mailer/UsersMailer.php:75 msgid "{0}Your social account validation link" msgstr "{0}Seu link de validação da conta social" -#: Model/Behavior/PasswordBehavior.php:56 +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "'username' ausente nas opções" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Conta social já está associada a outro usuário" + +#: Model/Behavior/PasswordBehavior.php:45 msgid "Reference cannot be null" msgstr "A referência não pode ser nula" -#: Model/Behavior/PasswordBehavior.php:61 +#: Model/Behavior/PasswordBehavior.php:50 msgid "Token expiration cannot be empty" msgstr "A expiração do token não pode ser vazia" -#: Model/Behavior/PasswordBehavior.php:67;116 +#: Model/Behavior/PasswordBehavior.php:56;117 msgid "User not found" msgstr "Usuário não encontrado" -#: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:111 +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 msgid "User account already validated" msgstr "Conta de usuário já validada" -#: Model/Behavior/PasswordBehavior.php:78 +#: Model/Behavior/PasswordBehavior.php:67 msgid "User not active" msgstr "Usuário inativo" -#: Model/Behavior/PasswordBehavior.php:121 +#: Model/Behavior/PasswordBehavior.php:122 msgid "The current password does not match" msgstr "A senha atual não corresponde" -#: Model/Behavior/PasswordBehavior.php:124 +#: Model/Behavior/PasswordBehavior.php:125 msgid "You cannot use the current password as the new one" msgstr "Você não pode usar a senha atual como nova senha" -#: Model/Behavior/RegisterBehavior.php:89 +#: Model/Behavior/RegisterBehavior.php:90 msgid "User not found for the given token and email." msgstr "Usuário não encontrado com a combinação de token e email" -#: Model/Behavior/RegisterBehavior.php:92 +#: Model/Behavior/RegisterBehavior.php:93 msgid "Token has already expired user with no token" msgstr "Token expirado, usuário sem token" -#: Model/Behavior/SocialAccountBehavior.php:102;129 +#: Model/Behavior/SocialAccountBehavior.php:103;130 msgid "Account already validated" msgstr "Conta já validada" -#: Model/Behavior/SocialAccountBehavior.php:105;132 +#: Model/Behavior/SocialAccountBehavior.php:106;133 msgid "Account not found for the given token and email." msgstr "Conta não encontrada com a combinação de token e email" -#: Model/Behavior/SocialBehavior.php:56 +#: Model/Behavior/SocialBehavior.php:82 msgid "Unable to login user with reference {0}" msgstr "Incapaz de autenticar usuário com a referência {0}" -#: Model/Behavior/SocialBehavior.php:98 +#: Model/Behavior/SocialBehavior.php:121 msgid "Email not present" msgstr "Email ausente" -#: Model/Table/UsersTable.php:82 +#: Model/Table/UsersTable.php:81 msgid "Your password does not match your confirm password. Please try again" msgstr "" "Sua senha não corresponde com a confirmação. Por favor, tente novamente" -#: Model/Table/UsersTable.php:175 +#: Model/Table/UsersTable.php:173 msgid "Username already exists" msgstr "Nome de usuário em uso" -#: Model/Table/UsersTable.php:181 +#: Model/Table/UsersTable.php:179 msgid "Email already exists" msgstr "Email em uso" -#: Model/Table/UsersTable.php:214 -msgid "Missing 'username' in options data" -msgstr "'username' ausente nas opções" - -#: Shell/UsersShell.php:54 +#: Shell/UsersShell.php:58 msgid "Utilities for CakeDC Users Plugin" msgstr "Utilitários para CakeDC Users Plugin" -#: Shell/UsersShell.php:55 +#: Shell/UsersShell.php:60 msgid "Activate an specific user" msgstr "Ativar um usuário específico" -#: Shell/UsersShell.php:56 +#: Shell/UsersShell.php:63 msgid "Add a new superadmin user for testing purposes" msgstr "Adicionar um novo usuário superadmin para fins de testes" -#: Shell/UsersShell.php:57 +#: Shell/UsersShell.php:66 msgid "Add a new user" msgstr "Adicionar um novo usuário" -#: Shell/UsersShell.php:58 +#: Shell/UsersShell.php:69 msgid "Change the role for an specific user" msgstr "Alterar o role de um usuário específico" -#: Shell/UsersShell.php:59 +#: Shell/UsersShell.php:72 msgid "Deactivate an specific user" msgstr "Desativar um usuário específico" -#: Shell/UsersShell.php:60 +#: Shell/UsersShell.php:75 msgid "Delete an specific user" msgstr "Deletar um usuário específico" -#: Shell/UsersShell.php:61 +#: Shell/UsersShell.php:78 msgid "Reset the password via email" msgstr "Redefinir a senha via email" -#: Shell/UsersShell.php:62 +#: Shell/UsersShell.php:81 msgid "Reset the password for all users" msgstr "Redefinir a senha de todos usuários" -#: Shell/UsersShell.php:63 +#: Shell/UsersShell.php:84 msgid "Reset the password for an specific user" msgstr "Redefinir a senha de um usuário específico" -#: Shell/UsersShell.php:98 -msgid "User added:" -msgstr "Usuário adicionado:" - -#: Shell/UsersShell.php:99;127 -msgid "Id: {0}" -msgstr "Id: {0}" - -#: Shell/UsersShell.php:100;128 -msgid "Username: {0}" -msgstr "Nome de usuário: {0}" - -#: Shell/UsersShell.php:101;129 -msgid "Email: {0}" -msgstr "Email: {0}" - -#: Shell/UsersShell.php:102;130 -msgid "Password: {0}" -msgstr "Senha: {0}" - -#: Shell/UsersShell.php:126 -msgid "Superuser added:" -msgstr "Superusuário adicionado:" - -#: Shell/UsersShell.php:132 -msgid "Superuser could not be added:" -msgstr "O superusuário não pode ser adicionado:" - -#: Shell/UsersShell.php:135 -msgid "Field: {0} Error: {1}" -msgstr "Campo: {0} Erro: {1}" - -#: Shell/UsersShell.php:153;179 +#: Shell/UsersShell.php:133;159 msgid "Please enter a password." msgstr "Por favor, indique uma senha." -#: Shell/UsersShell.php:157 +#: Shell/UsersShell.php:137 msgid "Password changed for all users" msgstr "As senhas de todos usuários foram alteradas" -#: Shell/UsersShell.php:158;186 +#: Shell/UsersShell.php:138;166 msgid "New password: {0}" msgstr "Nova senha: {0}" -#: Shell/UsersShell.php:176;204;282;324 +#: Shell/UsersShell.php:156;184;262;359 msgid "Please enter a username." msgstr "Por favor, indique um nome de usuário." -#: Shell/UsersShell.php:185 +#: Shell/UsersShell.php:165 msgid "Password changed for user: {0}" msgstr "Senha alterada para usuário: {0}" -#: Shell/UsersShell.php:207 +#: Shell/UsersShell.php:187 msgid "Please enter a role." msgstr "Por favor, indique um papel." -#: Shell/UsersShell.php:213 +#: Shell/UsersShell.php:193 msgid "Role changed for user: {0}" msgstr "Papel alterado para usuário: {0}" -#: Shell/UsersShell.php:214 +#: Shell/UsersShell.php:194 msgid "New role: {0}" msgstr "Novo papel: {0}" -#: Shell/UsersShell.php:229 +#: Shell/UsersShell.php:209 msgid "User was activated: {0}" msgstr "Usuário ativado: {0}" -#: Shell/UsersShell.php:244 +#: Shell/UsersShell.php:224 msgid "User was de-activated: {0}" msgstr "Usuário desativado: {0}" -#: Shell/UsersShell.php:256 +#: Shell/UsersShell.php:236 msgid "Please enter a username or email." msgstr "Por favor, indique um nome de usuário ou senha." -#: Shell/UsersShell.php:264 +#: Shell/UsersShell.php:244 msgid "" "Please ask the user to check the email to continue with password reset " "process" @@ -467,15 +425,51 @@ msgstr "" "Por favor, peça ao usuário para verificar seu email para continuar o " "processo de redefinição de senha" -#: Shell/UsersShell.php:302 +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "Superusuário adicionado:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "Usuário adicionado:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Nome de usuário: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "Email: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Papel: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Senha: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "Usuário não pôde ser adicionado:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Campo: {0} Erro: {1}" + +#: Shell/UsersShell.php:337 msgid "The user was not found." msgstr "O usuário não foi encontrado." -#: Shell/UsersShell.php:332 +#: Shell/UsersShell.php:367 msgid "The user {0} was not deleted. Please try again" msgstr "O usuário {0} não foi deletado. Por favor, tente novamente" -#: Shell/UsersShell.php:334 +#: Shell/UsersShell.php:369 msgid "The user {0} was deleted successfully" msgstr "O usuário {0} foi deletado com êxito" @@ -494,19 +488,20 @@ msgstr "Redefina sua senha aqui" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 msgid "" -"If the link is not correcly displayed, please copy the following address in " +"If the link is not correctly displayed, please copy the following address in " "your web browser {0}" msgstr "" "Se o link não estiver sendo exibido corretamente, por favor, copie o " "seguinte endereço em seu navegador {0}" -#: Template/Email/html/reset_password.ctp:30 -#: Template/Email/html/social_account_validation.ctp:35 -#: Template/Email/html/validation.ctp:30 -#: Template/Email/text/reset_password.ctp:24 -#: Template/Email/text/social_account_validation.ctp:26 -#: Template/Email/text/validation.ctp:24 +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 msgid "Thank you" msgstr "Obrigado" @@ -518,14 +513,6 @@ msgstr "Ative sua autenticação social aqui" msgid "Activate your account here" msgstr "Ative sua conta aqui" -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correctly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Se o link não estiver sendo exibido corretamente, por favor, copie o " -"seguinte endereço em seu navegador {0}" - #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" @@ -539,54 +526,53 @@ msgstr "" "Por favor, copie o endereço a seguir em seu navegador para ativar sua " "autenticação social {0}" -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 msgid "Actions" msgstr "Ações" -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 -#: Template/Users/view.ctp:19 +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 msgid "List Users" msgstr "Listar usuários" -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:21 -msgid "List Accounts" -msgstr "Listar contas" - -#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 msgid "Add User" msgstr "Adicionar usuário" -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 -#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 msgid "Username" msgstr "Nome de usuário" -#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 msgid "Email" msgstr "Email" +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "Senha" + #: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 msgid "First name" msgstr "Nome" #: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 msgid "Last name" msgstr "Sobrenome" #: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:44;75 +#: Template/Users/view.ctp:49;74 msgid "Active" msgstr "Ativo" #: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 +#: 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 @@ -605,17 +591,16 @@ msgstr "Senha atual" msgid "New password" msgstr "Nova senha" -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 msgid "Confirm password" msgstr "Confirmar senha" -#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:101 +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 msgid "Delete" msgstr "Deletar" -#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:18;101 +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 msgid "Are you sure you want to delete # {0}?" msgstr "Tem certeza que deseja deletar # {0}?" @@ -623,7 +608,7 @@ msgstr "Tem certeza que deseja deletar # {0}?" msgid "Edit User" msgstr "Editar usuário" -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 msgid "Token" msgstr "Token" @@ -643,11 +628,19 @@ msgstr "Data de ativação" msgid "TOS date" msgstr "Data TOS" +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Redefir Token do Google Authenticator" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "Você tem certeza que deseja redefinir o token para o usuário “{0}”?" + #: Template/Users/index.ctp:15 msgid "New {0}" msgstr "Novo {0}" -#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +#: Template/Users/index.ctp:37 msgid "View" msgstr "Visualizar" @@ -655,7 +648,7 @@ msgstr "Visualizar" msgid "Change password" msgstr "Alterar senha" -#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +#: Template/Users/index.ctp:39 msgid "Edit" msgstr "Editar" @@ -687,39 +680,35 @@ msgstr "Resetar Senha" msgid "Login" msgstr "Autenticar" -#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 msgid "{0} {1}" msgstr "{0} {1}" -#: Template/Users/profile.ctp:24 +#: Template/Users/profile.ctp:27 msgid "Change Password" msgstr "Mudar senha" -#: Template/Users/profile.ctp:34 +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 msgid "Social Accounts" msgstr "Contas sociais" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 msgid "Avatar" msgstr "Avatar" -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 msgid "Provider" msgstr "Provedor" -#: Template/Users/profile.ctp:40 +#: Template/Users/profile.ctp:44 msgid "Link" msgstr "Link" -#: Template/Users/profile.ctp:47 +#: Template/Users/profile.ctp:51 msgid "Link to {0}" msgstr "Link para {0}" -#: Template/Users/register.ctp:20 -msgid "Password" -msgstr "Senha" - -#: Template/Users/register.ctp:28 +#: Template/Users/register.ctp:29 msgid "Accept TOS conditions?" msgstr "Concordar com Termos de Uso?" @@ -735,94 +724,157 @@ msgstr "Reenviar email de validação" msgid "Email or username" msgstr "Email ou nome de usuário" -#: Template/Users/view.ctp:18 +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Código de verificação" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" Verificar" + +#: Template/Users/view.ctp:19 msgid "Delete User" msgstr "Deletar usuário" -#: Template/Users/view.ctp:20 +#: Template/Users/view.ctp:24 msgid "New User" msgstr "Novo usuário" -#: Template/Users/view.ctp:28;67 +#: Template/Users/view.ctp:31 msgid "Id" msgstr "Id" -#: Template/Users/view.ctp:34 +#: Template/Users/view.ctp:37 msgid "First Name" msgstr "Nome" -#: Template/Users/view.ctp:36 +#: Template/Users/view.ctp:39 msgid "Last Name" msgstr "Sobrenome" -#: Template/Users/view.ctp:40 +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Papel" + +#: Template/Users/view.ctp:45 msgid "Api Token" msgstr "Api Token" -#: Template/Users/view.ctp:48;74 +#: Template/Users/view.ctp:53 msgid "Token Expires" msgstr "Expiração do token" -#: Template/Users/view.ctp:50 +#: Template/Users/view.ctp:55 msgid "Activation Date" msgstr "Data de ativação" -#: Template/Users/view.ctp:52 +#: Template/Users/view.ctp:57 msgid "Tos Date" msgstr "Data TOS" -#: Template/Users/view.ctp:54;77 +#: Template/Users/view.ctp:59;75 msgid "Created" msgstr "Criado" -#: Template/Users/view.ctp:56;78 +#: Template/Users/view.ctp:61;76 msgid "Modified" msgstr "Modificado" -#: Template/Users/view.ctp:63 -msgid "Related Accounts" -msgstr "Contas relacionadas" - -#: Template/Users/view.ctp:68 -msgid "User Id" -msgstr "Id de usuário" - -#: Template/Users/view.ctp:71 -msgid "Reference" -msgstr "Referência" - -#: Template/Users/view.ctp:76 -msgid "Data" -msgstr "Dados" - -#: View/Helper/UserHelper.php:46 +#: View/Helper/UserHelper.php:45 msgid "Sign in with" msgstr "Logar com" -#: View/Helper/UserHelper.php:49 +#: View/Helper/UserHelper.php:48 msgid "fa fa-{0}" msgstr "fa fa-{0}" -#: View/Helper/UserHelper.php:52 +#: View/Helper/UserHelper.php:57 msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0} " -#: View/Helper/UserHelper.php:91 +#: View/Helper/UserHelper.php:106 msgid "Logout" msgstr "Desconectar" -#: View/Helper/UserHelper.php:108 +#: View/Helper/UserHelper.php:123 msgid "Welcome, {0}" msgstr "Bem-vindo(a), {0}" -#: View/Helper/UserHelper.php:131 +#: View/Helper/UserHelper.php:146 msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" msgstr "" -"O reCaptcha não está configurado! Por favor, configure Users.reCaptcha.key" +"reCaptcha não está configurado! Por favor, configure Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:205 +#, fuzzy +#| msgid "btn btn-social btn-{0} " +msgid "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0}" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Conectador com {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Conectar com {0}" + +#~ msgid "Type {0} is not valid" +#~ msgstr "Tipo {0} não é válido" + +#~ msgid "Type {0} has no associated callable" +#~ msgstr "Tipo {0} não tem chamada associada" + +#~ msgid "SSL is required for ApiKey Authentication" +#~ msgstr "SSL é requerido para autenticação por chave da API." + +#~ msgid "" +#~ "Missing configuration file: \"config/{0}.php\". Using default permissions" +#~ msgstr "" +#~ "Arquivo de configuração ausente: \"config/{0}.php\". Usando permissões " +#~ "padrão" + +#~ msgid "" +#~ "Table alias is empty, please define a table alias, we could not extract a " +#~ "default table from the request" +#~ msgstr "" +#~ "O alias da tabela está vazio, por favor, defina um alias de tabela, nós " +#~ "não pudemos extrair uma tabela padrão da requisição" + +#~ msgid "" +#~ "Missing column {0} in table {1} while checking ownership permissions for " +#~ "user {2}" +#~ msgstr "" +#~ "Coluna {0} ausente na tabela {1} ao verificar permissões de propriedade " +#~ "do usuário {2}" + +#~ msgid "" +#~ "If the link is not correcly displayed, please copy the following address " +#~ "in your web browser {0}" +#~ msgstr "" +#~ "Se o link não estiver sendo exibido corretamente, por favor, copie o " +#~ "seguinte endereço em seu navegador {0}" + +#~ msgid "List Accounts" +#~ msgstr "Listar contas" + +#~ msgid "Related Accounts" +#~ msgstr "Contas relacionadas" + +#~ msgid "User Id" +#~ msgstr "Id de usuário" + +#~ msgid "Reference" +#~ msgstr "Referência" + +#~ msgid "Data" +#~ msgstr "Dados" -#: Model/Behavior/RegisterBehavior.php:148 -msgid "This field is required" -msgstr "Este campo é obrigatório" +#~ msgid "This field is required" +#~ msgstr "Este campo é obrigatório" #~ msgid "The old password does not match" #~ msgstr "A senha antiga não confere" From fb535a525e9beda1ffb81dfa649c9515e357b182 Mon Sep 17 00:00:00 2001 From: Livia Scapin Date: Fri, 20 Oct 2017 16:49:57 +0200 Subject: [PATCH 0727/1476] Add default value for plugin param --- src/Controller/Component/UsersAuthComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index cde49bf3a..9944abfe0 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -116,7 +116,7 @@ protected function _initAuth() } list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); - if ($this->getController()->request->getParam('plugin') === $plugin && + if ($this->getController()->request->getParam('plugin', null) === $plugin && $this->getController()->request->getParam('controller') === $controller ) { $this->getController()->Auth->allow([ From 7f380d499c6942123fea24b118e92f28d6188bf1 Mon Sep 17 00:00:00 2001 From: madbbb Date: Sun, 22 Oct 2017 11:30:08 +0300 Subject: [PATCH 0728/1476] Remove depreciated Form->input method --- src/Template/Users/login.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 742f44b2c..5e08f7cd6 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -17,8 +17,8 @@ use Cake\Core\Configure; Form->create() ?>
    - Form->input('username', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> - Form->input('password', ['label' => __d('CakeDC/Users', 'Password'), 'required' => true]) ?> + Form->control('username', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> + Form->control('password', ['label' => __d('CakeDC/Users', 'Password'), 'required' => true]) ?> User->addReCaptcha(); From 05697eaf0f8e77fb5c745f8705d053df8425f3c0 Mon Sep 17 00:00:00 2001 From: rrd108 Date: Mon, 23 Oct 2017 17:18:14 +0200 Subject: [PATCH 0729/1476] hungarian translation --- src/Locale/hu_HU/Users.mo | Bin 0 -> 14725 bytes src/Locale/hu_HU/Users.po | 816 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 816 insertions(+) create mode 100644 src/Locale/hu_HU/Users.mo create mode 100644 src/Locale/hu_HU/Users.po diff --git a/src/Locale/hu_HU/Users.mo b/src/Locale/hu_HU/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..ce8e248ce1e47f5ee7993b5aeebfaad260a498ea GIT binary patch literal 14725 zcmb`N3y>T~dB?|K8!Q`agq;{-%t$si#=6tP;Kxa_b(T&q>xFbOhCuAO-MPKFot;_l z%$13myl51^fp1 zH1G%D<=~Sp^t=t=I#Ay)0iOWA3{<=Oz^8-n0iOvz3i8kUdxwvK=kom%@QI*zk>`yA z=Yb62-3VRm3 z7d#()E%>Y8Tfnoy4}s@_9|bQ4{}j}^z6h$__dx!6k7F?5#h}Ws0xtn?1|`aAhj)S- z`JM+g?t@?eJ_KrA=RDQ(c7T_F;`bu(3NQxOgAah>|0!?-_%%@TJCDf;p9*Rn&j2;< zH6SYWo(pQc32-eq2}<5|hb`~|z867_`)cq>;9Eh-?IBS89tPF#3!wDeZ@TiwvuN?Z4AlB3 z_>r9)2CoM11)l?+1U0{}fa3R$4u9mzFQicNxfGl-0$#mwP9h*V%+X2cB4uG4%4k)|-Fep3z8xT=>{|;(h=TfNgE(ay29iZl&fi&?R05$)I zLG}9!Q2P2hh-$pYT>Vc$pYKcQtoob4b>J>=Gnj*#=O2TT&!eE$^G#6m)#8O$f|C1g z5R>($L5)8LN*?!ulK*jV416!Bb$kKTeE${1MZB|MuJ4OM&3iql@ppo1e-M=2G(gSw ze)s)$P1mS1gUM{Gr>*ZU7+mX%?^7YO}!t0EYVx-TYp^- z-obYc9soZNivMLyM)O+(PJ+(?5vdo0@{`ws*;$_V5m5cEKv>TPJ0MH;-UU+SJqkV- z{5q)dFGBh9@AaV8GXY9(GobwR9#C?Am&1>MvacQ}IeZq>y1wDQFThwN&&$F6;PXKF z;j10K1JpRDK*{-ULCNdiK+W?BEM^<{EKqu$1vO3w^uhZ;$>IH=`hOUd9R3oNeSgb+ ze;?F3p2%QY_vIj>_O^ktle<8T*9Im3H-ehy!=T3fl*7+~*Yo`~P~%>RP!EHbf|5%U zY=Ex>HJ|T*lE+U$>3uyxN#o3blKZPb+0(}y_CT%gOQ7ub+u(WNe}LzL{|!nHk0&T; zURQx?zsY^?0OjY0K&>kPp8(zsG6iqReZLQcmG?nVe)knne9yYp%H>K>_PYaI0G|(T z2R{Q&gXhyp{qEvN>w5zzdHoqEIe*!ee;1UTFU9#Jj~hYN9|9%ESx|C$Hz;|05xf9A zXWZK3YEb&v2tEls06rOfG3bL$kRiO+gYx@F!5hIZgW`WalM~-tLG5eDKH zlw7|JVshU1!1KY2XnY}f8R&!SK*?`EsC6!ayTRAF`mcaz^Zi3m>-#TI<6N}S^4|nX z4mW{Y!56ykw}X=V$3exPe{khL1T~*a5YA2DW>E8809S)=1U0`Cpyc&Y@X6qxgPPyx zL5=q<&<7uPovptDl)N^9RC#xT8vjioOZPtJ>i-2KBzUV4p5nswp#176_*C$25SQ{^ z18UwM0yW-ez%Af+K5dqLCNP&K-uY+Kup@Z~d+*|9AG8Cy19~I$8tAv6*FjqMhoHTXo)<R#%tD&6`CTpID_+5mK+D~r={3A&6 zE}nT_PC`pXfy3V!_^!M6>l~g7$_DhvhxBxzhoM(PFM;&D8G934^_6RR-{!s}hYx_bT;-YI>z;v< zdwG|w$B=w;3$!27^8x5(=FQssE8P3l;C=4>7^oO5yVui#-VTM(s~|o1Lwlgxp-s@O z&{fcDp~pdILr;TV3B3iHggTI(UC?`=gU}&}5MW{sP(E+q?f2Z*7bRo(8Ant@geaT-8;;0_v zVZE%OKCb&on)@^1GS#Y>g+-m;j-Stkej{286F*Oz{05YVtssiWOMc}Dezw4zvTSxC zjx|3sBZG@ffUbVl4r|eDRPz_Iu+y(uN*6kQ;3hs7cEX{mEUiUB>?4~f@dxW!vcCh~ zMSFc~vGyCN*ZrerC|&|T36C+ycGwB(EjVcsc9CJ0M@hqPFLc^z7G|cOZEh#p34P{B zU-xn>K*D+I*TXnuWmotw-SBcmzf!YKn1yOD0ZOQ5;I;HwdyBVyE=U@oe+Y{>mUimJ zcYEktdg!EaX!?&xa(kN0MxB=5@0BJ=Sj+umQ9h^1d9+YLSRX7Z?0~T(Vd=;!VV&QO z!ypU&ytCv7jUYUrxUXLa;zO;fU1{Q@eU&(&w^EjdmmZD6ejHH$2Oai zk(E{)-V-bH_%ogKn5 z-;)>*Ep*%eZnym`i1T%R;NJY!0!t$*1i3H$=l-VWUGL9CdFDU+x=sGfQXXd4;D$+~ zWYP(@2kpEz7nCJsoLG+poaZ{T8fsH`LgD$NA*-0W3o&x7far2m!A38ocMN_QTQb#h<^GpuZ~zkxu%5INbqDlqV;;_(<=&wp zCKN9|awmA$NFBtn2`pLJu2QW9*b)1^2R8!8s^57Ivz-ZvSj8Zf=w2{!EN!$1G6YJX zGVu+`*5<;REiqe$gw0k(s9gxHs@iTv)+KP!RQrc_$g;EDjXM8t{eLlEVRmI88?+&- z0_muj*DuC*pl6r_Gen7HgN4!YcrgY+1osU}I~u8w1&tIIR_fzgMr13t7^;xgv^y3G zsZOJ>f|bgpS`*f62>Kap$|)+77;aaj5|&F57iK~>&CvO{cc_ytMs?h*c=2mN; zQ1;{3Q#K-*Un^i6G;K=ZEn@?XFd_XUj~e$~G$~Uo)3@ADS27(Vq^6b5{|nbD*t!AW+y4VtbkfC3j7rus2&%x0*0n zN0M4McD&2kngJ^kErm9`zoC&dv*($kcB8ns?`;Z ztk9+`uFTl+v5sMfbf-&aVWzCY-+7U#kiiT#EKShzEkEs94EtW;z-gEn|8?gLo19xN z)_%v#IPxzWkIF9PAhxwE4JRqoIXF92RUF0iFd3t`>80%FjwNL|F}ZYp*hh&=w#HLx!2sAWD(&jAZ3_qHct>0-I zF!F2=XJNrW!ll;aej@=AugTG=vWqmaUFL{ZqziU4W-5c3WqHzJn#CN=u|(gbi`0yv<4*TzJ&i6gyQ}WNmf4>@(gBmpuH&%+LnBQi?{fMct5C1`N$KBcq$=;5)Xb zK86Ei=w-q`bok)jsqNGL?Nf)3>^XQ~)uDsaW9BM?+A-bzO!%8NY`kG?{IKE-kcFr>7>0{FzNhkaqd9LTQ9wnQVCUw|nwjQ0{ zId)^eT_;E~Qq!?1;zFHc<%EADhwD}Nd?$#RckVvA>X&jOITgoYa^^TES8pnwO&dWy)pgr!7-Om3q<13joz_?0JDGDK z)C_Yj%lz4>ce?4fdM7xmlnij)#ULqavBM;6`T0UU4_X7Ql893@e5P#KlK9O_tb_s|yL5 z+;(YAC$hksbRTBDnnFs_SSfAx9_jWT$+F(bMr4PtG=Ym>@14jOT770iWxZ32Uhkdr z)oGZLfy>OfwA<~S2w;`5{4nbxX%-*(wcg1%4&r4v+!}RrR+sl4>BPN9>custD_#sF zf{<&&b^ct+JHC{413zd69n^~e;@+to!_p>GotqW^Jlej++Z)DN7yYz)r|W4(4<_jC zom!?)BCkj~^0O{#YFGLOeU4!x?3_7nc%Ec4x-DqevJ_L3418k=X1n#h-rJaY*evT8 zIq`J6VQhC}S&}h`-X~+W7wl0iwJ=QBsFW+RcBglGhBenYGB%jd$%Y>`mNdU{ZyyWo zgeYLqOfF1fwl;s>F5FmBWmzQ86%(2^@;{k*J1hQT)uM%s2*#;Qbw`*%Q`#QtJt%Gr zt81OWdK(^!L13k>)H+!l&T)S2ePX^7G?4^$;%X3IC>1x>M7LJ^vs@12gh5N$R|%m_``Q(YILVV4vZS31=~Mu9)m zdn9S#T}-)7tyuQ%?=1FCCR~xi%-YRRSr9jaIB4Oe+z0ngkNe2ql(mAQED4%iyfzfp zW@d`Z*YfW58vGDL?tMbdn#4@nCP@?yjZ<#RL*-UF%zC|1&}dxpc89T>zin&UIVZ5D zGZLu#U5cu%LT=tW)h4Uh#UG{=&k@<^a7aTL7{)WBP}Qbi7V>wc?OaOtPShjcsJ;5t z_whxU2y(ADP1C!zVCCHwi7D6Yg^3Q_;RapqaBK4I88(~!MQFlAmXEWAFRRwQ+tF2E zgH-=pv)Zo!p{>iE@OW~hK@ReCcsoLnZ} z_8W!`ZB2RF&4b)DHdVdT{f!h4F4+;};OCm)IAPQ7ie&>>?6q;suJ5+qNzw{A3T81l zS3;!OB+wa=)wXcqWj>6GTK;IU#KZ`##FBYAVKH{aRq+tEO42w&h&SE!_XMt|C*_6Vk%~{A{8Lr(WO21uoSYa zVA)ufldRO|jU3r$3NaD02MVp>afYarR@9P&i-^hivDla>{d3!kUny=jgu&6va>FV_ z36<8S)P%{Zdgh2MozO*MG$D(UBFP+ZiTz$C>cxzRpr)|zv z=Cg{zoPw3-njPuqc3deXCN60|3wtLAa(Ux*0g*;K(dg_)6PBOTVXsRPt7}pgr-Xte zw1`3@gP8;ADPL9gK~hq2XX7@@&9lf_7lUy!DgGYbzt5(R zIT)~ERyRwrE>2|S5rnyCUAHMz6ItUc{6C3SD~t!M$z}?;f=z*$bTD9cTyInoXX6v} zE^`#aby$EL(<*z*fSb1ThcUBjRhpOOOV%fX1Z!XS=+RS|9iimFQ6OXd}~#RUD8Htg}L1+vL6V}b`*3h6=GDuTEUV!HQI z<}C>hglJMlW>L|%J7ine?OWEe7YqGk9}VpdhP5rFh64wQK{mtVk@xf+jJcSuMn}ur zqcSmbqd_88bWNg(5w_Ck@*Iq94O+C3n3Cq=E@aSq>`55W8BZO(6B#vhMl}~4B!8oo z{llwCFDs%Snb>Ies$fRzwd%p8?HpW+I}!{j9CKW>+Aa^a!xmwhxYJCLG0JG|)>s)s zP3;CTm38fo&_sCEOM2bWBgx99-(;ULM_hN8r9?nwq%i|0!{tN9{sm&c*L$$OC<9-k zWVM6!+r*6t+XDmfqVNs=6J9@u)J;Wkz%MLS`+v^8vvnPJZ*MQ{#luDbdJUv^Fi8{c zg95*!yDDzNydz~`G*|96_hGN$h^+K#UMHB_B6k*5zQrwjFo#vU(}1|UD-@IQtC!s; zaI-%1W>l_G$0WIeyojuOu1xe;Ph^hl^NN~AiAo9wlSJJzRqlk0J=#?*FZboPbVfDT zJBf+Yg*>C~B4@V)y%Q@PL~{PCO#RI9CfZg?T(!Vo21{&_T%LrJ3`0q-u(FYw`OXwc x_F}NcpDM3al_ek5ADF6__UNylTjs{w`^UjbRA*l=q%WskL2!k%WPPQ!{s&TF9*zJ2 literal 0 HcmV?d00001 diff --git a/src/Locale/hu_HU/Users.po b/src/Locale/hu_HU/Users.po new file mode 100644 index 000000000..4fb02e3f6 --- /dev/null +++ b/src/Locale/hu_HU/Users.po @@ -0,0 +1,816 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-10-23 16:36+0200\n" +"PO-Revision-Date: 2017-10-23 17:17+0200\n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.1\n" +"Last-Translator: rrd \n" +"Language: hu_HU\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "A kiszolgáló nem lehet üres" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "A fiók sikeresen ellenőrizve" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "A fiókot nem tudtam ellenőrizni" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Érvénytelen token és/vagy közösségi fiók" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "A közösségi fiók már aktív" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "A közösségi fiók nem ellenőrizhető" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Az email sikeresen elküldve" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "Az emailt nem tudtuk elküldeni" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Érvénytelen fiók" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Az emailt nem lehet újraküldeni" + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Érvénytelen alkalamzás só. Az alkalmazás sónak legalább 256 bit (32 byte) " +"hosszúnak kell lennie" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "Nem tudod engedélyezni az email ellenőrzést ha a use_email false" + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "Nem sikerült társítani a fiókot, próbáld meg még egyszer." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "A közösségi fiók társítva." + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "Gond van a közösségi fiókkal való belépéssel." + +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Add meg az emailedet." + +#: Controller/Traits/LoginTrait.php:120 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"A felhasználód még nincs ellenőrizve. Názd meg az emailjeidet a teendőkért." + +#: Controller/Traits/LoginTrait.php:125 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"A közösségi fiókod még nincs ellenőrizve. Názd meg az emailjeidet a " +"teendőkért." + +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "Érvénytelen reCaptcha" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "Már be vagy jelentkezve" + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "Először engedélyezd a Google Authenticatort." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Az ellenőrző kód érvénytelen. Próbáld meg újra" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "A felhasználói név vagy a jelszó helytelen" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "Sikeresen kijelentkeztél" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "A felhasználó nem található" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "A jelszót nem tudtuk módosítani" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "A jelszó siekresen módosítva" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "Nézd meg az emailjeidet a jelszó visszaállítás folytatásához" + +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "A jelszó token létrehozása sikertelen. Próbáld meg újra" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "A {0} felhasználó nem található" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "A felhasználó nem aktív" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "A token nem állítható vissza" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "A Google Authenticator token sikeresen visszaállítva" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "Még nem jelentkeztél be. Jelentkezz be" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "Ki kell lépned ahhoz, hogy új fiókot tudj létrehozni" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "A felhasználót nem lehet menteni" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "Sikeresen regisztráltál, lépj be" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "Kérlek jitelesítsd a fiókodat mielőtt belépnél" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "A {0} mentve" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "A {0} nincs mentve" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "A {0} törölve" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "A {0} nem lett törölve" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "A reCaptcha nem ellenőrizhető" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "A fiók sikeresen ellenőrizve" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "A fiókot nem sikerült ellnőrizni" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "A fiók már aktív" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "A jelszó helyreállító token sikeresen ellenőrizve" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "A jelszó helyreállító token ellenőrzése sikertelen" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "Helytelen ellenőrzés típus" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "Helytelen token vagy a fiók már ellenőrizve van" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "A token már lejárt" + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "A token helyreállítva. Nézd meg az emailjeidet." + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "{0} felhasználó már aktív" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "A fiókod hitelesítési linkje" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "{0} A jelszó helyreállítás linkje" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "{0} A közösségi fiókod ellenőrzési linkje" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "Hiányzó 'username' az opciókban" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "A közösségi fiók már csatlakoztatva van egy másik felhasználóhoz" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "A hivatkozás nem lehet null" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "A token lejárat nme lehet üres" + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "A felhasználó nem található" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "A felhasználói fiók már ellenőrizve van" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "A felhasználó nem aktív" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "A jelenlegi jelszó nem stimmel" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "Nem lehet az új jelszó azonos a régivel" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "Nem található felhasználó ehhez a tokenhez és emailhez." + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "A token lejárt felhasználó token nélkül" + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "A fiók már ellenőrizve van" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "Nem található fiók ehhez a tokenhez és emailhez." + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "Nem tudom belépni a usert a {0} hivatkozással" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "Hiányzó email" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "A jelszavad és a jelszó megerősítés nem azonos. Próbáld meg újra" + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "A felhasználónév már foglalt" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "Az email már foglalt" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Eszközök a CakeDC Users Puginhez" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "Egy bizonyos felhasználó aktiválása" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "Új superadmin hozzáadása tesztelési céllal" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "Új felhasználó" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "Egy felhasználói szerep módosítása" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Egy felhasználó deaktiválása" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Egy felhasználó törlése" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "Jelszó helyreállítás emailben" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "Minden feéhasználó jelszavának visszaállítása" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "Egy felhasználó jelszavának visszaállítása" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "Adj meg egy jelszót" + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "Mindne felhasználó jelszava módosítva" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "Új jelszó: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "Adj meg egy felhasználónevet." + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "A {0} felhasználó jelszava megváltoztatva" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "Adj meg egy szerepet." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "{0} felhasználó szerepe módosítva" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "Új szerep: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "{0} felhasználó aktiválva" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "{0} felhasználó deaktiválva" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "Adj meg egy felhasználónevet vagy egy emailt." + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Kérd meg a felhasználót, hogy nézze meg az emailjeit, hogy folytatni tudja a " +"jelszó visszaállítási folyamatot" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "Superuser hozzáadva:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "A felhasználó hozzáadva:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Felhasználónév: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Szerep: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Jelszó: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "A felhasználót ne tudtuk hozzáadni:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Mező: {0} Hiba: {1}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "A felhasználó nem található" + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "{0} felhasználó nem lett törölve. Próbáld meg újra" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "{0} felhasználó sikeresen törölve" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Szia {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Jelszó visszaállítás" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Ha a link nem jelenik meg jól, akkor másold be ezt a címet a böngésződbe {0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "Köszi" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Aktiváld a közösségi fiókodat" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Aktiváld a fiókodat" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Másold be a böngésződbe ezt a címet {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Másold be a böngésződbe ezt a címet a közösségi fiókod aktiválásához {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Műveletek" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Felhasználók" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 +msgid "Add User" +msgstr "Új felhasználó" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 +msgid "Username" +msgstr "Felhasználói név" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 +msgid "Email" +msgstr "" + +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "Jelszó" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 +msgid "First name" +msgstr "Keresztnév" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 +msgid "Last name" +msgstr "Családi név" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "Aktív" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Ment" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Add meg az új jelszót" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Jelenlegi jelszó" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Új jelszó" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "Jelszó megerősítése" + +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Törlés" + +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Biztos törlöd # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Felhasználó módosítása" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 +msgid "Token" +msgstr "" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token lejárat" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Aktiválás dátuma" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Felhasználó feltételek dátuma" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Google Authenticator Token visszaállítása" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "" +"Biztos vagy benne, hogy vissza akarod állítani {0} felhasználó tokenjét?" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Új {0}" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "Mutat" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "JElszó módosítás" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "Szerkeszt" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "előző" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "következő" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Add meg a felhasználói nevedet és a jelszavadat" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Emlékezz rám" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Regisztrálok" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Jelszó visszaállítás" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Belépés" + +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "Jelszó módosítás" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "Közösségi fiókok" + +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "" + +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +msgid "Provider" +msgstr "Kiszolgáló" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "Kapcsolódva: {0}" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "Elfogadod a felhasználó feltételeket?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Add meg az emailcímedet a jelszó helyreállításhoz" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Ellenörző email újraküldése" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email vagy felhasználó név" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Ellenörző kód" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" " +"Ellenőriz" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "Felhasználó törlése" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "Új felhasználó" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "Keresztnév" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "Családi név" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Szerep" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "Token lejárat" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "Aktiválás dátuma" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "Felhasználói feltételek dátuma" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "Létrehozva" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "Módosítva" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "Belépés ezzel" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "" + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "Kilép" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "Üdv {0}!" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"A reCaptcha nincs beállítva! Ellenőrizd a Users.reCaptcha.key beállítást" + +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Összekapcsolódva ezzel: {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Kapcsolódás ehhez: {0} " From 41b7a3775c9eb2db8fe484329840c8d51dd3620f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrik=20S=C3=B6dergren?= Date: Wed, 25 Oct 2017 16:28:45 +0200 Subject: [PATCH 0730/1476] Updated Swedish Locale files --- src/Locale/sv/Users.mo | Bin 14862 -> 14831 bytes src/Locale/sv/Users.po | 568 +++++++++++++++++++++-------------------- 2 files changed, 295 insertions(+), 273 deletions(-) diff --git a/src/Locale/sv/Users.mo b/src/Locale/sv/Users.mo index 8b5fa6e2007f8a73d024967af7362c3dff14155a..746e0c282db28536596d3914137f6af5c3ee11cd 100644 GIT binary patch delta 5419 zcma*p3vg7`9mnyr5kVgENJ20K;gUcIlFiG6gz$(6C=~)oA|i-&lih5VEW2?Zp+R&N zt%wS!S3tD*3^Z!7%4#a5gLUFqralUtu~czzXh++Q)6)8&trqR~w|k@L*vFmx_jB&q zz4xB;KmT)KOYCGcaXho%Hp6j%7(;w~wlSaKYlHdVcwv|^m*IXKi2a5elY>Js7boIa ztiv+A#yQ`L12}&g^}8M%jfZg@et_IEVFr&#HB27%=Zh(L4pv|ZPRF6R8a04UEW}%| z5}!m}_bzfn^Ssom5;dTYk))Z=F&q13rDvRr`u&B-Sj+;)RZf2x2l0Hfk;X{8R~^{xn8b3<526P0 zSIoe_qXzsbdN6~hYUW;?i!sy#_hSLRilulGHK1`ktPHC$p&7K&kP+0()}v;8GipGa zQ8TX73R9K!kAr~&)|&&7YD20Vbm(RITxwZu8(U&S+>4!Hu)$4)H7 z9jF@|#6|cT)?psgxDr?5G)&@T{4<`1qxfL5rVPj9JXF7*58eMJ=Tfp7VGYt{W;?EM`lF}}tw-JHcC_#jRI$Ep1XyahFphf(+IM%BbV zoQ{d#(3n6Yli|=b)kv0218QcgQ4idJ%2YSRSD|M))n};mF zX+ZrhfEI2@f1faq(=t zqaOSsYTz&9YJZ}s|v|~EsZv(V-IQo&!JL!5bN-L z)QhN)PTjB^b%Tp>GA=>Yz&g~LZ$bTT7Z%~u*dLFges>&6s`+pd`PUcO{EFAN$wMtg z397#ybwMMZjjfo<1Zt@^p=P`XwdOCPUOca%t~-Gm_$SV}MtctD*^cKYXsG%NaR4@8 z2Cj6@ufY|Zx1eVB5^AXqqh7INd0Vk+rVMA{6{rE-hi=@91M!&Sd#H(=MBOj(2@R#H zAFnHoY^38@Cn z^J(aYP1uOn;XHf=HS-}%qXhk^ZL=Nq;8*Zmd>d7Ke?;w$bNI1#$2indRHJHaAySuS zBl2hV@-a~R{~a0{(fg=1J)5Tt!hF;N+^GKPNFAExsOnFkZoCb3gy@b50 z%v+d^r%|ui%&K(t7o(P{&GB~B_q$OOd=Zs_cTr1wx{Cbkg29Y}0yRaLiH)cW{HPgk zbiUt#N^!5#e+Y9p|1DmICs9jPTbkj&pqBO{WDF)J!2(@LVvGJ&1+D#Qim7eLOcsMqqgZi$VMfnp7REq`i$$st!2)&)|Hb$vJ1!n2U+~2*Zyi|9M$uw==8zI=KuOAzyRMS{sP9T6CH@=?9jn4PasrcKR6;Ud0@mySNWykus`UtX2)Z#zECXC?1}OC^gz~nqKve;*%ytr#Dl@k z^eF9LWfmu|&RXlTPh?jo_lC@U1s$2}Gi?lH{AC>RonmZl1k7w`laY{;*L~ zw>xuBPBcry+^xCQ6Y?{^zGT#<=B=+%ExUVkb3(HW_D$0A1S39=mkIVw->bxW$Ve-> zR63TlE63Hkrm6yz+5p8fC+zi^R892tG}B`RqE;Z(;Ry!3 zC01j4osz4qi!c6jJK|G|qgjC3> zpL(pea3~fowpzGpw6~|t3iy50@;?g4By%TKx^lj?vSRkQ${c%P(MtP^qWfH>_V&q# z?6wOoO|F_UFQarB;|l67mZvQi=wN>Tp^o)L3i(m@e3$)UiDgeHt^RL?yr^`o{kPH_ z`<>FQc1zg>11a2Kx^SN>yLw5g3}flpSiM~lHkOz7Ok23UJ?P;zpj>K5p%A@aC65aI z+Lg*mZ%-^*Vh=4JKhUYt_?qOQ@|#?C%Y`4=+bgT>(-X$nrz+Rkb>*XzEme2Arlo3; zkB~pw7WSHDD!DIDd8)<}_6LHofWO4Lj#ejenO8BuqE*)e{ zAI6KJ)-8i0p##UlZIGqrksQ)WX2v+`+veK{12iP*@1% z*%YYtOCYb94L%e8{B5uw^Lybi*zS){`uqj#&H3gmogVOaP!^wuo8X(!hKq;fJUsww z7$1W=@H03L_Q$FUSP5m&CRhn?f{NTBpBX5}o`Z7u6ig4G^D-S-`bQ{F--8PAUttOS z1g?U^abqcrLZ#|ypC@5|#vM?GorT)>O(=&hK<)D{sP{%uNUELELgKH^VkXAGdZ-+4 zgWBLATmg^41+XXXt%WskHrxkCz*itPnh)V6uqTt6pTI-=E`a=GHbB)@3!DhsM-cx@ z>HL}rS@uuJUpB!CT@i`acpTL4^Pq}r2~-HLf!eqps#tG^Q{Y`tDLDo$_zu*8y}1gy zW#v%&E=$wV^$7Bq3^i6L4?$Ue9FB+QpsM{dsMPeMgk?wp)VdNV0~f*wtc7ymC{&I7 z6wZaO!%{dJE9jc^B05CZY=H8_g*tF2RH%+Z{>&RZINSUe%JL#k)qB%?)IjfzYoE6@NaMhT*}>% z0ehfw`V`cGC!h>`4laT(!aUfQuqaafp>jMF>Q+_4?E!8O)IR4agtT(=HXSYe4^)ne zD1a(h4V8ir)IqmEf?;lldhY!7RvB-P?2 z9~Jr;P`6<<)P8Ze8g7M4viF~kLNWsP%3%uXz{j8rISy5HFF;+(x1nys=TNB`!b>Wy zNsziT4N&{s#Y2XjfHLG1l;LkcrTQ7KzXnp zItJJ9!0XZsGFL+ELLq8Qft{hiQ5b!ZVn#Y)43Yy%H85m zmcR(gpl8ttl#u_=(CLT9Beh*f-|6{iAL@nnq8+HSHPE>c%|&atqYeICcWh-4?KV+GKMyI54!RcUUSEOKu0%E2 zo-tp8i~W89ya}yVvBmt!@4?Ne5UoK?Xf)c6)}qNs?Fh=`4SFKry~1Nunq!WgaxA=v#(Bq&Uv^cQwVC*JZRt$B$xYe~E{i&S&ILP^Of*>-n{~rUxtW8b z_6CMTI3pBwu&2vGZ{C>qX0P7TOnyjK1Uuph%TA>d4bg0f8thn1Mw+fQyee;6u_x%2 z6qom`4VpDxU|6wtLvd5)LUDBnf9omebehi`7% z!Cz}M$cng|OfYS?S{?0SJ6Z2UI*uo!;fUi>f+6~r9dGSuj|c4}L82tHduQMLvLaJd zWLH626_c{j^ow#)?saxcx%guzgI}JJSw5wYm3+#=TzyWpTU?bVcZb{MovFOeYpWWY&KBpF zKE$oY7DY80cNN<9aG0dK(O7Jb@$0gsNrg$Qa)sH^p0wOVlUqj4la@jei-rkG*s&bf z^~35{XKS?k?vAQ+WCVw-c*lV-7q>G4xm;xSS8WT7sbLozKiavmIxA7n{6)_AMN xkMW|_H)s0HxGj)*VdmX|0_;+~$80Ntcd0FLZ{w`d-mhj&_u6MAz4F;V{~r}QL&pFB diff --git a/src/Locale/sv/Users.po b/src/Locale/sv/Users.po index 8f27e7636..839edfdc3 100644 --- a/src/Locale/sv/Users.po +++ b/src/Locale/sv/Users.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: Users\n" -"POT-Creation-Date: 2016-10-26 11:24+0200\n" -"PO-Revision-Date: 2016-10-26 11:30+0200\n" +"POT-Creation-Date: 2017-10-25 16:18+0200\n" +"PO-Revision-Date: 2017-10-25 16:24+0200\n" "Last-Translator: Ulrik Södergren \n" "Language-Team: CakeDC \n" "Language: sv\n" @@ -13,47 +13,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.11\n" +"X-Generator: Poedit 1.8.12\n" -#: Auth/ApiKeyAuthenticate.php:73 -msgid "Type {0} is not valid" -msgstr "Typ {0} är inte giltig" - -#: Auth/ApiKeyAuthenticate.php:77 -msgid "Type {0} has no associated callable" -msgstr "Typ {0} har inget tillhörande anrop" - -#: Auth/ApiKeyAuthenticate.php:86 -msgid "SSL is required for ApiKey Authentication" -msgstr "SSL krävs för ApiKey-autentisering" - -#: Auth/SimpleRbacAuthorize.php:142 -msgid "" -"Missing configuration file: \"config/{0}.php\". Using default permissions" -msgstr "" -"Saknad konfigurationsfil: \"config / {0} .php\". Använder " -"standardbehörigheter" - -#: Auth/SocialAuthenticate.php:432 +#: Auth/SocialAuthenticate.php:456 msgid "Provider cannot be empty" msgstr "Leverantör kan inte vara tomt" -#: Auth/Rules/AbstractRule.php:78 -msgid "" -"Table alias is empty, please define a table alias, we could not extract a " -"default table from the request" -msgstr "" -"Tabellalias är tomt, var vänlig ange ett tabellalias, vi kunde inte " -"extrahera någon standardtabell" - -#: Auth/Rules/Owner.php:67;70 -msgid "" -"Missing column {0} in table {1} while checking ownership permissions for " -"user {2}" -msgstr "" -"Saknar kolumn {0} i tabell {1} vid kontroll av ägarbehörigheter för " -"användare {2}" - #: Controller/SocialAccountsController.php:52 msgid "Account validated successfully" msgstr "Kontot har validerats" @@ -64,7 +29,7 @@ msgstr "Konto kunde inte valideras" #: Controller/SocialAccountsController.php:57 msgid "Invalid token and/or social account" -msgstr "Ogiltig token och / eller social konto" +msgstr "Ogiltig token och/eller social konto" #: Controller/SocialAccountsController.php:59;87 msgid "Social Account already active" @@ -90,25 +55,33 @@ msgstr "Ogiltigt konto" msgid "Email could not be resent" msgstr "E-post kunde inte skickas om" -#: Controller/Component/RememberMeComponent.php:69 +#: Controller/Component/RememberMeComponent.php:68 msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" msgstr "" "Ogiltig app salt, måste app salt vara åtminstone 256 bitar (32 byte) långt" -#: Controller/Component/UsersAuthComponent.php:178 +#: Controller/Component/UsersAuthComponent.php:204 msgid "You can't enable email validation workflow if use_email is false" msgstr "" "Du kan inte aktivera epost-validering arbetsflöde om use_email är falskt" -#: Controller/Traits/LoginTrait.php:96 +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "Kunde inte ansluta konto, försök igen." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "Socialt konto anslöts." + +#: Controller/Traits/LoginTrait.php:104 msgid "Issues trying to log in with your social account" msgstr "Problem vid inloggning med ditt sociala konto" -#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 msgid "Please enter your email" msgstr "Lägg till din epost" -#: Controller/Traits/LoginTrait.php:108 +#: Controller/Traits/LoginTrait.php:120 msgid "" "Your user has not been validated yet. Please check your inbox for " "instructions" @@ -116,347 +89,331 @@ msgstr "" "Ditt konto har inte verifierats ännu. Vänligen kontrollera din inbox för " "instruktioner" -#: Controller/Traits/LoginTrait.php:110 +#: Controller/Traits/LoginTrait.php:125 msgid "" "Your social account has not been validated yet. Please check your inbox for " "instructions" msgstr "" -"Din sociala hänsyn har inte validerats ännu. Vänligen kontrollera din inbox " -"för instruktioner" +"Ditt sociala konto har inte validerats ännu. Kontrollera din inkorg för " +"instruktioner" -#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 msgid "Invalid reCaptcha" msgstr "Ogiltig reCaptcha" -#: Controller/Traits/LoginTrait.php:171 +#: Controller/Traits/LoginTrait.php:191 msgid "You are already logged in" msgstr "Du är redan inloggad." -#: Controller/Traits/LoginTrait.php:217 +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "Vänligen aktivera Google Authenticator först." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Valideringskoden är ogiltig. Försök igen" + +#: Controller/Traits/LoginTrait.php:340 msgid "Username or password is incorrect" msgstr "Användarnamn eller lösenord är felaktigt" -#: Controller/Traits/LoginTrait.php:238 +#: Controller/Traits/LoginTrait.php:363 msgid "You've successfully logged out" msgstr "Du har loggats ut" -#: Controller/Traits/PasswordManagementTrait.php:47;76 -#: Controller/Traits/ProfileTrait.php:49 +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 msgid "User was not found" msgstr "Användaren hittades inte" -#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 msgid "Password could not be changed" msgstr "Lösenordet kunde inte ändras" -#: Controller/Traits/PasswordManagementTrait.php:68 +#: Controller/Traits/PasswordManagementTrait.php:74 msgid "Password has been changed successfully" msgstr "Lösenordsbytet lyckades!" -#: Controller/Traits/PasswordManagementTrait.php:78 +#: Controller/Traits/PasswordManagementTrait.php:84 msgid "{0}" msgstr "{0}" -#: Controller/Traits/PasswordManagementTrait.php:120 +#: Controller/Traits/PasswordManagementTrait.php:127 msgid "Please check your email to continue with password reset process" msgstr "Kontrollera din epost för att fortsätta lösenordsåterställningen" -#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 msgid "The password token could not be generated. Please try again" msgstr "Lösenordstoken kunde inte skapas. Var god försök igen" -#: Controller/Traits/PasswordManagementTrait.php:129 -#: Controller/Traits/UserValidationTrait.php:100 +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 msgid "User {0} was not found" msgstr "Användaren {0} hittades inte" -#: Controller/Traits/PasswordManagementTrait.php:131 +#: Controller/Traits/PasswordManagementTrait.php:138 msgid "The user is not active" msgstr "Användaren är inte aktiverad" -#: Controller/Traits/PasswordManagementTrait.php:133 -#: Controller/Traits/UserValidationTrait.php:95;104 +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 msgid "Token could not be reset" msgstr "Token kunde inte återställas" -#: Controller/Traits/ProfileTrait.php:53 +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "Google Authenticator token har återställts" + +#: Controller/Traits/ProfileTrait.php:54 msgid "Not authorized, please login first" msgstr "Inte auktoriserad, vänligen logga in först" -#: Controller/Traits/RegisterTrait.php:42 +#: Controller/Traits/RegisterTrait.php:43 msgid "You must log out to register a new user account" msgstr "Du måste logga ut för att registrera ett nytt användarkonto" -#: Controller/Traits/RegisterTrait.php:88 +#: Controller/Traits/RegisterTrait.php:89 msgid "The user could not be saved" msgstr "Användaren kunde inte sparas" -#: Controller/Traits/RegisterTrait.php:122 +#: Controller/Traits/RegisterTrait.php:123 msgid "You have registered successfully, please log in" msgstr "Din registrering är klar, vänligen logga in" -#: Controller/Traits/RegisterTrait.php:124 +#: Controller/Traits/RegisterTrait.php:125 msgid "Please validate your account before log in" msgstr "Vänligen validera ditt konto innan inloggning" -#: Controller/Traits/SimpleCrudTrait.php:76;106 +#: Controller/Traits/SimpleCrudTrait.php:77;107 msgid "The {0} has been saved" msgstr "{0} har sparats" -#: Controller/Traits/SimpleCrudTrait.php:80;110 +#: Controller/Traits/SimpleCrudTrait.php:81;111 msgid "The {0} could not be saved" msgstr "{0} kunde inte sparas" -#: Controller/Traits/SimpleCrudTrait.php:130 +#: Controller/Traits/SimpleCrudTrait.php:131 msgid "The {0} has been deleted" msgstr "{0} har tagits bort" -#: Controller/Traits/SimpleCrudTrait.php:132 +#: Controller/Traits/SimpleCrudTrait.php:133 msgid "The {0} could not be deleted" msgstr "{0} kunde inte tas bort" -#: Controller/Traits/SocialTrait.php:39 +#: Controller/Traits/SocialTrait.php:40 msgid "The reCaptcha could not be validated" msgstr "reCAPTCHA angavs inte korrekt" -#: Controller/Traits/UserValidationTrait.php:42 +#: Controller/Traits/UserValidationTrait.php:43 msgid "User account validated successfully" msgstr "Användarkontot har validerats" -#: Controller/Traits/UserValidationTrait.php:44 +#: Controller/Traits/UserValidationTrait.php:45 msgid "User account could not be validated" msgstr "Användarkontot kunde inte valideras" -#: Controller/Traits/UserValidationTrait.php:47 +#: Controller/Traits/UserValidationTrait.php:48 msgid "User already active" msgstr "Användaren redan aktiv" -#: Controller/Traits/UserValidationTrait.php:53 +#: Controller/Traits/UserValidationTrait.php:54 msgid "Reset password token was validated successfully" -msgstr "Återställning av lösenord lyckades." +msgstr "Återställning av lösenord lyckades" -#: Controller/Traits/UserValidationTrait.php:58 +#: Controller/Traits/UserValidationTrait.php:62 msgid "Reset password token could not be validated" msgstr "Token för att återställa lösenord kunde inte valideras" -#: Controller/Traits/UserValidationTrait.php:62 +#: Controller/Traits/UserValidationTrait.php:66 msgid "Invalid validation type" msgstr "Ogiltig valideringsmetod" -#: Controller/Traits/UserValidationTrait.php:65 +#: Controller/Traits/UserValidationTrait.php:69 msgid "Invalid token or user account already validated" msgstr "Ogiltig token eller så har användaren konto redan validerats" -#: Controller/Traits/UserValidationTrait.php:67 +#: Controller/Traits/UserValidationTrait.php:71 msgid "Token already expired" msgstr "Token redan löpt ut" -#: Controller/Traits/UserValidationTrait.php:93 +#: Controller/Traits/UserValidationTrait.php:97 msgid "Token has been reset successfully. Please check your email." msgstr "Token har återställts. Kontrollera din e-post." -#: Controller/Traits/UserValidationTrait.php:102 +#: Controller/Traits/UserValidationTrait.php:109 msgid "User {0} is already active" msgstr "Användaren {0} är redan aktiv" -#: Email/EmailSender.php:39 +#: Mailer/UsersMailer.php:34 msgid "Your account validation link" msgstr "Din länk för att validera kontot" -#: Mailer/UsersMailer.php:55 +#: Mailer/UsersMailer.php:52 msgid "{0}Your reset password link" msgstr "{0} Din länk för att återställa lösenord" -#: Mailer/UsersMailer.php:78 +#: Mailer/UsersMailer.php:75 msgid "{0}Your social account validation link" msgstr "{0} Din sociala konto svalideringslänk" -#: Model/Behavior/PasswordBehavior.php:56 +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "Saknas 'username' i alternativa uppgifter" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Socialt konto är redan kopplat till en annan användare." + +#: Model/Behavior/PasswordBehavior.php:45 msgid "Reference cannot be null" msgstr "Referens får inte vara null" -#: Model/Behavior/PasswordBehavior.php:61 +#: Model/Behavior/PasswordBehavior.php:50 msgid "Token expiration cannot be empty" msgstr "Giltighet för token kan inte vara tom" -#: Model/Behavior/PasswordBehavior.php:67;116 +#: Model/Behavior/PasswordBehavior.php:56;117 msgid "User not found" msgstr "Användaren hittades inte" -#: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:111 +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 msgid "User account already validated" msgstr "Kontot är redan aktiverat!" -#: Model/Behavior/PasswordBehavior.php:78 +#: Model/Behavior/PasswordBehavior.php:67 msgid "User not active" msgstr "Användaren ej aktiv" -#: Model/Behavior/PasswordBehavior.php:121 +#: Model/Behavior/PasswordBehavior.php:122 msgid "The current password does not match" msgstr "Den nuvarande lösenord matchar inte" -#: Model/Behavior/PasswordBehavior.php:124 +#: Model/Behavior/PasswordBehavior.php:125 msgid "You cannot use the current password as the new one" msgstr "Du kan inte använda det aktuella lösenordet som det nya" -#: Model/Behavior/RegisterBehavior.php:89 +#: Model/Behavior/RegisterBehavior.php:90 msgid "User not found for the given token and email." msgstr "Hittade ingen användare som matchar angivet token eller epost" -#: Model/Behavior/RegisterBehavior.php:92 +#: Model/Behavior/RegisterBehavior.php:93 msgid "Token has already expired user with no token" msgstr "Token har redan gått ut eller användare utan token" -#: Model/Behavior/SocialAccountBehavior.php:102;129 +#: Model/Behavior/SocialAccountBehavior.php:103;130 msgid "Account already validated" msgstr "Kontot är redan aktiverat!" -#: Model/Behavior/SocialAccountBehavior.php:105;132 +#: Model/Behavior/SocialAccountBehavior.php:106;133 msgid "Account not found for the given token and email." msgstr "Kontot hittades inte för givet token och e-post." -#: Model/Behavior/SocialBehavior.php:56 +#: Model/Behavior/SocialBehavior.php:82 msgid "Unable to login user with reference {0}" msgstr "Det går inte att logga in användaren med refrens {0}" -#: Model/Behavior/SocialBehavior.php:98 +#: Model/Behavior/SocialBehavior.php:121 msgid "Email not present" msgstr "Epost saknas" -#: Model/Table/UsersTable.php:82 +#: Model/Table/UsersTable.php:81 msgid "Your password does not match your confirm password. Please try again" msgstr "Dina lösenord matchar inte. Vänligen försök igen." -#: Model/Table/UsersTable.php:175 +#: Model/Table/UsersTable.php:173 msgid "Username already exists" msgstr "Användarnamnet är upptaget" -#: Model/Table/UsersTable.php:181 +#: Model/Table/UsersTable.php:179 msgid "Email already exists" msgstr "E-postadressen finns redan" -#: Model/Table/UsersTable.php:214 -msgid "Missing 'username' in options data" -msgstr "Saknas 'username' i alternativa uppgifter" - -#: Shell/UsersShell.php:54 +#: Shell/UsersShell.php:58 msgid "Utilities for CakeDC Users Plugin" msgstr "Verktyg för CakeDC User Plugin" -#: Shell/UsersShell.php:55 +#: Shell/UsersShell.php:60 msgid "Activate an specific user" msgstr "Aktivera en specifik användare" -#: Shell/UsersShell.php:56 +#: Shell/UsersShell.php:63 msgid "Add a new superadmin user for testing purposes" msgstr "Lägga till en ny superadmin användare för teständamål" -#: Shell/UsersShell.php:57 +#: Shell/UsersShell.php:66 msgid "Add a new user" msgstr "Ny användare" -#: Shell/UsersShell.php:58 +#: Shell/UsersShell.php:69 msgid "Change the role for an specific user" msgstr "Ändra rollen för en specifik användare" -#: Shell/UsersShell.php:59 +#: Shell/UsersShell.php:72 msgid "Deactivate an specific user" msgstr "Inaktivare en specifik användare" -#: Shell/UsersShell.php:60 +#: Shell/UsersShell.php:75 msgid "Delete an specific user" msgstr "Ta bort en specifik användare" -#: Shell/UsersShell.php:61 +#: Shell/UsersShell.php:78 msgid "Reset the password via email" msgstr "Återställ lösenord via e-post" -#: Shell/UsersShell.php:62 +#: Shell/UsersShell.php:81 msgid "Reset the password for all users" msgstr "Återställ lösenord för alla användare" -#: Shell/UsersShell.php:63 +#: Shell/UsersShell.php:84 msgid "Reset the password for an specific user" msgstr "Återställ lösenordet för en specifik användare" -#: Shell/UsersShell.php:98 -msgid "User added:" -msgstr "Användare tillagd:" - -#: Shell/UsersShell.php:99;127 -msgid "Id: {0}" -msgstr "Id: {0}" - -#: Shell/UsersShell.php:100;128 -msgid "Username: {0}" -msgstr "Användarnamn: {0}" - -#: Shell/UsersShell.php:101;129 -msgid "Email: {0}" -msgstr "Epost: {0}" - -#: Shell/UsersShell.php:102;130 -msgid "Password: {0}" -msgstr "Lösenord: {0}" - -#: Shell/UsersShell.php:126 -msgid "Superuser added:" -msgstr "Superanvändare tillagd:" - -#: Shell/UsersShell.php:132 -msgid "Superuser could not be added:" -msgstr "Superanvändaren kunde inte läggas till:" - -#: Shell/UsersShell.php:135 -msgid "Field: {0} Error: {1}" -msgstr "Fält: {0} fel: {1}" - -#: Shell/UsersShell.php:153;179 +#: Shell/UsersShell.php:133;159 msgid "Please enter a password." msgstr "Ange ett lösenord." -#: Shell/UsersShell.php:157 +#: Shell/UsersShell.php:137 msgid "Password changed for all users" msgstr "Lösenordet ändrat för alla användare" -#: Shell/UsersShell.php:158;186 +#: Shell/UsersShell.php:138;166 msgid "New password: {0}" msgstr "Nytt lösenord: {0}" -#: Shell/UsersShell.php:176;204;282;324 +#: Shell/UsersShell.php:156;184;262;359 msgid "Please enter a username." msgstr "Ange ett användarnamn" -#: Shell/UsersShell.php:185 +#: Shell/UsersShell.php:165 msgid "Password changed for user: {0}" msgstr "Lösenordet ändrat för användare: {0}" -#: Shell/UsersShell.php:207 +#: Shell/UsersShell.php:187 msgid "Please enter a role." msgstr "Ange en roll." -#: Shell/UsersShell.php:213 +#: Shell/UsersShell.php:193 msgid "Role changed for user: {0}" msgstr "Rollen har ändrats för användare: {0}" -#: Shell/UsersShell.php:214 +#: Shell/UsersShell.php:194 msgid "New role: {0}" msgstr "Ny roll: {0}" -#: Shell/UsersShell.php:229 +#: Shell/UsersShell.php:209 msgid "User was activated: {0}" msgstr "Användaren aktiverades: {0}" -#: Shell/UsersShell.php:244 +#: Shell/UsersShell.php:224 msgid "User was de-activated: {0}" msgstr "Användaren avaktiverad: {0}" -#: Shell/UsersShell.php:256 +#: Shell/UsersShell.php:236 msgid "Please enter a username or email." msgstr "Skriv användarnamn eller epost" -#: Shell/UsersShell.php:264 +#: Shell/UsersShell.php:244 msgid "" "Please ask the user to check the email to continue with password reset " "process" @@ -464,15 +421,51 @@ msgstr "" "Be användaren kontrollera sin epost för att fortsätta " "lösenordsåterställningen" -#: Shell/UsersShell.php:302 +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "Superanvändare tillagd:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "Användare tillagd:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Användarnamn: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "Epost: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Roll: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Lösenord: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "Användare kunde inte läggas till:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Fält: {0} fel: {1}" + +#: Shell/UsersShell.php:337 msgid "The user was not found." msgstr "Användaren hittades inte." -#: Shell/UsersShell.php:332 +#: Shell/UsersShell.php:367 msgid "The user {0} was not deleted. Please try again" msgstr "Användaren {0} raderades ej. Var god försök igen" -#: Shell/UsersShell.php:334 +#: Shell/UsersShell.php:369 msgid "The user {0} was deleted successfully" msgstr "Användaren {0} har tagits bort" @@ -491,19 +484,20 @@ msgstr "Återställ ditt lösenord här" #: Template/Email/html/reset_password.ctp:27 #: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 msgid "" "If the link is not correctly displayed, please copy the following address in " "your web browser {0}" msgstr "" -"Om länken inte visas korrekt, vänligen kopiera följande adress till " -"webbläsaren {0}" - -#: Template/Email/html/reset_password.ctp:30 -#: Template/Email/html/social_account_validation.ctp:35 -#: Template/Email/html/validation.ctp:30 -#: Template/Email/text/reset_password.ctp:24 -#: Template/Email/text/social_account_validation.ctp:26 -#: Template/Email/text/validation.ctp:24 +"Om länken inte visas korrekt, vänligen kopiera följande adress till din " +"webbläsare {0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 msgid "Thank you" msgstr "Tack" @@ -515,14 +509,6 @@ msgstr "Aktivera ditt sociala konto här" msgid "Activate your account here" msgstr "Aktivera ditt konto här" -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correctly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Om länken inte visas korrekt, vänligen kopiera följande adress till din " -"webbläsare {0}" - #: Template/Email/text/reset_password.ctp:22 #: Template/Email/text/validation.ctp:22 msgid "Please copy the following address in your web browser {0}" @@ -536,54 +522,53 @@ msgstr "" "Kopiera följande adress till din webbläsare för att aktivera din sociala " "inloggning {0}" -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 msgid "Actions" msgstr "Resurser" -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 -#: Template/Users/view.ctp:19 +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 msgid "List Users" msgstr "Lista användare" -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:21 -msgid "List Accounts" -msgstr "Lista konton" - -#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 msgid "Add User" msgstr "Ny användare" -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 -#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 msgid "Username" msgstr "Användarnamn" -#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 msgid "Email" msgstr "Epost" +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "Lösenord" + #: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 msgid "First name" msgstr "Förnamn" #: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 msgid "Last name" msgstr "Efternamn" #: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:44;75 +#: Template/Users/view.ctp:49;74 msgid "Active" msgstr "Aktivt" #: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 +#: 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 @@ -602,17 +587,16 @@ msgstr "Nuvarande lösenord" msgid "New password" msgstr "Nytt lösenord" -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 msgid "Confirm password" msgstr "Bekräfta lösenord" -#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:101 +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 msgid "Delete" msgstr "Radera" -#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:18;101 +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 msgid "Are you sure you want to delete # {0}?" msgstr "Är du säker på att du vill radera{0}" @@ -620,7 +604,7 @@ msgstr "Är du säker på att du vill radera{0}" msgid "Edit User" msgstr "Redigera användare" -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 msgid "Token" msgstr "Token" @@ -640,11 +624,19 @@ msgstr "Aktiveringsdatum" msgid "TOS date" msgstr "TOS datum" +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Återställ Google Authenticator Token" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "Är du säker du vill återställa token för användare \"{0}\"?" + #: Template/Users/index.ctp:15 msgid "New {0}" msgstr "Nytt {0}" -#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +#: Template/Users/index.ctp:37 msgid "View" msgstr "Visa" @@ -652,7 +644,7 @@ msgstr "Visa" msgid "Change password" msgstr "Byt lösenord" -#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +#: Template/Users/index.ctp:39 msgid "Edit" msgstr "Ändra" @@ -684,39 +676,35 @@ msgstr "Återställ Lösenord" msgid "Login" msgstr "Logga in" -#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 msgid "{0} {1}" msgstr "{0} {1}" -#: Template/Users/profile.ctp:24 +#: Template/Users/profile.ctp:27 msgid "Change Password" msgstr "Ändra Lösenord" -#: Template/Users/profile.ctp:34 +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 msgid "Social Accounts" msgstr "Sociala konton" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 msgid "Avatar" msgstr "Profilbild" -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 msgid "Provider" msgstr "Utförare" -#: Template/Users/profile.ctp:40 +#: Template/Users/profile.ctp:44 msgid "Link" msgstr "Länk" -#: Template/Users/profile.ctp:47 +#: Template/Users/profile.ctp:51 msgid "Link to {0}" msgstr "Länk till {0}" -#: Template/Users/register.ctp:20 -msgid "Password" -msgstr "Lösenord" - -#: Template/Users/register.ctp:28 +#: Template/Users/register.ctp:29 msgid "Accept TOS conditions?" msgstr "Jag accepterar villkoren" @@ -732,111 +720,145 @@ msgstr "Skicka nytt bekräftelsemejl" msgid "Email or username" msgstr "E-post/Användarnamn" -#: Template/Users/view.ctp:18 +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Verifieringskod" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" " +"Verifiera" + +#: Template/Users/view.ctp:19 msgid "Delete User" msgstr "Ta bort användare" -#: Template/Users/view.ctp:20 +#: Template/Users/view.ctp:24 msgid "New User" msgstr "Ny användare" -#: Template/Users/view.ctp:28;67 +#: Template/Users/view.ctp:31 msgid "Id" msgstr "Id" -#: Template/Users/view.ctp:34 +#: Template/Users/view.ctp:37 msgid "First Name" msgstr "Förnamn" -#: Template/Users/view.ctp:36 +#: Template/Users/view.ctp:39 msgid "Last Name" msgstr "Efternamn" -#: Template/Users/view.ctp:40 +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Roll" + +#: Template/Users/view.ctp:45 msgid "Api Token" msgstr "Api-token" -#: Template/Users/view.ctp:48;74 +#: Template/Users/view.ctp:53 msgid "Token Expires" msgstr "Token förfaller" -#: Template/Users/view.ctp:50 +#: Template/Users/view.ctp:55 msgid "Activation Date" msgstr "Aktiveringsdatum" -#: Template/Users/view.ctp:52 +#: Template/Users/view.ctp:57 msgid "Tos Date" msgstr "Tos datum" -#: Template/Users/view.ctp:54;77 +#: Template/Users/view.ctp:59;75 msgid "Created" msgstr "Skapad" -#: Template/Users/view.ctp:56;78 +#: Template/Users/view.ctp:61;76 msgid "Modified" msgstr "Ändrad" -#: Template/Users/view.ctp:63 -msgid "Related Accounts" -msgstr "Relaterade konton" - -#: Template/Users/view.ctp:68 -msgid "User Id" -msgstr "Användar-ID" - -#: Template/Users/view.ctp:71 -msgid "Reference" -msgstr "Referens" - -#: Template/Users/view.ctp:76 -msgid "Data" -msgstr "Data" - -#: View/Helper/UserHelper.php:46 +#: View/Helper/UserHelper.php:45 msgid "Sign in with" msgstr "Logga in med" -#: View/Helper/UserHelper.php:49 +#: View/Helper/UserHelper.php:48 msgid "fa fa-{0}" msgstr "fa fa-{0}" -#: View/Helper/UserHelper.php:52 +#: View/Helper/UserHelper.php:57 msgid "btn btn-social btn-{0} " msgstr "btn btn-social btn-{0} " -#: View/Helper/UserHelper.php:91 +#: View/Helper/UserHelper.php:106 msgid "Logout" msgstr "Logga ut" -#: View/Helper/UserHelper.php:108 +#: View/Helper/UserHelper.php:123 msgid "Welcome, {0}" msgstr "Välkommen, {0}" -#: View/Helper/UserHelper.php:131 +#: View/Helper/UserHelper.php:146 msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" msgstr "reCaptcha är inte konfigurerad! Konfigurera Users.reCaptcha.key" -#: Model/Behavior/RegisterBehavior.php:148 -msgid "This field is required" -msgstr "Detta fält är obligatoriskt" +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Ansluten med {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Anslut med {0}" + +#~ msgid "Type {0} is not valid" +#~ msgstr "Typ {0} är inte giltig" + +#~ msgid "Type {0} has no associated callable" +#~ msgstr "Typ {0} har inget tillhörande anrop" + +#~ msgid "SSL is required for ApiKey Authentication" +#~ msgstr "SSL krävs för ApiKey-autentisering" + +#~ msgid "" +#~ "Missing configuration file: \"config/{0}.php\". Using default permissions" +#~ msgstr "" +#~ "Saknad konfigurationsfil: \"config / {0} .php\". Använder " +#~ "standardbehörigheter" + +#~ msgid "" +#~ "Table alias is empty, please define a table alias, we could not extract a " +#~ "default table from the request" +#~ msgstr "" +#~ "Tabellalias är tomt, var vänlig ange ett tabellalias, vi kunde inte " +#~ "extrahera någon standardtabell" -#~ msgid "The old password does not match" -#~ msgstr "Det gamla lösenordet stämmer inte" +#~ msgid "" +#~ "Missing column {0} in table {1} while checking ownership permissions for " +#~ "user {2}" +#~ msgstr "" +#~ "Saknar kolumn {0} i tabell {1} vid kontroll av ägarbehörigheter för " +#~ "användare {2}" -#~ msgid "SocialAccount already active" -#~ msgstr "SocialAccount redan aktivt" +#~ msgid "List Accounts" +#~ msgstr "Lista konton" -#~ msgid "There was an error associating your social network account" -#~ msgstr "Det gick inte att associera ditt sociala nätverkskonto" +#~ msgid "Related Accounts" +#~ msgstr "Relaterade konton" -#~ msgid "Invalid token and/or email" -#~ msgstr "Ogiltig token och / eller epost" +#~ msgid "User Id" +#~ msgstr "Användar-ID" -#~ msgid "The \"tos\" property is not present" -#~ msgstr "\"tos\" fältet saknas" +#~ msgid "Reference" +#~ msgstr "Referens" -#~ msgid "+ {0} secs" -#~ msgstr "{0} sek" +#~ msgid "Data" +#~ msgstr "Data" -#~ msgid "Sign in with Facebook" -#~ msgstr "Logga in med Facebook" +#~ msgid "This field is required" +#~ msgstr "Detta fält är obligatoriskt" From 815be770d834c3f375ba7bccda0f1ed24358023a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 26 Oct 2017 18:30:40 +0100 Subject: [PATCH 0731/1476] Update Translations.md --- Docs/Documentation/Translations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index 2e2553f3b..432c93ef0 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -8,6 +8,7 @@ The Plugin is translated into several languages: * Brazillian Portuguese (pt_BR) by @andtxr * French (fr_FR) by @jtraulle * Polish (pl) by @joulbex +* Hungarian (hu_HU) by @rrd108 **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 4e3f88365a0f9ccdf3a47fcbb69d428ebda6ecad Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 27 Oct 2017 10:58:04 +0200 Subject: [PATCH 0732/1476] Implement Amazon Login --- composer.json | 2 ++ config/users.php | 8 ++++++ src/Auth/Social/Mapper/Amazon.php | 43 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 src/Auth/Social/Mapper/Amazon.php diff --git a/composer.json b/composer.json index 90489899e..528e23e63 100644 --- a/composer.json +++ b/composer.json @@ -37,6 +37,7 @@ "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", "satooshi/php-coveralls": "dev-master" @@ -46,6 +47,7 @@ "league/oauth2-facebook": "Provides Social Authentication with Facebook", "league/oauth2-instagram": "Provides Social Authentication with Instagram", "league/oauth2-google": "Provides Social Authentication with Google+", + "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" diff --git a/config/users.php b/config/users.php index 2d3840472..e590c5864 100644 --- a/config/users.php +++ b/config/users.php @@ -190,6 +190,14 @@ 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google', ] ], + 'amazon' => [ + 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', + 'options' => [ + 'redirectUri' => Router::fullBaseUrl() . '/auth/amazon', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/amazon', + ] + ], ], ] ]; diff --git a/src/Auth/Social/Mapper/Amazon.php b/src/Auth/Social/Mapper/Amazon.php new file mode 100644 index 000000000..20c532052 --- /dev/null +++ b/src/Auth/Social/Mapper/Amazon.php @@ -0,0 +1,43 @@ + 'user_id' + ]; + + /** + * @return string + */ + protected function _link() + { + return self::AMAZON_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['id']); + } +} From 76bf0e9577291ab8593f59bbe5e41c9138a1b1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Wed, 1 Nov 2017 21:13:01 +0100 Subject: [PATCH 0733/1476] Config key must be set before loading the plugin --- Docs/Documentation/Configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 4f070a835..c86f89318 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -8,6 +8,7 @@ For easier configuration, you can specify an array of config files to override t config/bootstrap.php ``` +// The following configuration setting must be set before loading the Users plugin Configure::write('Users.config', ['users']); Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); Configure::write('Users.Social.login', true); //to enable social login From 7f480050d0e3760f62dafef38e947e85660b9662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Wed, 1 Nov 2017 21:25:49 +0100 Subject: [PATCH 0734/1476] Improve documetnation around mapping fields Show a simple example, as the CakePHP documentaiton also lacks a clear, applicable example. --- Docs/Documentation/Extending-the-Plugin.md | 30 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index 20d6faa4b..01a5b5b99 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -9,7 +9,7 @@ users data. Check the initial users migration to know the default columns expect If your column names doesn't match the columns in your current table, you could use the Entity to match the colums using accessors & mutators as described here http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators -Example: we are going to use a custom table in our application ```my_users``` +Example: we are going to use a custom table ```my_users``` in our application , which has a field named ``is_active`` instead of the default ``active``. * Create a new Table under src/Model/Table/MyUsersTable.php ```php @@ -18,7 +18,7 @@ namespace App\Model\Table; use CakeDC\Users\Model\Table\UsersTable; /** - * Users Model + * Application specific Users Table with non plugin conform field(s) */ class MyUsersTable extends UsersTable { @@ -32,8 +32,32 @@ namespace App\Model\Entity; use CakeDC\Users\Model\Entity\User; +/** + * Application specific User Entity with non plugin conform field(s) + */ class MyUser extends User { + /** + * Map CakeDC's User.active field to User.is_active when getting + * + * @return mixed The value of the mapped property. + */ + protected function _getActive() + { + return $this->_properties['is_active']; + } + + /** + * Map CakeDC's User.active field to User.is_active when setting + * + * @param mixed $value The value to set. + * @return static + */ + protected function _setActive($value) + { + $this->set('is_active', $value); + return $value; + } } ``` @@ -53,7 +77,7 @@ return [ ``` Now the Users Plugin will use MyUsers Table and Entity to register and login user in. Use the -Entity to match your own columns in case they don't match the default column names: +Entity as shown above to match your own columns in case they don't match the default column names: ```sql CREATE TABLE IF NOT EXISTS `users` ( From c1ed7e0397cb7eb8ea668a476d1cfdde6f4b8aad Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Wed, 8 Nov 2017 19:38:01 +0100 Subject: [PATCH 0735/1476] Fix twitter workflow for social email. Increase facebook api version --- config/users.php | 2 +- src/Auth/SocialAuthenticate.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/users.php b/config/users.php index e590c5864..52bba11e8 100644 --- a/config/users.php +++ b/config/users.php @@ -152,7 +152,7 @@ 'facebook' => [ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook', diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 965e67005..331f5b2c0 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -352,12 +352,12 @@ protected function _touch(array $data) } if (!empty($exception)) { $args = ['exception' => $exception, 'rawData' => $data]; - $event = $this->_getController()->dispatchEvent(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, $args); + $this->_getController()->dispatchEvent(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, $args); if (method_exists($this->_getController(), 'failedSocialLogin')) { $this->_getController()->failedSocialLogin($exception, $data, true); } - return $event->result; + return false; } // If new SocialAccount was created $user is returned containing it From 96ba4528fad121b0b9970aa664b6a5d3a445a380 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 14 Nov 2017 12:08:48 +0100 Subject: [PATCH 0736/1476] Update facebook graph version --- tests/TestCase/Auth/SocialAuthenticateTest.php | 4 ++-- .../Controller/Traits/LinkSocialTraitTest.php | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index 47dc9e4a3..fb1387438 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -117,7 +117,7 @@ public function testConstructor() 'facebook' => [ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => 'http://example.com/auth/facebook', ] ] @@ -139,7 +139,7 @@ public function testConstructorMissingProvider() 'facebook' => [ 'className' => 'missing', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => 'http://example.com/auth/facebook', ] ] diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 97363cf0e..9088c66fc 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -146,7 +146,7 @@ public function testLinkSocialHappy() $this->equalTo([ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => '/auth/facebook', 'linkSocialUri' => '/link-social/facebook', 'callbackLinkSocialUri' => '/callback-link-social/facebook', @@ -335,7 +335,7 @@ public function testCallbackLinkSocialHappy() $this->equalTo([ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => '/auth/facebook', 'linkSocialUri' => '/link-social/facebook', 'callbackLinkSocialUri' => '/callback-link-social/facebook', @@ -480,7 +480,7 @@ public function testCallbackLinkSocialWithValidationErrors() $this->equalTo([ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => '/auth/facebook', 'linkSocialUri' => '/link-social/facebook', 'callbackLinkSocialUri' => '/callback-link-social/facebook', @@ -573,7 +573,7 @@ public function testCallbackLinkSocialFailGettingAccessToken() $this->equalTo([ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => '/auth/facebook', 'linkSocialUri' => '/link-social/facebook', 'callbackLinkSocialUri' => '/callback-link-social/facebook', @@ -664,7 +664,7 @@ public function testCallbackLinkSocialQueryHasErrors() $this->equalTo([ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => '/auth/facebook', 'linkSocialUri' => '/link-social/facebook', 'callbackLinkSocialUri' => '/callback-link-social/facebook', @@ -751,7 +751,7 @@ public function testCallbackLinkSocialWrongState() $this->equalTo([ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'options' => [ - 'graphApiVersion' => 'v2.5', + 'graphApiVersion' => 'v2.8', 'redirectUri' => '/auth/facebook', 'linkSocialUri' => '/link-social/facebook', 'callbackLinkSocialUri' => '/callback-link-social/facebook', From 741c59c6097db8bb912fb138a3ea550f7bce1969 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 8 Dec 2017 13:59:07 +0100 Subject: [PATCH 0737/1476] Fix flash messages on social login --- src/Auth/SocialAuthenticate.php | 2 +- src/Controller/Traits/LoginTrait.php | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 331f5b2c0..a6a612e07 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -420,7 +420,7 @@ public function getUser(ServerRequest $request) 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; } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 19e0982a5..543199f59 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -188,8 +188,13 @@ public function login() if (!$this->request->is('post') && !$socialLogin) { if ($this->Auth->user()) { - $msg = __d('CakeDC/Users', 'You are already logged in'); - $this->Flash->error($msg); + 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); From 3ed722e8a212fc18050197f8d4d0d91e3686f93c Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 8 Dec 2017 14:51:38 +0100 Subject: [PATCH 0738/1476] Fix flash messages for social email --- src/Auth/SocialAuthenticate.php | 1 + src/Controller/Traits/LoginTrait.php | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index a6a612e07..730d51bbb 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -400,6 +400,7 @@ public function getUser(ServerRequest $request) $provider = $this->_getProviderName($request); try { $user = $this->_mapUser($provider, $rawData); + $this->_getController()->Auth->setConfig('authError', false); } catch (MissingProviderException $ex) { $request->getSession()->delete(Configure::read('Users.Key.Session.social')); throw $ex; diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 543199f59..3a94cbf36 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -106,7 +106,7 @@ public function failedSocialLogin($exception, $data, $flash = false) if (isset($exception)) { if ($exception instanceof MissingEmailException) { if ($flash) { - $this->Flash->success(__d('CakeDC/Users', 'Please enter your email')); + $this->Flash->success(__d('CakeDC/Users', 'Please enter your email'), ['clear' => true]); } $this->request->getSession()->write(Configure::read('Users.Key.Session.social'), $data); @@ -129,10 +129,8 @@ public function failedSocialLogin($exception, $data, $flash = false) } } if ($flash) { - $this->Auth->setConfig('authError', $msg); - $this->Auth->setConfig('flash.params', ['class' => 'success']); $this->request->getSession()->delete(Configure::read('Users.Key.Session.social')); - $this->Flash->success(__d('CakeDC/Users', $msg)); + $this->Flash->success(__d('CakeDC/Users', $msg), ['clear' => true]); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); From 49694d64fb05b036ae4fde0c417e9523fc9c107a Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 12 Dec 2017 11:47:39 +0100 Subject: [PATCH 0739/1476] Add link social for twitter --- config/permissions.php | 2 +- config/users.php | 1 + src/Controller/Traits/LinkSocialTrait.php | 101 +++++++++++++++++----- src/Controller/Traits/LoginTrait.php | 2 +- 4 files changed, 82 insertions(+), 24 deletions(-) diff --git a/config/permissions.php b/config/permissions.php index 4a9efbfde..b73559e05 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -65,7 +65,7 @@ 'role' => '*', 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => ['profile', 'logout'], + 'action' => ['profile', 'logout', 'linkSocial', 'callbackLinkSocial'], ], [ 'role' => '*', diff --git a/config/users.php b/config/users.php index 52bba11e8..b68b7d351 100644 --- a/config/users.php +++ b/config/users.php @@ -159,6 +159,7 @@ ] ], 'twitter' => [ + //'className' => 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 128922243..15c565850 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -13,6 +13,8 @@ use Cake\Core\Configure; use Cake\Network\Exception\NotFoundException; +use CakeDC\Users\Model\Table\SocialAccountsTable; +use League\OAuth1\Client\Server\Twitter; use League\OAuth2\Client\Provider\AbstractProvider; /** @@ -22,7 +24,7 @@ trait LinkSocialTrait { /** - * Ação para inicial processo de link e autenticação social (facebook, google) + * Init link and auth process against provider * * @param string $alias of the provider. * @@ -33,15 +35,20 @@ public function linkSocial($alias = null) { $provider = $this->_getSocialProvider($alias); - $authUrl = $provider->getAuthorizationUrl(); - $this->request->session()->write('SocialLink.oauth2state', $provider->getState()); - + $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); } /** - * Ação para receber o retorno do provedor (facebook, google) referente ao - * processo de link e autenticação social + * Callback to get user information from provider * * @param string $alias of the provider. * @@ -50,21 +57,60 @@ public function linkSocial($alias = null) */ public function callbackLinkSocial($alias = null) { - $provider = $this->_getSocialProvider($alias); $message = __d('CakeDC/Users', 'Could not associate account, please try again.'); - if (!$this->_validateCallbackSocialLink()) { - $this->Flash->error($message); + $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; + } - return $this->redirect(['action' => 'profile']); - } + } + } else { + if (!$this->_validateCallbackSocialLink()) { + $this->Flash->error($message); - $code = $this->request->getQuery('code'); + return $this->redirect(['action' => 'profile']); + } + $code = $this->request->getQuery('code'); + try { + $token = $provider->getAccessToken('authorization_code', compact('code')); - try { - $token = $provider->getAccessToken('authorization_code', compact('code')); + $data = compact('token') + $provider->getResourceOwner($token)->toArray(); + } catch (\Exception $e) { + $error = $e; + } - $data = compact('token') + $provider->getResourceOwner($token)->toArray(); + } + + 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); + } + try { $data = $this->_mapSocialUser($alias, $data); $user = $this->getUsersTable()->get($this->Auth->user('id')); @@ -78,9 +124,9 @@ public function callbackLinkSocial($alias = null) } } catch (\Exception $e) { $log = sprintf( - "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", - $e->getMessage(), - $e + "Error retrieving the authorized user's profile data. Error message: %s %s", + $e->getMessage(), + $e ); $this->log($log); @@ -116,7 +162,7 @@ protected function _mapSocialUser($alias, $data) * @param string $alias of the provider. * * @throws \Cake\Network\Exception\NotFoundException - * @return \League\OAuth2\Client\Provider\AbstractProvider + * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter */ protected function _getSocialProvider($alias) { @@ -129,19 +175,29 @@ protected function _getSocialProvider($alias) throw new NotFoundException; } - return $this->_createSocialProvider($config); + return $this->_createSocialProvider($config, ucfirst($alias)); } /** * Instantiates provider object. * * @param array $config for social provider. + * @param string $alias provider alias * * @throws \Cake\Network\Exception\NotFoundException - * @return \League\OAuth2\Client\Provider\AbstractProvider + * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter */ - protected function _createSocialProvider($config) + 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']; @@ -160,6 +216,7 @@ protected function _createSocialProvider($config) 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')); diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 3a94cbf36..2b6518a07 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -44,7 +44,7 @@ public function twitterLogin() $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.redirectUri'), + 'callback_uri' => Configure::read('OAuth.providers.twitter.options.redirectUri'), ]); $oauthToken = $this->request->getQuery('oauth_token'); $oauthVerifier = $this->request->getQuery('oauth_verifier'); From 64306ed2d6022f58effd517ff90d4bd2a5e31f91 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 12 Dec 2017 12:08:24 +0100 Subject: [PATCH 0740/1476] Fix phpcs --- src/Auth/SocialAuthenticate.php | 5 ++++- src/Controller/Traits/LinkSocialTrait.php | 16 ++++++++-------- .../Controller/Traits/LoginTraitTest.php | 8 -------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index 730d51bbb..b3d26cce8 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -400,7 +400,9 @@ public function getUser(ServerRequest $request) $provider = $this->_getProviderName($request); try { $user = $this->_mapUser($provider, $rawData); - $this->_getController()->Auth->setConfig('authError', false); + 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; @@ -422,6 +424,7 @@ public function getUser(ServerRequest $request) $request->getSession()->delete(Configure::read('Users.Key.Session.social')); } $request->getSession()->write('Users.successSocialLogin', true); + return $result; } diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 15c565850..490c1e127 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -11,11 +11,10 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; use Cake\Network\Exception\NotFoundException; -use CakeDC\Users\Model\Table\SocialAccountsTable; use League\OAuth1\Client\Server\Twitter; -use League\OAuth2\Client\Provider\AbstractProvider; /** * Ações para "linkar" contas sociais @@ -44,6 +43,7 @@ public function linkSocial($alias = null) if (empty($temporaryCredentials)) { $this->request->session()->write('SocialLink.oauth2state', $provider->getState()); } + return $this->redirect($authUrl); } @@ -80,7 +80,6 @@ public function callbackLinkSocial($alias = null) } catch (\Exception $e) { $error = $e; } - } } else { if (!$this->_validateCallbackSocialLink()) { @@ -96,7 +95,6 @@ public function callbackLinkSocial($alias = null) } catch (\Exception $e) { $error = $e; } - } if (!empty($error) || empty($data)) { @@ -108,6 +106,8 @@ public function callbackLinkSocial($alias = null) $this->log($log); $this->Flash->error($message); + + return $this->redirect(['action' => 'profile']); } try { @@ -124,9 +124,9 @@ public function callbackLinkSocial($alias = null) } } catch (\Exception $e) { $log = sprintf( - "Error retrieving the authorized user's profile data. Error message: %s %s", - $e->getMessage(), - $e + "Error retrieving the authorized user's profile data. Error message: %s %s", + $e->getMessage(), + $e ); $this->log($log); @@ -195,8 +195,8 @@ protected function _createSocialProvider($config, $alias = null) 'secret' => Configure::read('OAuth.providers.twitter.options.clientSecret'), 'callback_uri' => Configure::read('OAuth.providers.twitter.options.callbackLinkSocialUri'), ]); - return $server; + return $server; } $class = $config['className']; $redirectUri = $config['options']['callbackLinkSocialUri']; diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 0550b2711..47a3d29c5 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -326,14 +326,6 @@ public function testFailedSocialUserNotActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Trait->Auth->expects($this->at(0)) - ->method('setConfig') - ->with('authError', 'Your user has not been validated yet. Please check your inbox for instructions'); - - $this->Trait->Auth->expects($this->at(1)) - ->method('setConfig') - ->with('flash.params', ['class' => 'success']); - $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } From 0a2dfc60ea84a956a5f40d46ca36c3e9e8b0a09a Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 12 Dec 2017 12:13:42 +0100 Subject: [PATCH 0741/1476] Remove out commented classname --- config/users.php | 1 - 1 file changed, 1 deletion(-) diff --git a/config/users.php b/config/users.php index b68b7d351..52bba11e8 100644 --- a/config/users.php +++ b/config/users.php @@ -159,7 +159,6 @@ ] ], 'twitter' => [ - //'className' => 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', From c71e4f4c99d9d1c0daf9066d9db968e71bebd298 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 12 Dec 2017 12:59:45 +0100 Subject: [PATCH 0742/1476] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a8348d5da..7e964f94a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,7 +42,7 @@ script: - sh -c "if [ '$DEFAULT' = '1' ]; then ./vendor/bin/phpunit --stderr; fi" - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p -n --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then ./vendor/bin/phpunit --stderr --coverage-clover build/logs/clover.xml; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then php vendor/bin/coveralls -c .coveralls.yml -v; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then php ./vendor/bin/coveralls -c .coveralls.yml -v; fi" notifications: email: false From bceefe9f8d11bd4eb0136bc4b33101a5693084da Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 12 Dec 2017 13:16:16 +0100 Subject: [PATCH 0743/1476] Add codecov --- .travis.yml | 11 ++++++----- README.md | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a8348d5da..574d41f68 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,11 +20,11 @@ matrix: fast_finish: true include: - - php: 5.6 + - php: 7.0 env: PHPCS=1 DEFAULT=0 - - php: 5.6 - env: COVERALLS=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' + - php: 7.0 + env: CODECOVERAGE=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' before_script: - composer self-update @@ -41,8 +41,9 @@ before_script: script: - sh -c "if [ '$DEFAULT' = '1' ]; then ./vendor/bin/phpunit --stderr; fi" - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p -n --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then ./vendor/bin/phpunit --stderr --coverage-clover build/logs/clover.xml; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then php vendor/bin/coveralls -c .coveralls.yml -v; fi" + - sh -c "if [ '$CODECOVERAGE' = '1' ]; then phpunit --coverage-clover=clover.xml || true; fi" + - sh -c "if [ '$CODECOVERAGE' = '1' ]; then wget -O codecov.sh https://codecov.io/bash; fi" + - sh -c "if [ '$CODECOVERAGE' = '1' ]; then bash codecov.sh; fi" notifications: email: false diff --git a/README.md b/README.md index 4624e27cf..262201ce4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ CakeDC Users Plugin =================== -[![Bake Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/CakeDC/users) +[![Build Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/CakeDC/users) +[![Coverage Status](https://img.shields.io/codecov/c/gh/CakeDC/users.svg?style=flat-square)](https://codecov.io/gh/CakeDC/users) [![Downloads](https://poser.pugx.org/CakeDC/users/d/total.png)](https://packagist.org/packages/CakeDC/users) [![Latest Version](https://poser.pugx.org/CakeDC/users/v/stable.png)](https://packagist.org/packages/CakeDC/users) [![License](https://poser.pugx.org/CakeDC/users/license.svg)](https://packagist.org/packages/CakeDC/users) From ad54a75079d96897ca2eb925b764fa00d4705f1a Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 12 Dec 2017 13:48:14 +0100 Subject: [PATCH 0744/1476] Improve docs --- Docs/Documentation/Configuration.md | 7 +++++++ Docs/Documentation/SocialAuthenticate.md | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index c86f89318..db4f2887f 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -39,6 +39,13 @@ Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRE Or use the config override option when loading the plugin (see above) +Additionally you will see you can configure two more keys for each provider: + +* linkSocialUri (default: /link-social/**provider**), +* callbackLinkSocialUri(default: /callback-link-social/**provider**) + +Those keys are needed to link an existing user account to a third-party account. **Remember to add the callback to your thrid-party app** + Configuration for reCaptcha --------------------- ``` diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index d251c33ca..937039366 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -1,6 +1,17 @@ SocialAuthenticate ============= +We currently support the following providers to perform login as well as to link an existing account: + +* Facebook +* Twitter +* Google +* LinkedIn +* Instagram +* Amazon + +Please [contact us](https://cakedc.com/contact) if you need to support another provider. + Setup --------------------- From 5196df4e26fc46f4e615ddf40f3bdbef8366a5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 12 Dec 2017 13:34:23 +0000 Subject: [PATCH 0745/1476] Update CHANGELOG.md --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b16c8ad66..5949db7bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ Changelog Releases for CakePHP 3 ------------- +* 6.0.0 + * Removed deprecations and orWhere usage + * Amazon login implemented + * Fixed issues with login via twitter + * Updated Facebook Graph version to 2.8 + * Fixed flash error messages on logic + * Added link social account feature for twitter + * Switched to codecov + * 5.2.0 * Compatible with 3.5, deprecations will be removed in next major version of the plugin * Username is now custom in SocialBehavior From cb391c9b4cabcec00f2bffc8940d527daf829b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 12 Dec 2017 13:34:44 +0000 Subject: [PATCH 0746/1476] Update .semver --- .semver | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.semver b/.semver index e9855cbaa..f83d94eff 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- -:major: 5 -:minor: 2 +:major: 6 +:minor: 0 :patch: 0 :special: '' From 3fe8d0a1253d4ef8a803710095dfdacc30c24793 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 12 Dec 2017 14:35:40 +0100 Subject: [PATCH 0747/1476] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 262201ce4..4e9741ea6 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^3.4 | [master](https://github.com/cakedc/users/tree/master) | 5.2.0 | stable | +| ^3.5 | [master](https://github.com/cakedc/users/tree/master) | 6.0.0 | stable | | ^3.5 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 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 | From 2d5fe45019cd8c68b5368ee801d0ca06ca417e8c Mon Sep 17 00:00:00 2001 From: Livia Scapin Date: Fri, 15 Dec 2017 14:43:41 +0100 Subject: [PATCH 0748/1476] Remove unnecessary translation strings --- src/Controller/Traits/LoginTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 2b6518a07..6e7c7b509 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -130,7 +130,7 @@ public function failedSocialLogin($exception, $data, $flash = false) } if ($flash) { $this->request->getSession()->delete(Configure::read('Users.Key.Session.social')); - $this->Flash->success(__d('CakeDC/Users', $msg), ['clear' => true]); + $this->Flash->success($msg, ['clear' => true]); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); @@ -247,7 +247,7 @@ public function verify() $query->execute(); } catch (\Exception $e) { $this->request->getSession()->destroy(); - $message = __d('CakeDC/Users', $e->getMessage()); + $message = $e->getMessage(); $this->Flash->error($message, 'default', [], 'auth'); return $this->redirect(Configure::read('Auth.loginAction')); From 6a27a2d5f3e9979260ee864a861cd114413f6bc2 Mon Sep 17 00:00:00 2001 From: Livia Scapin Date: Fri, 15 Dec 2017 14:44:43 +0100 Subject: [PATCH 0749/1476] Remove unnecessary translation strings --- src/Controller/Traits/PasswordManagementTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index a07354a35..653498906 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -81,7 +81,7 @@ public function changePassword() } catch (UserNotFoundException $exception) { $this->Flash->error(__d('CakeDC/Users', 'User was not found')); } catch (WrongPasswordException $wpe) { - $this->Flash->error(__d('CakeDC/Users', '{0}', $wpe->getMessage())); + $this->Flash->error($wpe->getMessage()); } catch (Exception $exception) { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); $this->log($exception->getMessage()); @@ -164,7 +164,7 @@ public function resetGoogleAuthenticator($id = null) $message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset'); $this->Flash->success($message, 'default'); } catch (\Exception $e) { - $message = __d('CakeDC/Users', $e->getMessage()); + $message = $e->getMessage(); $this->Flash->error($message, 'default'); } } From ccc357eb2ba97be9507a029f1f56cdfeae20991e Mon Sep 17 00:00:00 2001 From: Livia Scapin Date: Fri, 15 Dec 2017 14:52:51 +0100 Subject: [PATCH 0750/1476] Remove unnecessary translation strings --- src/View/Helper/UserHelper.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 56cfec3b4..cd03eeb0e 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -45,20 +45,16 @@ public function socialLogin($name, $options = []) $options['label'] = __d('CakeDC/Users', 'Sign in with'); } $icon = $this->Html->tag('i', '', [ - 'class' => __d('CakeDC/Users', 'fa fa-{0}', strtolower($name)), + 'class' => 'fa fa-' . strtolower($name), ]); if (isset($options['title'])) { $providerTitle = $options['title']; } else { - $providerTitle = __d('CakeDC/Users', '{0} {1}', Hash::get($options, 'label'), Inflector::camelize($name)); + $providerTitle = Hash::get($options, 'label') . ' ' . Inflector::camelize($name); } - $providerClass = __d( - 'CakeDC/Users', - 'btn btn-social btn-{0} ' . Hash::get($options, 'class') ?: '', - strtolower($name) - ); + $providerClass = 'btn btn-social btn-' . strtolower($name) . ' ' . Hash::get($options, 'class') ?: ''; return $this->Html->link($icon . $providerTitle, "/auth/$name", [ 'escape' => false, 'class' => $providerClass @@ -202,11 +198,7 @@ public function isAuthorized($url = null) */ public function socialConnectLink($name, $provider, $isConnected = false) { - $linkClass = __d( - 'CakeDC/Users', - 'btn btn-social btn-{0}' . Hash::get($provider['options'], 'class') ?: '', - strtolower($name) - ); + $linkClass = 'btn btn-social btn-' . strtolower($name) . Hash::get($provider['options'], 'class') ?: ''; if ($isConnected) { $title = __d('CakeDC/Users', 'Connected with {0}', Inflector::camelize($name)); From 3fe503f5a51397ced121680c6b2e4f570b39e56e Mon Sep 17 00:00:00 2001 From: Artur Mamedov Date: Fri, 12 Jan 2018 17:07:00 +0100 Subject: [PATCH 0751/1476] it_IT - Added Italian translations to Locale --- src/Locale/it_IT/Users.mo | Bin 0 -> 15385 bytes src/Locale/it_IT/Users.po | 783 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 783 insertions(+) create mode 100644 src/Locale/it_IT/Users.mo create mode 100644 src/Locale/it_IT/Users.po diff --git a/src/Locale/it_IT/Users.mo b/src/Locale/it_IT/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..f242989f460433ffb9e21dea5b545ccbdf20e4d9 GIT binary patch literal 15385 zcmb`NdypkneaDZ0xUQli$je8XM;y?d+1cf>ILl*~*7q(XRh`P~)8AaR+!B_xnM*nj1jzaf`pd9Xx{jyTKQN_ko)C&p|Eq zo8a-_o)e{yvWn zgPQ*l@G$T%K=J!^@U`G$pw@ThF~)2ICqd0~Gk7X^2e=;mGAKTN0*-@6!ld}#|zX4y&{m($@^*I=q-ai}M4Nig=g13QJf{%f(0AI#pPXL=B zESVd@lfm13`$M3{{U*qt`7vLzr^9(^1l$O|47?f?UvC5XGw38G4K7|f~v319?n0QGz? zxDI?RxEZ_^6#riX#qVRF-v1RSxjh?WksX}{%5Ki%OZ{Hu@eQE#@o^B-H}`{**Q22H z@*Qv#`~j$SK9As|^_&jkT4vJU?+3N6>p<~yGpPRW0cBVBg5v)h{{C@L{`3SWy=jrC z(i{bD0Y|`%-~uRnxYOe|Kv*$PfQZVR#NhJlP2g4F>%raN--4R|G@M8JJP*`-J3#Sw z8Mqak0S^b?4@ypVfYR^BK>5>`!8bk4m>+=}XC5Qa`mY0}pIbob<8JUQ@G&p~pMf#R z-cASAe?6%6T?&f-CMbEo#p4G+_5Tzo`9BECj=lnFo}Yu7e=SUjuVeX=+%|)X8<&9c zl0 z2VM%^pLDi z5_~a;D9mZ#0(coX4L$_wy)^_YjdL6*KRFc?-y1=#|6=f&;8oz+;4HWX{2-`tKMGV7?B-5T{C^aDKKKBL%FLsn^zt+R{6z>~_b&%$z$-!V|7lS1 z{9#aW;^(0B^{jK8J}w0bm1YKnHB*9G|2^RIz`q7H@ApBi>zDri$W5;QiQuuc?*g@s zSy25Cg7V*6!Q;StLGkklcs%$uFap01YM#T+b@#`BlJi-h*1Z{&Jzol50cN1q^Jm~T z@PEKb@S<0^b-W#vd_MtR4gMAQd*BGdUj*+5HUCQ)MD}3xvw>Wz>-=Q}VT0;M;}ZVwbeZ-X*uH*_VW&u1J|-{M{Ckk5w?BD6aEqHmb<_-XLt z{`z$A1CVrkpKoh`H$z83uY)dx^eG(-e4oV~A~ToyR{7MFzn0x%R_5K%vwYj7;O+ie z{{IQ+R)4<_yv|?05PU1N5qha_lfS(R`eSI>w|xx!BSI5!wama~kv-NcMCpq_}YebR!f# zo4EKKbZ=+?KUKTVxxO0u0(4}pz0I}!xR3QGwfCS6&>Nt;p<|#FIvctk(&v-VUAo}&5$GV4KqHVo z&xJk;y#vzzI{bM(4GTk!hjV`u)P!CM9S?1X^tl+Cv{%Ml4qoK1j|P{ZY3P7&`!J}O za2zxPwV)S4Z-VwiXF&Sgudl6prlK-CkaWz}MkDE#(ah!3Q6uX#(=yFE#f56ldYv+g zTX_;Um!rkFl{VutX;x2o-fBjjtc+%p6&~xs978nu&ZBZ6iRRPAq~m6dV%n2-oVLcQ z@v0f3q6be!G1qIgmU(PBvbYEXyc!kVq>;|0ji^^7dH>0B*2|;VGro}I$iHl+> z%bVf8J9IA@=UFSUyc{B>$*eP%=IyBe7K)WVCwqCGFnjd?NyKJb5+nGP1-{KPNf*nj z6^y?=WY+B%l+l-y-*&0o*zd}+lIzo=EPUgDQRPViV=FzWwad=B13fV}iMtcG6aTKd z4_cLFVM0fo)%4oO7aF=$tOH%vFRMSkkSIpF$we42gIS{3V zb%#cVKpU;)sF@bsR=k`v*G1h{5*G;`)?K#!=dxBSTavNF%_iIz5r$;#cPW{TX7g-G zMkV&9I@U3QUH9+1-KdCL<+>>LS5dnM%Q$0PMw+gSHlBS>G@F)1bo!YaquJ#$DbB$9 zJM+~bc`_My%f>=nwb-B__gs${y~B8y8tUW492l$gS^06*-?zxC%H?iiri!AM6j7Nk zO8{6s9;x*&rR9PX!qCJ!wHT`ldu3Iz6NwvrX#fdoCuS7+uvNG_nI@O=cYSBQ((Fo$ zLbHwp6B*IWS=R;`IelDpX=JTlyQ8tyrHp5BEleX?T1dHSEF_Hs8Yx@qFv~*PjfeyFaMe zl{E=_`0Q>XkQQezD#ul8xN)|v7KMcVog}pzmx+7jLYAioYsTr~B0-`k&7Kfj!UgM9 z5OUExZndn76;;21$6B|WvHx~`v+zUpUtWj{?3T?TOfs+oghBj}&XeK-#S`$XjIjW# z4%=e46&VGBB^>t>XIEXnqDZkqAtTcsWA=E*ls291{omeyYK{$eRd}^tKd?1PM}e=W zHg4@rLLSx^R|YW_h71p67l$-ToN})S@3w+iwa3r{=|cNr5cA+{c8zwt)!L;nry1M# zHw;s;s2pOrUkE- zeLCbNJeVimFv#AdrERnydG;plq&Z!(8Le_WT)jABPSu6BgOyhwC4XDm#SbLR_1h>}2{opV? zy;ECeo?O>Ub01l@cGJs}2|G<2Hd31DbiNZd2s7=nI3MY&ZO8gkGW>KEAr6jF znCaeZn?z+=Nu7--?8-@VqSi1lkbkP2*`|pzc5gt*sDTw(BdYd%0(shDQ}#QE?X@mi zQZf(}oLpb#@K2u*_1$hWmuGDo(OnAtctG7chjo^E(vIzAYV9$5AGamA=&$}K~`_k|`)q~KVMY1t-9;z9% zak;+zj<#Rl#mEcSRvB$#TM^cw9#7{4h1&K3D7@A#H{;7!AAjZfsOx4Gmf{j#WU&ne4 zao;5#){rcRc?iEYuiK|Aij3Q0i0EN?RnQxJJfQGZ`c%yWYxd(f_jgnJ6R1DOj2`6PSxH_Mpt`OP2%R1y&~Trm^ycQG~jOb4Vy)4 zBD>#*_xx$BYA0e>A%x-6jyv6y)exTHGHp>hAp9uCPsRt5ZIh7(DF`h+<=^|$WXW8a zv>I7ES!WgdN)Es=+j5v1Gf;v_Up>LlN6IL1M&fcZuQ6?-oP!U{ae|7{Ihppgt^*9t z#jPR<14u+XwITG7V2RXAG^3;?>$q1Ih+ITHx3j}aJq@kmIcx?V?SV`8oGe@d<6iYO z0;aC&5n^eC(d$FX@U>!{OL$!M4O_Vus)MC_SgBz!%DYU*9wKU|`^t6u5#7$<^UUBz z&S`aMB;n{g#Bx$r1Jry!?aXG^TLq_`qRe}~GGhm}YyE#2Zno@1(5Posmoi{87o%KV znhyJ=;mp67X1&7ncPSrU+<}V9O7rBfuT@RXCdaCG#ttOQMq_FUo%=z%9v2NOnOil4 zXG21)nWgPUTKT%9QI1YENB83ZXmMh|Bi8P@d}ee~)fXO(Qf=XQwsCyJrqK->M>lSW zHf)?2-|+JB4ddf<9No(*HAKJPxufG7=o)R!(xk=u94W3UX0ZFs9R%aWn zymo44?XIa^+xv^#FgCt+lDEj%MiuKPq7n_Qr}mL{HY@qd*~-q}H?w2(+7#e)p;u$Z@wgK` zdQVi8$TFgkSERG{z#qEkBr)PWNE6sPDPpFekx?+?9o)V(;zE)FTFYnjgvJg*vS0G7 z%_x*&JqsA!V584ttk`BJV4nH;lsa%4?Xw*Cd#aHz)#+u68BDWYR|(a^3u;`cCZO6>hVE&Sr1)a$d+4{2K|`1ERL2(C9+5Ba>wFjH*dyCgb*Os;7HGouX=K^^d&1 zn*@~ivX)cKO2V9^1Vfpn{-)eB3eW|B`@}1nb*D9yhVv|DWPmE$Ud(D%yLlCgmYHiU>wfojQ{LGF|0@n$})KELk zY{<09g6m`7#D)e8);)5$0IKL_k-c^m)kHVM*4=FV?rSoQUD3`~Qgza!ny=7hyAqD4 z6KPH1)bg~L;_6X5W7m;dYz|VE)G1g$8#5L&7cc5<8DFedi)6lMT_(lrsdF97*y(XZ z93@m&RcTe|ue-1f0$6=0sY)QOZ7ix9n+Y2^#UpA2Brh;Q3ft?P-?CEWVVl6ys8IT)bHy|f}ClMgb(zHw{DN#^DVo;{h6l;MiBR7I^6eYgo>Win%@LA?QYR^{3FD|cBjt3Dft zGKq0_b|vXxg|=3iZR0%rFrp-_MFh{fE_`$5PML^Gb|==*9CvH|>_J<>!xn3sY#JJY z+puoC>Qhd^YT78##wujc&C{erpfaY`h!?Snw>uR4kp}keinmU%Va^pRxXOlQa#p^z zdHnId@@^MmcH20*&wDdBwLqk2{afc%#=T%;nsYhVAY- zn+va0L)rfH@ue>-pn)-4Za@ygL*r3J7+7xiyH&B; zOts{7MEX6xj%{OnxA*9SVNY7@kt-Qr#6B3CoiT@6ThTs9yK-o@{$nE#=IvG~uGReKcd*Xg-rjWE!90+fE6SkGEE{1?G zE9onQ4mb^~FIVXqgx#O461B}4YWa1I&6-E99P55V-<5L7-_Sj=Iox0e*=5Bz*}U0n zGu0{#hSP-GkX-ar;T(aw$XBp7Np0oIx%-(yKR7DbRmz=qHFTRn*f{bePdy=3a_( znX2%<`#NXtS(zv8Hql1;BR|gDI2K04h(p!AsfuMK*VtT~b3jVOiOc=_n$iN~Avgrb z%2ji4S7EOk_@FscW$8!09N%HHM}SYlW5j3m<9*Pw%S?RkA{O(sM|k2lZI@hFX?T6t zTKu_njD`All~h$OOA2NWW5Z6gbHtCK-kNQNH=g1G`-i2F%T#0bk1qVzgQR5lxK$W6 z1MT(&BH|VL4TaN#jh+mg&Ca&cd9tKDb?J7;OgG|Y(jiQ`@`20Kt(z1)A+K6ZH&UKW z8^oEm0|hBXUcF~WMDuRcLqf0&Iv$?73Un}9XCUmI{ICd{Zkl>uSGMT0Go-Zvg@lY4 zmK6qV6709hF;^6z&aVxp)X5^Kc|rfu#J_Nm3(WO8&gO6;(y*A{o#OBlfQlxEyvt(z z5vzU}ttF<2&LuL6X;nH$?5b^HvW+SJBg-YsAtrg#J>*pMWSl9KbHZtRXv|gj5$^yY zd`$#Ds|Qx!M-H;8>xK8!=}A|S!sND)Q)X^&@QwWIk(~_VR{LvKm;i70oxQWHz;sZ# z=cy|CR~ODS`?ZLDB#Q3;2M&#uD#Y32zn5}gSic=92x$#ud%mxPT%zj6$xrh`#BUbM>@Jmw7SYGFx^TX+1niKP35f}KnonXkfy zB(i6nVqN|0?(#}675&z*)Bj=-CKw74)@gO1Q1wM_Sed^T8(c-Pty;G1wzeJWjfh{Y zwVS$=0bxOBc)QxcQrp;}J78cStjX8gH3^Dv`evudIIvZ$QPZyPr6IEU)W5+$-)VL< zjWNKC{&f+f?of5IOKi)9*#}^kDs9`=MN{#ysG3t2g05%5PwqJR?JV#E6#s?f%!)!R z83+Xy2{tRymQJoz7}z}Wo`Pv=e)}&V{#PW1G5ij~;Z>!sp;8lk`F}Qx`5mO6W>oD@ m=C_dT6qUm{rLu?q<|5YnW}sbn#TP0O(H}e1QE5=O=6?Zk(R~g8 literal 0 HcmV?d00001 diff --git a/src/Locale/it_IT/Users.po b/src/Locale/it_IT/Users.po new file mode 100644 index 000000000..80176186a --- /dev/null +++ b/src/Locale/it_IT/Users.po @@ -0,0 +1,783 @@ +# LANGUAGE translation of CakePHP Application +# Copyright 2010 - 2016, Cake Development Corporation (http://cakedc.com) +# +msgid "" +msgstr "" +"Project-Id-Version: CakeDC Users\n" +"POT-Creation-Date: 2017-12-21 12:01+0100\n" +"PO-Revision-Date: 2018-01-12 17:06+0100\n" +"Last-Translator: Silvia Ghignone \n" +"Language-Team: CakeDC \n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 2.0.5\n" + +#: Auth/ApiKeyAuthenticate.php:73 +msgid "Type {0} is not valid" +msgstr "Il tipo {0} non è valido" + +#: Auth/ApiKeyAuthenticate.php:77 +msgid "Type {0} has no associated callable" +msgstr "Il tipo {0} non ha nessuna funzione di chiamata associabile" + +#: Auth/ApiKeyAuthenticate.php:86 +msgid "SSL is required for ApiKey Authentication" +msgstr "SSL è richiesto per ApiKey Authentication" + +#: Auth/SimpleRbacAuthorize.php:142 +msgid "Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "File di configurazione mancante: \"config/{0}.php\". Utilizzo dei permessi di default" + +#: Auth/SocialAuthenticate.php:432 +msgid "Provider cannot be empty" +msgstr "Il campo Provider non può essere vuoto" + +#: Auth/Rules/AbstractRule.php:78 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a default table from the " +"request" +msgstr "" +"L'alias della tabella è vuoto, per favore definire un alias tabella, non potremmo estrarre una tabella " +"di default dalla richiesta" + +#: Auth/Rules/Owner.php:67;70 +msgid "Missing column {0} in table {1} while checking ownership permissions for user {2}" +msgstr "" +"Colonna {0} mancante nella tabella {1} durante la verifica dei \"\"permessi di proprietà per l'utente " +"{2}" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Account convalidato con successo" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Non è stato possibile convalidare l'account" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Token e/o account social non valido" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Account Social già attivo" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Non è stato possibile convalidare l'Account Social" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Email inviata con successo" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "Impossibile inviare l'email" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Account non valido" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Non è stato possibile reinviare l'email" + +#: Controller/Component/RememberMeComponent.php:69 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "App salt non valido. App salt deve essere almeno lungo 256 bits (32 bytes)" + +#: Controller/Component/UsersAuthComponent.php:178 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "Non è possibile abilitare il workflow di validazione email se use_email è false" + +#: Controller/Traits/LoginTrait.php:96 +msgid "Issues trying to log in with your social account" +msgstr "Si sono verificati dei problemi nel tentativo di effettuare il log in col tuo account social" + +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Per favore inseirsci la tua email" + +#: Controller/Traits/LoginTrait.php:108 +msgid "Your user has not been validated yet. Please check your inbox for instructions" +msgstr "" +"Il vostro utente non è ancora stato convalidato. Per favore verifica le tue email in arrivoper " +"ottenere le istruzioni" + +#: Controller/Traits/LoginTrait.php:110 +msgid "Your social account has not been validated yet. Please check your inbox for instructions" +msgstr "" +"Il tuo account social non è stato ancora convalidato. Per favore verifica la tuacasella di posta " +"elettronica per maggiori informazioni" + +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +msgid "Invalid reCaptcha" +msgstr "reCaptcha non valida" + +#: Controller/Traits/LoginTrait.php:171 +msgid "You are already logged in" +msgstr "E' già  stato effettuato il log in" + +#: Controller/Traits/LoginTrait.php:217 +msgid "Username or password is incorrect" +msgstr "Username o password non corretti" + +#: Controller/Traits/LoginTrait.php:238 +msgid "You've successfully logged out" +msgstr "Log out effettuato con successo" + +#: Controller/Traits/PasswordManagementTrait.php:47;76 Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "Utente non trovato" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +msgid "Password could not be changed" +msgstr "Non è stato possibile cambiare la password" + +#: Controller/Traits/PasswordManagementTrait.php:68 +msgid "Password has been changed successfully" +msgstr "Password modificata con successo" + +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:120 +msgid "Please check your email to continue with password reset process" +msgstr "Controllare la propria email per continuare col processo di ripristino della password" + +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +msgid "The password token could not be generated. Please try again" +msgstr "Non è stato possibile generare il token della password. Per favore riprovare" + +#: Controller/Traits/PasswordManagementTrait.php:129 Controller/Traits/UserValidationTrait.php:100 +msgid "User {0} was not found" +msgstr "Utente {0} non trovato" + +#: Controller/Traits/PasswordManagementTrait.php:131 +msgid "The user is not active" +msgstr "Utente non attivo" + +#: Controller/Traits/PasswordManagementTrait.php:133 Controller/Traits/UserValidationTrait.php:95;104 +msgid "Token could not be reset" +msgstr "Non è stato possibile ripristinare il token" + +#: Controller/Traits/ProfileTrait.php:53 +msgid "Not authorized, please login first" +msgstr "Non autorizzato, per favore effettuare prima il login" + +#: Controller/Traits/RegisterTrait.php:42 +msgid "You must log out to register a new user account" +msgstr "Per registrare un nuovo account utente, effettuare prima il log out" + +#: Controller/Traits/RegisterTrait.php:88 +msgid "The user could not be saved" +msgstr "Registrazione utente non riuscita" + +#: Controller/Traits/RegisterTrait.php:122 +msgid "You have registered successfully, please log in" +msgstr "Registrazione avvenuta con successo, per favore effettuare il log in" + +#: Controller/Traits/RegisterTrait.php:124 +msgid "Please validate your account before log in" +msgstr "Per favore convalida il tuo account prima di effettuare il log in" + +#: Controller/Traits/SimpleCrudTrait.php:76;106 +msgid "The {0} has been saved" +msgstr "{0} è stato salvato" + +#: Controller/Traits/SimpleCrudTrait.php:80;110 +msgid "The {0} could not be saved" +msgstr "Non è stato possibile salvare {0}" + +#: Controller/Traits/SimpleCrudTrait.php:130 +msgid "The {0} has been deleted" +msgstr "{0} è stato cancellato" + +#: Controller/Traits/SimpleCrudTrait.php:132 +msgid "The {0} could not be deleted" +msgstr "Non è stato possibile cancellare {0}" + +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "Non è stato possibile convalidare la reCaptcha" + +#: Controller/Traits/UserValidationTrait.php:42 +msgid "User account validated successfully" +msgstr "Account utente convalidato con successo" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account could not be validated" +msgstr "Non è stato possibile convalidare l'account utente" + +#: Controller/Traits/UserValidationTrait.php:47 +msgid "User already active" +msgstr "Utente già attivo" + +#: Controller/Traits/UserValidationTrait.php:53 +msgid "Reset password token was validated successfully" +msgstr "Il token per il ripristino password è stato convalidato con successo" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "Non è stato possibile convalidare il token per il ripristino della password" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Invalid validation type" +msgstr "Tipo di validazione non valido" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token or user account already validated" +msgstr "Toke non valido o account utente già convalidato" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Token già scaduto" + +#: Controller/Traits/UserValidationTrait.php:93 +msgid "Token has been reset successfully. Please check your email." +msgstr "Il token è stato ripristinato con successo. Per favore verificare la propria email." + +#: Controller/Traits/UserValidationTrait.php:102 +msgid "User {0} is already active" +msgstr "L'Utente {0} è già attivo" + +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Il tuo link per convalidare l'account" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0}Ecco il tuo link per ripristinare la password" + +#: Mailer/UsersMailer.php:78 +msgid "{0}Your social account validation link" +msgstr "{0}Ecco il tuo link per convalidare il tuo account social" + +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "La referenza non può essere nulla" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "La scadenza del Token non può essere vuota" + +#: Model/Behavior/PasswordBehavior.php:67;116 +msgid "User not found" +msgstr "Utente non trovato" + +#: Model/Behavior/PasswordBehavior.php:71 Model/Behavior/RegisterBehavior.php:111 +msgid "User account already validated" +msgstr "Account utente già convalidato" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "Utente non attivo" + +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "L'attuale password non corrisponde" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "Non puoi utilizzare la password attuale come nuova password" + +#: Model/Behavior/RegisterBehavior.php:89 +msgid "User not found for the given token and email." +msgstr "Utente non trovato per l'email ed il token forniti." + +#: Model/Behavior/RegisterBehavior.php:92 +msgid "Token has already expired user with no token" +msgstr "Il token è già scaduto utente senza token" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Account già convalidato" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "Account non trovato per l'email ed il token forniti." + +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "Impossibile effettuare il login per l'utente con referenza {0}" + +#: Model/Behavior/SocialBehavior.php:98 +msgid "Email not present" +msgstr "Email non presente" + +#: Model/Table/UsersTable.php:82 +msgid "Your password does not match your confirm password. Please try again" +msgstr "La password non corrisponde con quella inserita nella conferma password.Per favore riprova" + +#: Model/Table/UsersTable.php:175 +msgid "Username already exists" +msgstr "Username già esistente" + +#: Model/Table/UsersTable.php:181 +msgid "Email already exists" +msgstr "Email già esistente" + +#: Model/Table/UsersTable.php:214 +msgid "Missing 'username' in options data" +msgstr "'username' mancante nelle opzioni dati" + +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Utilità per Plugin CakeDC Users" + +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Attiva un utente specifico" + +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "Aggiunge un nuovo superadmin per scopi di test" + +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "Aggiungi un nuovo utente" + +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Cambia il ruolo per un utente specifico" + +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "Disattiva un utente specifico" + +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Cancella un utente specifico" + +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "Ripristina la password per email" + +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "Ripristina la password per tutti gli utenti" + +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "Ripristina la password per un utente specifico" + +#: Shell/UsersShell.php:98 +msgid "User added:" +msgstr "Utente aggiunto:" + +#: Shell/UsersShell.php:99;127 +msgid "Id: {0}" +msgstr "Identificatore : {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Username: {0}" +msgstr "Nome utente: {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Email: {0}" +msgstr "Email : {0}" + +#: Shell/UsersShell.php:102;130 +msgid "Password: {0}" +msgstr "Password: {0}" + +#: Shell/UsersShell.php:126 +msgid "Superuser added:" +msgstr "Superuser aggiunto :" + +#: Shell/UsersShell.php:132 +msgid "Superuser could not be added:" +msgstr "Lo Superuser non può essere aggiunto :" + +#: Shell/UsersShell.php:135 +msgid "Field: {0} Error: {1}" +msgstr "Campo : {0} Errore : {1}" + +#: Shell/UsersShell.php:153;179 +msgid "Please enter a password." +msgstr "Per favore inserire una password." + +#: Shell/UsersShell.php:157 +msgid "Password changed for all users" +msgstr "Password cambiata per tutti gli utenti" + +#: Shell/UsersShell.php:158;186 +msgid "New password: {0}" +msgstr "Nuova password : {0}" + +#: Shell/UsersShell.php:176;204;282;324 +msgid "Please enter a username." +msgstr "Per favore inserire un nome utente." + +#: Shell/UsersShell.php:185 +msgid "Password changed for user: {0}" +msgstr "Password cambiata per l'utente : {0}" + +#: Shell/UsersShell.php:207 +msgid "Please enter a role." +msgstr "Per favore inserire un ruolo." + +#: Shell/UsersShell.php:213 +msgid "Role changed for user: {0}" +msgstr "Ruolo modificato per l'utente: {0}" + +#: Shell/UsersShell.php:214 +msgid "New role: {0}" +msgstr "Nuovo ruolo: {0}" + +#: Shell/UsersShell.php:229 +msgid "User was activated: {0}" +msgstr "Utente attivato: {0}" + +#: Shell/UsersShell.php:244 +msgid "User was de-activated: {0}" +msgstr "Utente disattivato: {0]" + +#: Shell/UsersShell.php:256 +msgid "Please enter a username or email." +msgstr "Per favore inserire un nome utente o email." + +#: Shell/UsersShell.php:264 +msgid "Please ask the user to check the email to continue with password reset process" +msgstr "" +"Per favore richiedere all'utente di controllare l'email per continuare con la procedura di ripristino " +"password" + +#: Shell/UsersShell.php:302 +msgid "The user was not found." +msgstr "Utente non trovato." + +#: Shell/UsersShell.php:332 +msgid "The user {0} was not deleted. Please try again" +msgstr "L'Utente {0} non è stato cancellato. Per favore riprovare" + +#: Shell/UsersShell.php:334 +msgid "The user {0} was deleted successfully" +msgstr "L'utente {0} è stato cancellato con successo" + +#: Template/Email/html/reset_password.ctp:21 Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Ciao {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Ripristina la tua password qui" + +#: Template/Email/html/reset_password.ctp:27 Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "If the link is not correcly displayed, please copy the following address in your web browser {0}" +msgstr "" +"Se il link non viene mostrato correttamente, per favore copia il seguente indirizzo nel tuo browser " +"web {0}" + +#: Template/Email/html/reset_password.ctp:30 Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Grazie" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Attiva qui il tuo login social" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Attiva qui il tuo account" + +#: Template/Email/text/reset_password.ctp:22 Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Per favore copia il seguente indirizzo nel tuo browser web {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "Please copy the following address in your web browser to activate your social login {0}" +msgstr "Per favore copia il seguente indirizzo nel tuo browser web per attivare il tuo login social {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 Template/Users/index.ctp:13;26 +#: Template/Users/view.ctp:15;79 +msgid "Actions" +msgstr "Azioni" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 Template/Users/view.ctp:19 +msgid "List Users" +msgstr "Lista utenti" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 Template/Users/view.ctp:21 +msgid "List Accounts" +msgstr "Lista Account" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +msgid "Add User" +msgstr "Aggiunti Utente" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 Template/Users/index.ctp:22 +#: Template/Users/profile.ctp:27 Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Username" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 Template/Users/index.ctp:23 +#: Template/Users/profile.ctp:29 Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "Email" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 Template/Users/index.ctp:24 +#: Template/Users/register.ctp:25 +msgid "First name" +msgstr "Nome" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 Template/Users/index.ctp:25 +#: Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Cognome" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Attivo" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 Template/Users/edit.ctp:57 +#: Template/Users/register.ctp:35 Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Inviare" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Per favore inserire la nuova password" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Password attuale" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nuova password" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Conferma password" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 Template/Users/view.ctp:101 +msgid "Delete" +msgstr "Cancellare" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 Template/Users/view.ctp:18;101 +msgid "Are you sure you want to delete # {0}?" +msgstr "Sei sicuro di voler cancellare # {0} ?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Modifica utente" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Scadenza Token" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API Token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Data di attivazione" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Data TOS" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nuovo {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +msgid "View" +msgstr "Vedere" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Cambiare la password" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +msgid "Edit" +msgstr "Modifier" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "precedente" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "successivo" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Per favore inserisci il tuo nome utente e la password" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Ricordami" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Iscriviti" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Ripristina Password" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Login" + +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:24 +msgid "Change Password" +msgstr "Cambiare Password" + +#: Template/Users/profile.ctp:34 +msgid "Social Accounts" +msgstr "Account Social" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +msgid "Avatar" +msgstr "Foto profilo" + +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +msgid "Provider" +msgstr "Provider" + +#: Template/Users/profile.ctp:40 +msgid "Link" +msgstr "Link" + +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Link a  {0}" + +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Password" + +#: Template/Users/register.ctp:28 +msgid "Accept TOS conditions?" +msgstr "Accetti le condizioni TOS?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Per favore inserisci la tua email per ripristinare la password" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Rispedire Email di Convalidazione" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email o Username" + +#: Template/Users/view.ctp:18 +msgid "Delete User" +msgstr "Cancellare Utente" + +#: Template/Users/view.ctp:20 +msgid "New User" +msgstr "Nuovo Utente" + +#: Template/Users/view.ctp:28;67 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:34 +msgid "First Name" +msgstr "Nome" + +#: Template/Users/view.ctp:36 +msgid "Last Name" +msgstr "Cognome" + +#: Template/Users/view.ctp:40 +msgid "Api Token" +msgstr "API Token" + +#: Template/Users/view.ctp:48;74 +msgid "Token Expires" +msgstr "Scadenza Token" + +#: Template/Users/view.ctp:50 +msgid "Activation Date" +msgstr "Data di attivazione" + +#: Template/Users/view.ctp:52 +msgid "Tos Date" +msgstr "Data Tos" + +#: Template/Users/view.ctp:54;77 +msgid "Created" +msgstr "Creato il" + +#: Template/Users/view.ctp:56;78 +msgid "Modified" +msgstr "Modificato il" + +#: Template/Users/view.ctp:63 +msgid "Related Accounts" +msgstr "Account correlati" + +#: Template/Users/view.ctp:68 +msgid "User Id" +msgstr "Id Utente" + +#: Template/Users/view.ctp:71 +msgid "Reference" +msgstr "Referenza" + +#: Template/Users/view.ctp:76 +msgid "Data" +msgstr "Dati" + +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Registrati con" + +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:91 +msgid "Logout" +msgstr "Logout" + +#: View/Helper/UserHelper.php:108 +msgid "Welcome, {0}" +msgstr "Benvenuto, {0}" + +#: View/Helper/UserHelper.php:131 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "reCaptcha non configurata! Per favore configura Users.reCaptcha.key" + +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Questo campo è obbligatorio" + +#~ msgid "The old password does not match" +#~ msgstr "La vecchia password non corrisponde" + +#~ msgid "" +#~ "If the link is not correctly displayed, please copy the following address in your web browser {0}" +#~ msgstr "" +#~ "Se il link non viene mostrato correttamente, per favore copiare il seguente indirizzonel tuo web " +#~ "browser {0}" From 59f332878dded9903ec4e9ce20139bdd53fdd48b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 17 Jan 2018 09:44:06 +0000 Subject: [PATCH 0752/1476] Update Translations.md --- Docs/Documentation/Translations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index 432c93ef0..808e80f6a 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -9,6 +9,7 @@ The Plugin is translated into several languages: * French (fr_FR) by @jtraulle * Polish (pl) by @joulbex * Hungarian (hu_HU) by @rrd108 +* Italian (it) by @arturmamedov **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 fe82ef059c1cf4a4708b46d34b3ca10adf679979 Mon Sep 17 00:00:00 2001 From: Livia Scapin Date: Thu, 18 Jan 2018 14:33:01 +0100 Subject: [PATCH 0753/1476] Update UsersHelper, fix CSS class building --- src/View/Helper/UserHelper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index cd03eeb0e..5f7a7b0a7 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -54,7 +54,7 @@ public function socialLogin($name, $options = []) $providerTitle = Hash::get($options, 'label') . ' ' . Inflector::camelize($name); } - $providerClass = 'btn btn-social btn-' . strtolower($name) . ' ' . Hash::get($options, 'class') ?: ''; + $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 @@ -198,7 +198,7 @@ public function isAuthorized($url = null) */ public function socialConnectLink($name, $provider, $isConnected = false) { - $linkClass = 'btn btn-social btn-' . strtolower($name) . Hash::get($provider['options'], 'class') ?: ''; + $linkClass = 'btn btn-social btn-' . strtolower($name) . (Hash::get($provider['options'], 'class')) ? ' ' . Hash::get($provider['options'], 'class') : ''; if ($isConnected) { $title = __d('CakeDC/Users', 'Connected with {0}', Inflector::camelize($name)); From 3c1eda62e70acc3efb8564b66b1e64dfe119fb2f Mon Sep 17 00:00:00 2001 From: Livia Scapin Date: Thu, 18 Jan 2018 15:04:09 +0100 Subject: [PATCH 0754/1476] Update UsersHelper, fix CSS class building --- src/View/Helper/UserHelper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 5f7a7b0a7..c1f4cb7b7 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -54,7 +54,7 @@ public function socialLogin($name, $options = []) $providerTitle = Hash::get($options, 'label') . ' ' . Inflector::camelize($name); } - $providerClass = 'btn btn-social btn-' . strtolower($name) . (Hash::get($options, 'class')) ? ' ' . Hash::get($options, 'class') : ''; + $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 @@ -198,7 +198,7 @@ public function isAuthorized($url = null) */ public function socialConnectLink($name, $provider, $isConnected = false) { - $linkClass = 'btn btn-social btn-' . strtolower($name) . (Hash::get($provider['options'], 'class')) ? ' ' . Hash::get($provider['options'], 'class') : ''; + $linkClass = 'btn btn-social btn-' . strtolower($name) . ((Hash::get($provider['options'], 'class')) ? ' ' . Hash::get($provider['options'], 'class') : ''); if ($isConnected) { $title = __d('CakeDC/Users', 'Connected with {0}', Inflector::camelize($name)); From 227b16a44184057a57d6bcdcb9e6037da2a7807f Mon Sep 17 00:00:00 2001 From: Livia Scapin Date: Thu, 18 Jan 2018 15:12:43 +0100 Subject: [PATCH 0755/1476] Removed extra blank space in class names --- tests/TestCase/View/Helper/UserHelperTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index b63521935..55e5d1cbe 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -227,10 +227,10 @@ public function testAddReCaptchaScript() public function testSocialLoginLink() { $result = $this->User->socialLogin('facebook'); - $this->assertEquals('Sign in with Facebook', $result); + $this->assertEquals('Sign in with Facebook', $result); $result = $this->User->socialLogin('twitter', ['label' => 'Register with']); - $this->assertEquals('Register with Twitter', $result); + $this->assertEquals('Register with Twitter', $result); } /** From 460284a0ae360d0b8bd3351f09ee456ec1704f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 22 Jan 2018 09:39:35 +0000 Subject: [PATCH 0756/1476] Update Extending-the-Plugin.md Improve docs thanks to @llincoln --- Docs/Documentation/Extending-the-Plugin.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index 01a5b5b99..3da0705d6 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -180,6 +180,8 @@ Updating the Templates Use the standard CakePHP conventions to override Plugin views using your application views http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application +`{project_dir}/src/Template/Plugin/CakeDC/Users/Users/{templates_in_here}` + Updating the Emails ------------------- From 76110b19be21df2257db526489105818c4e38073 Mon Sep 17 00:00:00 2001 From: Serdar Sayin Date: Mon, 22 Jan 2018 22:30:52 +0300 Subject: [PATCH 0757/1476] tr_TR translation added --- src/Locale/tr_TR/tr_TR.mo | Bin 0 -> 15267 bytes src/Locale/tr_TR/tr_TR.po | 819 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 819 insertions(+) create mode 100644 src/Locale/tr_TR/tr_TR.mo create mode 100644 src/Locale/tr_TR/tr_TR.po diff --git a/src/Locale/tr_TR/tr_TR.mo b/src/Locale/tr_TR/tr_TR.mo new file mode 100644 index 0000000000000000000000000000000000000000..c65ebec0d2712a5e0117fa2b0d3ae8d036658bdf GIT binary patch literal 15267 zcmb`N36LCDdB+>$3)%R@*q{K%$z3%Cr z-Q`NU^v%Efo!|Se_r14z;;iG}8Ss1_`ZegO6N2C;;FnL~hv##r2fk9J_fMe4`xlS@0lt{;6VD0)rV1|gcrD1kU>83c{}rJ4 zd>g2C?*dnY4}ltY5tJw%2hRn+1s)In5EMU8fru>lAMiQg@n^gBJ`Ys;%RyKPc6hwg zmp8ywl-~!Q1HRpVKjiV#;Cjj*1I5R`fyaUW35wtU21D>TCe^wt;0V|THQ%G)1>oc0 zW#A7%@$(`kTL*3e#s7@Q7N~U{0=3@Pg5vKjpw{6|7@oV6zeE$Qe z`M(D~8~iaSeow+^)bDiA>KByVT;uU}@CAH#!3)86f$IMlxEuU3cmueaMce}30bUJ$ z8oUJj0eBvGE0(dF-RZw#Osjpv)@oS!4p!}=@YW%l@lKaO%{so`pM|yc2 zlsvxyiti`Emw+-(>H9)Z_HiXBInIF6&wZfm_^qJUF%N3Ihd|lGr@(8#Z-Ord&w?3V zgH0eJ4#q&O>j0?vUI$7}4}ts(zQqr$1W$qD|8$sBzl%ZH$qk_NHVUHpU<_2d7&PGP zeEkQ(wR|4|#m^I<_IF0yw11P>80Hx1| zLCyQ;p!i+{hrzFa&je3LXeWVZgVOJ6P=2)uyz3bdxR38Y!wBT(XP|7=uLdR0&7kym z2PivxB`AJB2&(;Gg0l0kfER;52IYrq7)1WR)8k#>34Av}+2t&FHFzH=Ieh`tdj1iF zmEgOe*0BoVo(S#)HQt!V2$UQTg3`-jQ2zcfDE)p3RDAm`C_8vA%*ifZ0;=Ce@R?u) z$_`>s>pBFU489kXoIeDf1Re!7|00Nq2HymwkEcM{;VCRy<>!K!NU#x<9qb2XpA+D5 z;H<|kxRLKeptWOP{urqFz5rIhFM{HGkf1aUUJq)#cYu=9VNibaWl-xr8D(q&F90R) zJ3NNqD!!*dt)m4>zpn=+-v_{Ffgb{|06z{&Pv7?V6nF~XC*Z6qKNFPP*MKL3>p;o% zYEa|Fpyb~K`4@bEAI0l2ie@j7F4?Y531%4eo6+8vz#Ls!4##;|+{WpTo2KR!f zHnIOxJK|5Q1bc_DEs*- zC_c_+F!}#l@N{rH_%iS|5LXD^16sQPrROh#(&u+T@%uwx{xop}6q1>6VD zfU?iegQzn2FK{>bQi7WSyP)FAd%zpON5Q+mAA@&*w+=b^eFi+2@5e#e;kQBQ`v)HX z9lVL}r$O1%Hk@AdJ3;X?4$3aO;4?st^*QLXkmAu>Aw92vLg;Qt&+j-0P`~BpouKUL z^S=C(;5KN&e-DD2q2GrjuX`aq!w!P`LFrSnl6=J5eNYS93*8Rs`GkY~_j=xb*MG?m z^jrr$7y46u@XR;}J`R2m`Y_wq6Zoe#an7hVX)(8Ev!Js)}{ z^dU$wM|PY&@`WA#<3#Y?&}#oJ=t3zZ-+B}D2hefQmC);;!_ae}Dl`PW3VIa!Bk28* zo_Xli&@^-@q~{Fi1JG|nFNd;cmX{9no6v!*5ZnkI54{$;75WY6dC*o!&vt0kz6HUr zdlZ}n%|ZL2I;7`)(5ImDpj)5@WT4kWw?PAto+J9XHf@H9nXH9rdfl4oTDLh9Pc{;h zzYWwH(*tp`#)Pdn9GHnKl_W$JvrxjAaZQ{7;A?{?E}RHGyqo}7%D zZ8N@S%rICbZpV!zy+Or|PSQ4Etrdlpu9*#MaV2a=mAr=fTE!%dwwZ{QsaC}lLsa-} znf6R%rsLTtakH9`@~9rhwZVM6d{PFjvE&cXm)P1=kmhkYrrBvV8)=lBUmC-hci;FeMR%fS#?w;QGs)gsn-fqB)s zSEGcLnzf=dQhO9=XSOV?q0bsRA*HYtY?%p@>B#KGSPnK?mF&CO_btV=8nws{vqZF8 z8p%}Ls+(S~Mv_F6ZF4Yg&xpr>7AlA;#iGnGm`fs;(wtV-nr1Bu)5x@2T@y}+aWWWe z!N6o!TRN>)gcS0*MxqeiFR$|vE2qGL(~W;$vW8J?I?#`6HY%$N>~C(|(cN*{PJLm? zt|jP%?&^epWDCRM3*|EPW~n6>FO?)=J@S3kylmKZ%pohp8{?=}v9D&d)oQeOUH|If z#<-QX&2Ek1UhQyO8;xnyHQYgSNjshl+j1{!2?xWpG=;Hd5^Rg@B-<;&b~j0|eabpy zEl#Q?POT45Hjw^gyVf<8IBnL#ZdA#YHQ8u(ZHK8wt=2dw6AvpD22TyK#^zK*P3?ZM4mXjaQn9xSg7dFW+D$y6q^v z1fNZ&^FdnCmay5LoC)(1w|;`kWeCH&xi`7KHeNFsW4Q_B(I;>3OB4&*-DVVQPt#76 z%5o(De3dw&^;=i4Lg<@#rxs(?XWy*$b|UgXKN>)S+KJ^^!%Tynic9)!blSnLI88Or zMVTF4q`4YR8w?ek!eCdULJ-7rb`y{GD?I5Xcc0>iGc%RQ*Lz>$U^mtqVoi-!JXcV< zi;{SM+79++K_h!H2%qTUVtZJtS!+-8cBN`9z|Gj}U34TrRIl?4W;_uQ*|JGW`$0B{ zAJT=BFh!t5GR-B)PR>M=t|YRatD*+pl5`@cuclv-a}m6^p&cjK>xOgPtxkWn{=b~V zz+E2ciiYG=ART3V{c__LdPYe&LDX0_cvu||W^)i!kYSkH(UJ;T(2~N;N)7&HMYdv# zz6xnADVnWcs$-+4f--x(a%tO!ITwdAy)M%{XHmIFf4j{6-6&ZOF%glwMBdSZy{*P< zT*1w<7c&_qKL3g8&2~4~7fq3MB$H90CLxQVVj4fE>%OQS)h7@zL4BY0mWsLAWmbwa zR&utyy}YVi_MndK-p=kmvlSr_Wd)_ZDqCH}kKNZ+`$pcRw1fEeQc~VW>0Hm{-Q-If z^e1V{w405?(u%E8^J#2;whvni^pnQ|&EAVBs&au~ES^rXXdH~WL~pn+hqX=?_1CT- zsqz?U)+;lOEHBPeoQf2~3Zy6hyjuH}960JewT`bSRY~OrSUCDIBgypj& zur!=y2g>VwHsK|m7i;Ze)gA~2d(DYZMs+Ujt(0vq@13>M2)^YCi%`oFd%n4yaY<#5 zcU9%vPJf@g!nd~>y!AvgdUrE!MQPx^GMk8ODN;jr=*4ytxA z>&5<9;dMKx@p7qyK~Ph7I)jX+a#a;;8r z;$+D!BZghnr|8 z1{(0J>QxbC`C=1Hh3MS2NTR#j0mtpxxY0?2-nNBRh$$y0nZ5h=+%&pn+}u36 zZ*2RX-K+NQ86U9M9@Gx#;%UfiShs%D!1{Fq>#r~yE+4vLD) ztsmI1!ED$tv|;_F>n^9=PEKQ;a5@?okHY$p**Uy>>;B=bqvqPtUBlaVzHE48WZ&r6 z*!8P+ZQnK8V{853x>Z{^7LjWYjB~^tGHqmg8K?g^xkedRi_Pk~{o^+dT-9sW3X_y9 zcVLv@QsIO;WUk_{zKX!n3Tp#5Hd^&`$RthsnO?Wy8g6`4bKS*>IsZDd{*r4}-8!(< zeM(?EFSR{c~MvoRjO!Oqp6+55FMfc?g!hUi5CuYsGqT;F-wQwt`38K zoQd$*yx8d0!tyl3)f9FTcnmg2wYXJ_xiD#&s@R6-NxHy!SZxzFXF{^)>8KsI?5GoV zRdZBNpq2`^W&O9BAHfLN%bX0lQR3E+E*vEv?k+r%!182VTvH0uk$T>iH7+dJ)eLjPdXrQcjK#Hj zq}wg_;&^dBPLR4TYwI{ulHIQsc~S^)yf|AhOgFW7q*X&FD~*$1wjO&ho??p|iJ0lw zykzZ5D!q~wG=;tr-O4N+O%{%l-u92sNJ8|_c%7t!#?3^yIFFX?*4kgVc%+8;*eYkD z(Xsg&1Vb2L9Z9S;Ow^vj7~4^`6}Ff#iMY@j4EEGIH0)r?bzXw4(ZbMB|JsPmk_qxZpC93d<5 z>zc-bIIH_*=d~*ocN^8b$!vsY7A?#Aa5j9=C-cE7an{=mDzL{-Y)bYmFGR$92 zD#5ZBFy7#bL+8e4!^*CxH4{#RRt6aX7JSzNfSB}R?j_Ch^^rh-VoAw&c&(1ce^u3%Svah$==B0 zOgNWa;JW+Uu-m@G5PWrmtC-xG!;CwN^ZaEfG>uw4tPvrdwP})kZ!VN&ar3g-s2g&< zYlD-Gn#(kzMNxTbhDk0Ltb3DY0lOZWNphYz3xK{eE;?thBp(n>H*AJ2U9v13UOZCO z9~>Gj`DTlL-LT?+H#7A} zi>*Tj-HNenMEdUHI%T9!-g7@;FpaCk)+~$=28l>6WELiM1>U!9JazBRer*9UsqiJH zZ;RSkRqTRPt!GPdt!i*LuD#rjApv1WJ_ZKk3rFikow%*l2No@-5cM$HxF{SSk{xq> z?HqSY0&V8bnxxa8zqW+;nwQf4q_W0Z^gr4KVf7EE|1`I+Mqn1r9Cyi~YD+eO># z(Vh+)Y;-nR3PyZBj01Uzux2qW*^zB%OVZA~{8ng_H!>YFmI*5Jk|hNNQM$~!(@T+x$`ua{Mtkb8a+MP^=w6k6bvjJtW+3~8F!K!UL9t^g63mUU$g`$IKo8EcVb*rD(up&ZGq8eN%00xlQ{AS7N^0EYN3})4T!W7i;;n zzUqF>X6_SFq(1}N8aBG4c3a8L$+b$yx6aKtvn1bvQ>4=-!NX~<6mndvFq-m?@zZa>r~2L@-xMbbORv zE>SJ&K5O=~Y%Ob(&9&tIpg3UeGQ~nCH5USk<+ic4sG$<`-iDnUy9l(RE&sghkZQqe zR&)V3Vef83`J9VzMRu1vnYuIb(zb=EN=uXemWqRztvsHqk^I)C)N2@B!cc*{5z543yA$9SYg>g(<%L&}^w0CWvtw+bu zELqCT*rnU#eeM>4{v^!Rn5zJLdx6Q#v6J>kZ}^FAUST&FpOcZaZ~@_cUHMDK&*s8) z8bMCkOM{q{bXZi)r_8-2XBkblWpgWuPHnLu<>f5ROwVn?TmNotl8CNU4 z#L3-1_I3;YZvuZ_Mxx%XFauJ!YNsu+b;`$%f|>rmkG=e#1%83Q7Nm^?Yls7@9WcLN t5bsklw +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-10-14 23:45+0000\n" +"PO-Revision-Date: 2018-01-22 22:21+0300\n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.6\n" +"Last-Translator: \n" +"Language: tr_TR\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "Sağlayıcı boş olamaz" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Hesap başarıyla doğrulandı" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Hesap doğrulanamadı" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Geçersiz jeton ve/veya sosyal hesap" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Sosyal Hesap zaten aktif" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Sosyal Hesap doğrulanamadı" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "E-posta başarıyla gönderildi" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "E-posta gönderilemedi" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Geçersiz hesap" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "E-posta tekrar gönderilemedi" + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Geçersiz tuz kodu, tuz kodu en az 256 bit (32 bayt) “long” uzunluğunda olmalı" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Eğer use_email yanlışsa, e-posta doğrulama iş akışını etkinleştiremezsin" + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "Hesap eşleştirilemedi, lütfen tekrar deneyin." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "Sosyal hesap zaten eşleştirilmişti." + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "Sosyal hesabınız ile giriş yaparken çıkan sorunlar" + +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Lütfen e-posta hesabınızı girin" + +#: Controller/Traits/LoginTrait.php:120 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Kullanıcınız henüz doğrulanmadı. Lütfen talimatlar için gelen kutunuzu " +"kontrol edin" + +#: Controller/Traits/LoginTrait.php:125 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Sosyal hesabınız henüz doğrulanmadı. Lütfen talimatlar için gelen kutunuzu " +"kontrol edin" + +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "Geçersiz reCaptcha" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "Zaten giriş yapmış durumdasınız" + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "Lütfen önce Google Authenticator ‘ı aktif hale getirin." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Doğrulama kodu yanlış. Tekrar deneyin" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "Kullanıcı adınız veya şifreniz yanlış" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "Başarıyla çıkış yaptınız" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "Kullanıcı bulunamadı" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "Şifre değiştirilemedi" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "Şifre başarıyla değiştirildi" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Şifre sıfırlama işleminize devam edebilmek için lütfen e-postanızı kontrol " +"edin" + +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "Şifre jetonu oluşturulamadı. Lütfen tekrar deneyin" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "Kullancı {0} bulunamadı" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "Kullanıcı aktif değil" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "Jeton sıfırlanamadı" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "Google Authenticator jetonu başarıyla sıfırlandı" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "Yetkili değil, lütfen ilk önce giriş yapın" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "Yeni bir hesap oluşturmak oluşturmak için önce çıkış yapmanız gerekli" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "Kullanıcı kaydedilemedi" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "Başarıyla kayıt oldunuz, lütfen giriş yapın" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "Lütfen giriş yapmadan önce hesabınızı doğrulayın" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "{0} kaydedildi" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "{0} kaydedilemedi" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "{0} silindi" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "{0} silinemedi" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "reCaptcha doğrulanamadı" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "Kullanıcı hesabı başarıyla doğrulandı" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "Kullanıcı hesabı doğrulanamadı" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "Kullanıcı zaten aktif" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "Şifre sıfırlama jetonu başarıyla doğrulandı" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "Şifre sıfırlama jetonu doğrulanamadı" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "Geçersiz doğrulama cinsi" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "Geçersiz jeton veya kullanıcı hesabı zaten doğrulandı" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "Jeton süresi zaten doldu" + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "Jeton başarıyla sıfırlandı. Lütfen e-postanızı kontrol edin." + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "Kullanıcı {0} zaten aktif" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "Hesap doğrulama bağlantısı" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "{0} Şifre sıfırlama bağlantısı" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "{0} Sosyal hesap doğrulama bağlantısı" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "Seçenekler verilerinde ‘kullanıcı adı’ eksik" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Sosyal hesap zaten başka bir kullanıcıyla eşleşmiş durumda" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "Referans boş olamaz" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "Jeton son kullanma tarihi boş olamaz" + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "Kullanıcı bulunamadı" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "Kullanıcı hesabı zaten doğrulandı" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "Kullanıcı aktif durumda değil" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "Geçerli şifre uyuşmuyor" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "Geçerli şifrenizi yeni bir şifre olarak kullanamazsınız" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "Verilen jeton ve e-posta için kullanıcı bulunamadı." + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "Jeton son kullanma tarihi zaten doldu, kullanıcının jetonu yok" + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "Hesap zaten doğrulandı" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "Verilen jeton ve e-posta için hesap bulunamadı." + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "Referans {0} ile giriş başarısız" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "E-posta yok" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Şifreniz onay şifreniz ile uyuşmuyor. Lütfen tekrar deneyin" + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "Kullanıcı adı zaten var" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "E-posta zaten var" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "CakeDC Users eklentisi için araçlar" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "Belirli bir kullanıcıyı aktif hale getir" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "Deneme için yeni bir süperyönetici kullanıcısı ekle" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "Yeni bir kullanıcı ekle" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "Belirli bir kullanıcının rolünü değiştir" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Belirli bir kullanıcıyı devre dışı bırak" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Belirli bir kullanıcıyı sil" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "Şifreyi e-posta aracılığıyla sıfırla" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "Tüm kullanıcıların şifrelerini sıfırla" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "Belirli bir kullanıcının şifresini sıfırla" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "Lütfen bir şifre gir." + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "Tüm kullanıcıların şifreleri değiştirildi" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "Yeni şifre: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "Lütfen bir kullanıcı adı gir." + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "Kullanıcı için şifre değiştirildi: {0}" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "Lütfen bir rol gir." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "Kullanıcı rolü değiştirildi: {0}" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "Yeni rol: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "Kullanıcı aktif hale getirildi: {0}" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "Kullanıcı devre dışı bırakıldı: {0}" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "Lütfen kullanıcı adı veya e-posta girin." + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Şifre sıfırlama işlemine devam etmek için, lütfen kullanıcıya e-posta " +"hesabını kontrol etmesini söyleyin" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "Süperkullanıcı eklendi:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "Kullanıcı eklendi:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Kullanıcı Adı: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "E-posta: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Rol: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Şifre: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "Kullanıcı eklenemedi:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Alan: {0} Hata: {1}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "Kullanıcı bulunamadı." + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "Kullanıcı {0} silinemedi. Lütfen tekrar deneyin" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "Kullanıcı {0} başarıyla silindi" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Merhaba {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Şifrenizi buradan sıfırlayın" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Eğer bağlantı düzgün şekilde gözükmüyorsa, lütfen adresi internet tarayıcına " +"kopyala {0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "Teşekkürler" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Sosyal girişi buradan aktif hale getirin" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Hesabınızı buradan aktif hale getirin" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Lütfen adresi internet tarayıcınıza kopyalayın {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Lütfen sosyal girişi aktif hale getirmek için adresi internet tarayıcınıza " +"kopyalayın {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Aksiyonlar" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Kullanıcıları Listele" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 +msgid "Add User" +msgstr "Kullanıcı Ekle" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 +msgid "Username" +msgstr "Kullanıcı Adı" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 +msgid "Email" +msgstr "E-posta" + +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "Şifre" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 +msgid "First name" +msgstr "Ad" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 +msgid "Last name" +msgstr "Soyad" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "Aktif" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Gönder" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Lütfen yeni bir şifre gir" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Geçerli şifre" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Yeni şifre" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "Şifre onayla" + +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Sil" + +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Silmek istediğine emin misin # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Kullanıcıyı düzenle" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 +msgid "Token" +msgstr "Jeton" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Jeton Son Kullanma Tarihi" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API jetonu" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Aktivasyon tarihi" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "TOS tarihi" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Google Authenticator Jetonunu Sıfırla" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "Kullanıcı {0} için jetonu sıfırlamak istediğine emin misin?" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Yeni {0}" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "Görünüm" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Şifre değiştir" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "Düzenle" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "önceki" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "sonraki" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Lütfen kullanıcı adını ve şifreni gir" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Beni Hatırla" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Kayıt Ol" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Şifre Sıfırla" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Giriş" + +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "Şifre Değiştir" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "Sosyal Hesaplar" + +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +msgid "Provider" +msgstr "Sağlayıcı" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "Bağlantı" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "Şuna bağlı {0}" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "TOS koşullarını kabul ediyor musun?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Şifreni sıfırlamak için lütfen e-postanı gir" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Doğrulama e-postasını yeniden gönder" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "E-posta veta kullanıcı adı" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Doğrulama Kodu" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" Verify" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "Kullanıcıyı Sil" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "Yeni Kullanıcı" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "Ad" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "Soyad" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Rol" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "Api Jeton" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "Jeton Bitiş Tarihi" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "Aktivasyon Tarihi" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "Tos Tarihi" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "Oluşturulmuş" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "Değiştirilmiş" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "Şununla giriş yapın" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "Çıkış" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "Hoşgeldiniz, {0}" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha konfigüre edilmedi! Lütfen konfigüre edin Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0}" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Şununla bağlanıldı {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Şununla bağlan {0}" From b6e018f52facf37aaea182db25661acc8ed65f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 30 Jan 2018 17:38:39 +0000 Subject: [PATCH 0758/1476] Update Translations.md --- Docs/Documentation/Translations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index 808e80f6a..41abc4e08 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -10,6 +10,7 @@ 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 **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 8ba515b00fab2b5320a5620e24ae08347050bbf7 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 2 Feb 2018 16:49:55 +0100 Subject: [PATCH 0759/1476] Update readme for 2.x --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e9741ea6..b3143e4a4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Versions and branches | ^3.5 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 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.1.2 | Note CakePHP 2.7 is currently not supported | +| 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.2.0 |stable | The **Users** plugin is back! From d856ad5768e424c50cca06475c5af98a5193213e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Feb 2018 14:16:00 -0300 Subject: [PATCH 0760/1476] doc for google authenticator --- .../Google-Two-Factor-Authenticator.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Docs/Documentation/Google-Two-Factor-Authenticator.md diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Google-Two-Factor-Authenticator.md new file mode 100644 index 000000000..9a098a115 --- /dev/null +++ b/Docs/Documentation/Google-Two-Factor-Authenticator.md @@ -0,0 +1,27 @@ +Google Two Factor Authenticator +=============================== + +Installation +------------ +To enable this feature you need to + +``` +composer require robthree/twofactorauth +``` + +Setup +----- + +Enable google authenticator in your bootstrap.php file: + +Config/bootstrap.php +``` +Configure::write('Users.GoogleAuthenticator.login', true); +``` + +How does it work +---------------- +When the user log-in, he is requested to inform the current validation +code for your site in Google Authentation app, if this is the first +time he access he need to add your site to Google Authentation by reading +the qrCode shown. From fdcfe3ca18b34d08515571a4ef08232c24dea3ef Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Feb 2018 14:21:35 -0300 Subject: [PATCH 0761/1476] Add files via upload --- Docs/Documentation/GoogleAuthenticator/App.png | Bin 0 -> 52261 bytes .../GoogleAuthenticator/FirstLogin.png | Bin 0 -> 21106 bytes .../GoogleAuthenticator/NextLogin.png | Bin 0 -> 15031 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Docs/Documentation/GoogleAuthenticator/App.png create mode 100644 Docs/Documentation/GoogleAuthenticator/FirstLogin.png create mode 100644 Docs/Documentation/GoogleAuthenticator/NextLogin.png diff --git a/Docs/Documentation/GoogleAuthenticator/App.png b/Docs/Documentation/GoogleAuthenticator/App.png new file mode 100644 index 0000000000000000000000000000000000000000..dd47e98453d50c1aa3c68ed9195c272c5731daf3 GIT binary patch literal 52261 zcmeFZ_cxqh)HW`?DUlE@NopV<76L9&!N%BVQ=XyNL=6&G{hONTJXK2k8DyGv$89N+Fy(7R-uau=)>NQx6I>R0s z*g4JzILk;IXbBfNT+G#+8~GJb)T|{>%_l>44bsDKmr-QJ2FZ88LLwco8r>jZ{iQHF zi%gJ>u>$G1m1p^Q;z45y7?2!1gFY!MTWNDnsZRo@M9Z_etn7=o9CHnl@;KP_)A>2` z<4%<^D2HFa=J_gd!BECf#)_Ns{4mVwvleM zXM886N5DF>kl^z$&+BOV<;)9~6RXI`#t_PQfwG*^>I*84bNwD44)`6tWk=^Ogt93t zUkN3AxIjXZD{}s`PWWp$4Uz`2vK)a|&ldYOj+N3W-IdB3xv{lQDd*GZnveCcpoLE) zKxZ0-C`ayGvL4dI9>1R@pYe5(Kwc;;(d!X}zgTz!`(flUv@2l`ATYBXOWqLgxgF})0FhAaX)ET+wb1FIn4M{H4+v267N&B;G>~097 zxwygN;o-7RC}q@RTY?KD13Oz*T3=6SWEG3SneUgN3+>HCi+Mt?GtRd5>KJQg`+7Vx zWVj;@smHvpC^pch8kQy)72E!@43!ELXsFEhH@UqI+wo9YF5{@ z--^a7L3iX?)ZaU4he&$Z4tP9PQxJXIIZBYoL1)^z{7r=R=oX>>_9aRNsB1B|JbKvw zASG2)Jina%wQtcy4eoDMi~h<{jER9PE(>47aPETcdl#d46H|J0iqKPvax!4M45AlDPI9F`$@@DVFTkENnX%6*zb-V6-O3hZTS{=S=mgFGzzsk-w%HS^DyGL{V_TTZx zPV3>yzVVKc1W!d85Nbl2SO zjhBoOM=jp9W^^=K26n_mw%b0y#5npM)l^lgJW@BNZY4n8bB`dsCZo@kW>UhO5%i&Sma7Wv& zeesrtt<6d9wnQZ#*N(7_{p@oc%X1{b7d`~5)k0dZeMS6m9%DNry{|4+6@&FKxfZG> zhe10AJ`RSG0j4aj{OS1zdZlW@Wg>6veN^PsDipT#;vxz^nTq*(@u9yTLete5N53u< z4OnIT7KT@L!4_uXMxh+=8GknX-ZK!C0(}EfmY&&qNp>kOB6L;i+&A=;%rB>IE0A8 zYhXJK`iy2u&3a5tdgUm$Vvz(_Bf|^6nLb?DtyLy>)w}egF_N!+CJBVz{NQIOu2xf* z#geef)HfTgd2yL*s{Wm$tNI2J3#wZifL_PGt5)npR2+~6e?8Apa}Z3(}?kj1TGaO z`q7bvqI?la2ko8{vP!!->G&3_-tIc4*Vz?(u3+mqweyzs%CLrKd5Q=}qvzRgQ(eAH5`6wc zFa@>x#@sp7hi^q~Y5C|)$C(TlGPaN-JD=A-3?&6v%P3T1%A66&gaGZikstRcRqoyz z4YiWPjBnNveLw1D3G`0L&R=j+Nb+-(aWg3?(}xJuHI(MHsThfThnsVZH9OmC$oSFG z3q8VC`J0W|dLmA8Z8LKR zIe4l^y6&XdXXDMRnbY!QmEKeEvjKeSLs2(*Sxde_NrWp`(cBN-nze!7*+r|-wdkYDNR&}JyxHiJf9M>)SlL#Q+(e5~ z|ExnA9JqQ2=9vdrs`3VFH1wsy@FDN|7RNe19pNC`ZCnLd0qh8Rc>l;IRk0tjHBr;V!G=Or<{JbGA-aE%@k}7W&|P508m`Vn*ve}{ zWYJJHt@WOW_??9=<`BHT8}+CI?f!m*YfP@qQsM$9Es6A%m%v&jXA2aJ_7MUp{-;g` zTV4(AdBPwlI?rk4oiWL19}0eHD0L2OeBmXLJ))S?<LoUL1+oBEYA-SF+rPq+i5yGeB74s*JP9 z{7*x?pOdLS7Ms{$uKK*?*5UB01tvQ+G|hK`wfVR+^-1fjePy#2J+9}N&wsUDZh~E@ zO51CPN+~CU#@R(nR_Td($Qi0Hwag6eY~m=ANGmlpj&Ls7V+>w_H+7Dzt@R`+TNgj7 z3;jBWNEa)vDpl&yIH4!$``N0HT$#h9jmb$lozt-2id)%v8rAx0uKpeE+}P=NDBlBw zY3oj&nyw6z6W*nfP?;2Rw$a=ea@0qtyVmasJandvH~%xjwaRgjzpx5<)7hg7<$j~+ zrN_jNquvMQ__RvR+#^P}A#dJ5Q-6JS1~;Lzhvc7a-ozYcENIwc%(jD#p0nnDtl@*4ru#*oWm+K{ z+hVIWV+)bdlOo}-LvSAbI=WsNcT8#Fj&A0@_K=5r+Al$dHuU7-jD^o&TB#F%mXQl9 zA}riSHeE_Yziz_%<5xR_)wUOREixF;I0J3n@fosVziQVmUO$<4U@nq1V3zV#R~Uq(u{yJK9Q*K4^vWW4`~ zvqvz+NqbuTQj^_v0hi3}Gh#~NrJ4*exK`rqw* zYhurJaFyhdBeJ9L1uMRZePrTP`4r1V-F&(bLefyid(YM`Da46MBBJ<39p_xVCZ`G= z>TG;EHJ(X78GfPa!SIvIHfht>G0Yi^9*#F7QO=vUX?pZC`x%pW8vUIHFoFdRK^BV{ zk55sU#OP<`-V4R$d6&j&F7?kmO-ly@BOYv0W^y%`x-yc!m~A`Dy5v zm&paU%nBm-Y)BR6<>Xl!w(#O{J`#!q9&V z9)r}hLSm4<3M88QA4?=X)dw)m%p>z7f386Am>JZj>yNUN0$l!>kWD~O%^)Px+9i9-~Avh7x+#yU7WK*jHVGGPD~xj zQeC>yX)tke)26Bwj-=ko1Gg^=>M|N-;g-dWS*~<0mr1U60Ejuvo3G#@rFr=9wXdgR zW3e-@Wmo9+n2*V1_ck)?l{cWZW|dOT$_j*iZ)m_Ve40W@!}D|f6{P%z3A17&d0a|O z+pJSR=98`1ojf^YIXBf1Jigk#yx+P`xz*I)s(EzEA+`jrwzz^O$Tnw5l#Jf;eJTy1#9 zJnG3aOSu=3!-W~G3h~G?z1_*PUC)qc!v|ixg-oToJ416>YoLU6Q3~`Rg*cw&{ zlQ&mk4$sjUX*Z3_6Gel~*@=-tCe6u(dFQPgSfOTahUUU&_(N)g`7H*+?E{=!_v`S+ zcgh~uASQmoy0rT=_MR5#K#}ty50m(0XkxCd&QSFGb1{F`I%<>j@M?3y`vkS4rJ?Od zZ=vmfrJ+t84bQ9E4VquRK9@T;&nrQ=lDp-9;^g-@s<J`Xm8s@UoUV)AV`8Z4Q^XU!LOKsxcz zN6V#yXLtpR3b2&knC)ky{hfBav~|%x+aHLdXHW`uiy~lg0IiU-7%t&32(Cz{l$U=(Rz` zn4QLljg@_~J4oKc6NlHs9!^LGG_(Z=-jHEi8Z}+?5*dOmO^n!=HK$jB0VFsAass3M zf>=3cU7kl@`SY+PX3Cd0#%E6jK+c^RVLPSWj9VTR^MQAx)TRq9YPVArK}#&)@twcBI#_J zB^{Vc-CXbdvF{xfWw%zd`Y~|SS1~{Bsa9uxIh}sR)lh?OMf=jP?xnV%>I)3)uN&-$nzamB z?_@#aZYJ;S(RXhNl8PyZc#8*nmGYu9hP7}3gT`6&Cbi{+ltat2KXcDNvH@5z`r$Sg za|)TCgQJwingffh@>C-e$fb8kpJae6^pK7BMx|*Vq*2yeBpS*kH)YJQf^Ywkl z3Hfgn1p!j#Qmx4Y5po44{xirazbchB*Zh|(qpG5Ck=fBp)DR-Z$q@QE+eR*HAH33j znM4{Q10YE@6h*-Z4x-zaA@6iKd5U~vjMKgA_KLHg#NcR~=#NaN$*YXZy+3Cjr;%%9 zRD03LtdY4nm&y$+k+(?&%E}UfF`AY<3O1@fG#%Z!<;Pp1{Q}kaaFtH3z|j^YsFS;} z`sLUP*5bPp4>F$)6<%6{5c7BZ68S&>jV_W+w_F^7YehWn8uTP%+oYE`pP)kuMHw!h z)f&nK0OMn>?UIyIu}R3i*#VSfp~_DQbk>~-a2$NglDKEplFD3 zB!Jmgr2-Elb9(vm@VUesGwf(Jwfk1`&Xnhfzu0BpR-M#siOqJ3)0T|QrRx0WddjqS zM@9UDI=H(@1+?coaRcHg8WV`HwOIT-Q%{%u<9;(*kn^pdHB~+Di311u>szM5RN2IR z$VkS@_73o~a+)D)OaXSZa1#^yG2H;9qa?dxC0 zwn#Xca8Y51!%J929g(wbimxKPpzIwig#kmJ0)kf@7$sN!v|0m}a%GuI;;-CUkNKRm zCPKCMbp5NlxqeK=-~K@C=JvwWQJEv9+<#$7A&Y~Qh*YejE?1(gH#v4=wnA>?|En3T z@U8H2rq(QK@>kqJ_@3g+%__+XV5{}xix12>5td4BbYPt)66T(kCoxednNCMfh|Psg z4}FQYsp;vX7>r_eu#?9A=1HSwqG$p&lV)2vQ|gJcmF7ked5qVsR#w8VCHuO&I!{S; za96ZJvUE;;Y!mR9sfO}A5%c-stlLcGZ%I*>xO8)=pFK^95r~?PIt6u|aT=1=5nQA_ z6XnJJXBJAyF;(?S5|za}p+hI_QND(^<|W!`(#yjX6GG|;80voq0CJd8F0&F8oe1qe zp{}lBMD85qpAu^dUf~P?VmETrEeDeHiTJA+EvjGq@&M$Gr3;1pUIO>$T~x%Yu6$2@ z;J-1`Shmy@h;S)j*KHBH2%0Si4}q1bBA!IQVs073H@-`0J}QC3Q`xi6%t z=xy;Pr&(aN+@`?NN@}d1U9Z_8v(R}#Yt(A&HaElCS?3j1VPA8lE#_tu!<>EPz_xI} zGOh(M_HfyLuR9_CTj6Gw{--)#T9RH|wA8OT^4In9|9N;!b&@UO@^P$j(b;OvoF;F2 z1|R)vLxZyH@M9x)#GBDV7gGb%a=zpApc0`%#t0nxmWUef)-^sm29PFQeB9kg)xkYbQ|iR~6UZ^@%GmqohO3y7{JGgO<%;bmSzeZ+%1o;?n;rr!r)S z;m&C4hoS*bC+u8i|W#D0+0pP;~`npBjW<+(H*ApPQ4;DvyisUMt9v2 zQ$G`8!HBeCA#VS!+(NeEex~CMQ;|w6x5|c?(3+$PnGB#EO1SS*kJ@KEooVcu%u9d) zHgIUe+HUpNHu_n^?)ONpQ_-Gy1U^R0*E*-dCCD}K_-NZ=y@k1Sygvi3UoQcjxgBjr zX$$zPHL?hsnJ{@{R?~c)ev^@(qC_6y97&(9B$PG1u5QVY_NIJYCs>Wmv7dW)Z*f~P zAIYKl3 zzAEu)@Tj#X!Jni|h%*^y!?SKIRsLk)$cHE0<}wng-s_2bXV*rx^`Fa2LnzOFvHfYU z=gni+X&N5pO71GY>%S8xyU;bK>(~#HU^a=+e%y*MJjl5K-6M2Z^@|D6SNKl_Fz+v{ zCf66{l1H)GiZELFV&S9E?0>e-K%W7cXhTWfT6e-`{*OHWWq?GRMN;kZVA)_S=(?5`W@~_%<>AX9BoQoj4nMjx~)&*5%+45+|`&_4+E0YwpXFKH! zKUtL2OEYU7A1n7@7-Alv2WFOn*Lf<{wvbG=TFsxTCY*Vc>+EE;?sG}h4YcJk)z;L@ z>1zxu-wYuJZ*jn~5%y+=cVRT=Ki~K9RnZT`_FtB$eP)!nAU)el&ewLhDCfVkD7Pb_ zKP5A)Sw4nax)7CpX;8nWaB@;gVrpIVPn#CZ9LWbUd6&EYMRD&~uZl+$9zivuP3(KS5>MY&rvmVD(=a5d>fUJfeJIQS+03 z4oFwl1HlHWlzNyru>1;~KvJje>S|T{%)xhs7uThj?8k>`*tK`nQ(dh*`o~zq|52?M zND^}Z);#pJssJjO?U_BPr|L5KVSs)|o2Wf>CzLA;=G>hCu}ier`Ro!U2$L{oSM=mj zud;7T6IHwu=Ey8KDdP;OXy8Vz-HH*le@N45CtCd<8!R{fXG3>t98YfX-C9tYd3Hr z7l=zdb`nc)o|rRn`xr6(8oml-d%V&05&qh>$l2q>DxeH--z%tyF`=@rzNxMxF=l#e z)$Q3;Q?W|53RU}!?#RlV>QFe{xkaN6%Z>{~jC@+Zf#deC zAe$6LnK3zwas(D-Ru`?xvTadZtMDAhOr&J4SZ<)0|LZ@_gX z8w9<;ez&dqf!icijMPcT6NKD&!<~od7YxcTe<6bJQARP?lm!x10iYy5eFcdtsN2=^ z)cT0Dm0EG={2f*l%{x(ETRKD?@2JGiz{ptPhF*n5KHIj%M|i+T!ivaaO4JbBUJ(AQ z`49;RsM@7H*0-59?!#n~ExRy+d}Vx*k_=^A;+K@Cr=@6JpcyrNzs}iln5urtEJig1 z2#f^sV@kP`rgsU=vPUg};IP%X{B~}3NjP{B;MqsafNyR#^+mV6$uF9mWaZF!0GNqu zA1=lgGi8xV{B3&j(ol4QNUiEP?s`YD6J=XAH^yU04%|nZC=tB(kbuGoBrAEaLEw#H$YV+B)^p}-g^1*eF_AeWAA4FXg%nv6e}!?fdKNDdg!|%a|D5 zM0`A)hd}ODc`2GjnGip9^>*^9Y-q#plaf^x@k1>kvWc&@0i4t$~NKJWKIur}a@A?fbfBRjWq-?e_V%QUl-d!aA`mY?z2l8EuASjQ- zND07NmNd3jKN$@8iLp)jpPk;Hr*qpCeHn4x(!Bdun53v!*|ne>8Tl@I1<)Ry0`zYN zs%qj$?%CSb&+xf~86q5Xf)m`ckK!^R^B+X39eE`e*IO55~?pauV!yE-q{l)@?PW>vS;urA$HYtg8 zJ7*WK1#JjhFE43Y(c@Vd67MV&V*1PF?lAH{J?*cb{Da$HqE=a%(mO*|p={{^-M{|R zWxjf}g;u95Ce+&Y$&Gb9RUz&S5)!J2l{<0*%w*4L|NDISN*m>^rt@J%qLhO&|M|@O z$*-+)vb>__|9znD)6?^x4O#Eg(*4f|21WhThF8_)}rz6Z)l@VeSZ$I7P4 z%=q7ZMs$W~LBW~$x*3d>lmB-`a`ET=$p5aM*D8-W>^lDUgJlTif45_K`#<;n|6EYT z{`W^8%!B{C>(#rgZ2#Vp{{4S%alYs3e-D3C`27D~{J&>}E|eJGbHhP|Gf=fBpA02xJq~2sQY3e#KJNl4{Eq0(lW;!_IC% zTC=T%cBifP(&Lm<*?k8w8~bG@1CY*7Jh(f-{$SQqi?TnP=d>k_9uPb0=ZZMZw84CH z*(l{N+U%+uC<$5CSwZ9sD5gZ;_4VR+=|jd_BJuzaT|^qO4zJd+VL&n3N~Ji++aFIV zx3qPnxCGsA_EhX?48}5hp--CYfM(VPKt*=?12JpBPsm|~1OvX70+|^7c&&NSZDP_h zH*0GWxR&q6HAqkWc>VNFrK0VaaZ7Fo!^0rIblmzE8$V}amxdv2^zt91zU*^iO_Cj{ zXpf1Gguk?#?dGxtbj+Ph=7~DWPlBT16|AT=Ak$o*u0Nyy_&iN)0p1b7vapab`lR2E zAJ@h3xMDU*y*X*egyX&n-JMaDr=4ypR5CNklK##?Fh(@?od3a6D$pF6M(sO`Cy&6R z7R7f@Q+b8+fo|dD|4hX_5;YO4-|`gdmr_vY&Fw;b0h0z1&27b8tC(SO znEwz`05xe(9G|=ZBT`!0)v$_|SKN4?Na=hV@*GznIJs6aO*bIo2G||!S>ni15KPkF zhcgz-31gN@(fTM(40?=O8!^`8aZr!wv*YjG-xxNE{ebM;OEU45Im0uvK1- z7;Am%DqHxUD{Aa@e6sz2xT<=AoHqhV!jW>CSYQ;|Rhv_|Eq3E}-d|2;gEV+ozalh_ zu>4XX%fZ53)gH5RXQ(g^obItNS=2A`I4atYHt%^9N;Tit9=~_6Qj?=Xo|*f6N?*#C zo9?dwnNT$A=~7`L091sxKl(w%vHr`$yE(5PKP3aa^_z$jV4`o#;rcL*ndE?WHtjw5 zCrV8sFagMoY~88^lz8aG43u3ErUuTtHT7#HMk8CrPvJmXvDp)-{d%f9>rCIWCZ||T zo@Mk2(1+CR4R%7<&>MC(OR-@gNBk2|O;|A==+P>!I8@9hjaG{idW!j0*1@x*0|Sj7 za|F9=SBpZhTncv_ACJ2}bCH(?Jr#Q_z$1Q3T)b6*{!<2&=ljTIK++tu-pBoUz!$~1 zemZh;AZB}tTS%2DG7LibM z!$yx{-Dy2}nr|>?JAgA`WBXSsQ9dLa)FCwO`)zX9Sm{!`tdk@vfUh)&eO4;!??_|` zHv>)O?d^Gg7|`z!-f#J9HnsuN2Q#WURG`uH1WnreMQ9*$MUTEd77XK-M8H2mIsL6o zUqlG~4ea<-u8(}hlX5CPAE$YIh4pDUE3P|=`la8l26ieuae*s$Z)1Cu(tqXD#UtD= zR19dbjyp@ZC57^dn>$%Qa2K;4o(Kea<1I?wcBGu;z3ZPai>bE+t#V8G?q!T(|Ms2S zm?Gb>+&tKy1KL`WPHscB%m-G70S1DX(5r;O%oBzU6;4f1HSvBw!>0UzJRtYRL z$XGs1@bdFm)exQUY&a46!b4}i!62klM=O`<^h!+=iMRPAhrwcxb8OzC@rW+X-~4Hy zjQ>s}?QKefjSv{AZW6*3U;glx9Jp=bd42VYJ$O;wZqq`o+)H#`+9wKX!pTW$$kCD4 zlt$V%>`s~CQLTuS;PuY&v4sUx*sM*5`zAolGT&=Rvy5I32rYmpZzQDr(8pwJ^U36J zzCrofCvS45oI0QyV`eV;H{X&MI8GQIrKHqsK0Qc%qOT4&mG+WpFkaow6w}!S*l|bd zrP;D^i}p_`vF5B$2S8*HmO)R{ihUv(c(fUc53(G8cP>df>&Z@>>J#FI>8x#KnFFh8 zm)|UsVO*z&$FdyWYNh;=ilv>(x*W?k!Oqy$){o>%eL4gmU##HC^~SK3|LiOs1SBS& zr|Nil?UrI)Aonf(K)qxQ(cvztD0zgMwL1u`(xoi1k6z6jHCzu$GzzKIEBfp3jZsv4 zY6K1Lvg*m?d5~RXMhoZ78B-E1Lo5uI@FfxWc*!=pDpF_0=GeKTd-vkVfbe~E0lFik zz4QU0;S;mDUu(kn6X-3Io%*B%n%`K+2Kl*ifi0hSJ$vqY9sX;USCvshuS^8iMeX2N zpPl}0;SC$Fr2c?s4FvBq9=M28iIOE9?2enaTSiBMB{;BI@ppFLHGzS;{DWoa4D@TN z{pA$4#U0j+^lJUsyAS~$R1`dFrIN#OiXr#7Qtz}E8iM`uyYeLaZN#6%n8g#7kfSFH zJv$AM1(y?QTL%qp{B&l{glIFKvuG;L5z|E9{|Oo{)f#}44}{u*sFfqV#2yjvqjsZt z<73H}B{K0R*FbC1=a#ma3 z00BNjY}7)a!U;%C`Qux{t(_Ik|XC;wl@P0#J;J zPNx#qh@Dt@VHmme$ZdPv_0Qy4?&m95T|ixlC;8zaZr(-~x1CgBP+g=Y(I!e5r95q+ zOP5MBO9uBS1kwO$2{F8V@WZj`B!+NHkU_y>QaIfIylC3Cb_*!-M{mAhxu-DuuJSFs zicI$*-Jja8rhF+8j=i9hX+Uhx7nxY{kd(W__9~HOjERX|@B17~JZ}oaz{vifS0)T+ z|7u56<3~vIFw?x#rD*y`#I2&|e}*3k1p-s8lszmy%ghnmM26bft#6>QZJJ7M1@wD_ z&>zI1)Ys5bgSEspfncJpP4|oDTy83WpVFW2$J%_l*LEW4JGsqiyx&^ia?++_pIivG zq4>ND^9NaE<;7d^L1#5dA2Zb1sBgTQZ^= zcP;mNwUe$KsNx{Wy~_E~X&imEu`9TFn9lAmLVAv<_>vg!C16i)VnJ(QGYsfh4=YD< zhU7bZ9~6qw{M~MMTy3agJ9Oezf`fEeuHNjAG;oZBHproKre}q~!qx`T|HtIv7F@qc zkU_TK&_S0jWW1_8uNox2?hdjvIR@z|g-A*YvR>GYbE0@swv)+@y)Dpzpt#~A`Od+! z&Y}36M638pdDza!Lpmav@TyO-cIEbcM5gt|TEwA2r&@fnld^r^*RaYgjVTBL^tBrM zBan$-b@3d)AfJ8NX^GHFNSvuk#&plswnAM$QR%=dd0 z5bd3sz7Eh71d9G?j()eY5H^q)u51YpCZ{79(iu8GXR=@eM74k>sE zGml+Y-o=*!Uqg|Ux1uNSRFl}*Q*kKUp}^{t4ZC6DfC5Ue`Ko5L;^?R-MCsXTAUCmP za;9`eBpw_dxvY5+rB|(@!q>a$)KAYaC*|nr=sFuC{i@cC(I5AU9#TZvyj9a|JDcl& zw_Z?T6k1CLYw()3Q$DuG(1!r|`Ab2kSNrtBz*dm0&M`Mg0?nziWcVx*7mpBisi61#4o0q*>MvijRh#{0htrq1`vx>y(Q+%i&RUi zDz;4kauC-alr|n;CsTm*+wcd9V_G3WN4p7$Zdt_{E8%+&kxaEvvwX|z9 ze@xHlCt<9oi&0Cc;fz^+-xbEd55cd09PKD&z=7y0U>8|lOZf{!Z>3f-M9@nMK|fE% zf%~lU0_gP(C{1t;3{M0Kbl)=XHa;&pJ7lGHyX_f^VUbS+JS>w&m5W*Mu@E(QbO>O8iXTt}ASU;9B0Ghre*@SPk89Xk zzSJRSu(8lPQjka4w!!-5*A!eWTWvE?>UCb3-eS}tt^gVsD9}M|lpY}$e*5}dt#A?+ zuf{+*iXYO-8UfcSiU9BALh4RR=O&B9^*^rF$|7DT+LJAAT- zC;XCRLo;+|?ZbIFCiilF_jxTPA?27dB}=8*Br+|a_O3v-CBuihK3!s|YR{My!{>w6 zlfS+ZJPg*y*V))?XP+AoJFO7TUmn@ej{w++@)ghXXt^Oq5yAJu4B-B3;{=lnEnvgf z>Ly~fqJ&@;=%MzLVFHlsdR7?$T=RbEx`}&1aar5(*|$q>*KKx`o$c1$8RvERRB z_=(P-9S9YPiU6|h#lYf)srXUd07S_J_LD4SV$s^I!|stV=qv(dy5G3r6FCnjVX7;R@cRD+}JI2tT4w!x8p5dfXdoB^IFfW z1Ks!N)*R5oL)0fNrb(Q>lZ*<<2M0fpE7pmlZWl8 zt%tt7C+tjo+i6TZVXG&rV)+8I#xLe8aG^FM9KX_xRXJ{-t`Ef3T!qkhz7P3?DDkxp@1 z@s&@JUIjYHh?^`U;aVD8Sc<~3@&b+0=mIykJnWW_H4GJcg_4?9`9jsO{;VCN2Hqp$GYu#)&^;f%?pd zD!${z$iyAAl2V=R^cPyLj0vAIfqI;K!5nK&0lPKXz(#GEu-uMQj`6JRmvhJ&)L60g z9B%bvp3v4e+_CD8@G@#FF&pFMk6YuJ!Qi_X)6?w{e>pQW2vhiiCY5I2p7L-8>Z(eoe7%nLjy4vIm&D17O5aH%e}+KN9)pQ5V7G#GNGAaK;zv4s#QSi*sKbX(vP{nRYvRR>fI0!4z@{gv z3NGFBf*te7ymVZ9Oat@dSrMu){@=WFHLQ3a)yxEXb1%S6ubV&J_C-B6$Ga$2?pJjp zyqd?~3N)-X}UYEq$d|9h)>!K*I{v*ET z-OcpSfU4LZQ$w+KT`!84lx@ss9O0U^=IDr&TLRo;l?E!Ky9t>B=I35%ma7pOTa4Nt zA(sqpWQ|M5qWAa7!9OCHBK3QNGXf7jm(i$*f@WO~|IdKq|EQNz4k%`OTkMN3Nui;G~thWRw!)JQ#J6nci)G9P19+*;Q90*pv2d6fE;upe*g8y8U#7=^Fcq4vV=k0n*>T00t*2Xly7ZX} zt)s4|9h%s>SP>=}`>2%%$0Sj?Xq0X-^6u^U)Hw;~{I0i*)L>LnHA4*MdF^*Tyqx`c zTGKkeKxd=Ips2*1yLOSJLa}Vc$F;WP3~QCXWEeAV2Ys{{kLlm!2Xq27l|CN%a6OuA zL5dMEKnuMoV2NE1YPrl1+3WJKBCOz#xB0#IaUR4#F;2^fVBTuI(jt!@#Y05%v!kD~ z_7?s8G#aC?#4DV58SV!WC7qZ{1&5GKg8USil-zYYdGzy8Fe%5&Ex#G`J<$nj^6`1o zq;h?pig4y=_w|95bputT@t<+31UoB3L0*|)wnEJlHH|gitRNaF;rE(~z~r9F@9wsH z2$Z+SuWxH0Z4dvO0MZlQ__r9u71bcWit35h7K~gAwufF13j#~L`wC3WBvB6Ooz6Gp zq|c&m`PCC*b?ZYg+v!2=QHhK|i;Di!VZF}Sn>_)~maw7oA)8K-s`VRb_cfS7Y8DrK zkHP<@^Ve#F**C^Ar#cDMmOTvX3&2w~<7+e`B|7E`^3zl*B#qh}9j48n+B^#Mu9IOW z9jH_n|DH!@9_4@fAWfKU!+7j1qF7=r5)W;{U_@{ax#M)^e5~W-W)g z&)H|kbzOVk_mBL8si0n zTR`E=(w=Djne{JP9(UWGV@8AE;5sr^VBWPFd9FcidcWWx{G8Yce*rxbjf~f0*dHg~ z`xrS?`c%ak%$x>8EHh`#_jSUD$u73}Yd*DA#{T}!sEFpyhiaS+qf;j_!oW`z5J zlgo&_(kVBC&H@J1umUj*nOYix%&apqzvK&5>ajDfYMjJk&_{qg+yV@d7On6U7hF+* zP}##R1jk_brKiKM8Isj{bE{P$-79onnBo3vy_sF7iKVRIZNhvI;urDJ#N8V#3B|em# zC5}RH-ZgN@?!20~Ak@{)N~Bm0cxv5#3RsY?$fzbs8u_t4ZxgxlZ?P?j{W z3Q0QTh~CUQ`@+F4T~C`}QA6+f)c(Al)rDrC$b^(=mt^s3yL8){1zYvPrf_YScQwdW zazf2Ik(Z__v5cV^UJw16VeBbh3{3=E#G4`Q4V90ckmtIDF#oPTgmrFpKEBkI_7|kI zA09K^G|&ognA}&+o@ahhdld*pZV{|#(1FxH-0W`YnHej<-mPojj0Cm?@c8BC%uc&U zt-fI4W@a9(@?{n#<)EjvP_dcajYB@<5f5iS1P{gEpe3Vql-(|Q%F&Hqo}y)P-$J=< z?a~hw>PSpIwOX!|D8I4UM}{ZV))u2T<0)nKzC&YCL_eSu0fBJjwW~hIb40GYn~y}N zSQN3elMWCl%FRcp`g*bfb00X;EloF<3%oDIq)S%eIRV2>)TnR~kl|O4YTG}A6Il%B zAC(Xq+hS0hk)ktQ-g7v2`5s|7?Cle$YM~v0y|2}*k-)=iu-+2olps*tHr##v?Q5MX zuL%O!xMF`bBuO_Hb}S zn=$(^xpz3Y2DaC0B-bgD$G@Rn3ZPs@=IA(kVOEqbKG;B91tXC*@*CS|@0~8YZJcgL zxiqA|UKh2lk)-c&SmX51sTAM>0bv1q=L0()zIo9+&O>rUi;A#VYv;x>I_?ox5;XcPkAxEzmS9HX5%5BESF;z1u)FMxM;yDoC`aB^oX-`htH?3hIza3 zOYe(bqUC|plh@9+1nKEo0UAjATwoJBCou>Ow?7)XUnbekXiZcbZBtvYn|@ZTlB6b3a(QA^p7zY+wM=V@H6 zp1jeho*#*LR34<{sNghAYr)IP#@3sb87*^Nq6(rjLkyPEI?KCQHq_7+92T znWOPQ!gc`rgYSg%(EBZ4K*Gl4dXR&5Z%ujNGEuzR3x*EjKHW1_@8=cm;-uLKYmF-q z^71hwvpcsoE85?rjN`?~&2hGO21^yvT6~urZs*t^pz!(NeT*@Oj00s07rS+nV7gIf zyMr?6ay3`*=V95+=|Q~a*~9g@_gM8_OneX1A5I~vURq#h*8MWGbG2WhW=71@%5EkW z0B*&8&JIf}TxCst{)h`K3x)hY4-n_zRWRLA^$Pj8I207`o7WS4+U)<{p!_oea0%_o zs76gtsle-Y_lAB#pVr>mxneLK{4f(p8B@JHi)mB)bInq{y*Bqjr?>bn#qZCOcY)6a zDL9ra$Eq#oJB>~+Ar51EK7PJid_9LK^ks=Pfrooz?2a&}ZEd2<-TzFk|7X)^!+cew zQh1BR7D=wzgK{aR-P?QoguvZjJ(ML`C&Hs z>U`q6(GUWzmm0_Ekd>1o!K1Y`%;>~LGE-qCz-B%@Fx%|IVl+hYN~204?1f~JHd4W7 z7@wROS_;M7cq7p0JNx?^=64)R%%)h0xf~f%*uFH+4y+6&hlhnFkBlg^wzqdL?{zL( zXBHO9+S%D<<>o313;Ve8B+zM8rF{L0#(lbytXgTk_|zN;yK@T8V$~Aj(>^U)zJ24*j7Obx8@mU~1*M4Hpy(rV)!QU!f|{T3*^)(eX=y@o2Eo39 z{!d_lpvZV6vZrm0Wt8=aX*40;bPj!WayumJq5iXilwxSyw z8y@Y{)YJsL?ymXygueahsj1IDj!P&hMOa%~Q`mV6FZadC>*=LN$HXk|oghsxJ+1!u z@ndRMR@QY!i|L9)5P=zqiEkaYVBy273aYBnFC?Q!5Io;GeC8FDlx~wOFDy{e(u&J1 z9}Q0w8`v#&JuWRN>Ci8xe*Rn#M8Hr0K9jS?A>T^>YetzKj%8rD{ZVDD)zbq+mCI2c z5vEUQSQygt*=?4nczAfS7Vo#tqoG(@{B&s9eh2hLgZ}u@&6#TO#o+~`S4SID=^#dW z6L__{BVIApoDU7jx$SmRR@rZ;j>9eBbs7)2_d}HOHHi-xEnqd7(!3W6V2kKRL?;`t zS~YxpeAS|lez-5+4{RJ^`Uq^*o#jnVPEv@juCAU=^ty*XxcD9Ce(ocE~^6oXK8VS~9OcoAamt9v`2V9`7u+x73TU zQ)%S6I=3O_aeeQwIla2W4w92#nFkH!I=|qe-RyhCf(3F}wA<(2wO)2h%qF z7$SJHk&%(cW%bK}BPUL-AWA*jk&9iGh7c5D9U)E0 zR(~S-Yp;01bh1E4poQ;3stI8Kovrz`sX9Y9wcU3hakpBqbh6H#(Fm4!(m9nXR^G za7^KKZe2Y+Bg4|Xxk*V$zEji6s8#{{kt)mQ2MB1XZaXFjI=WPe)#=#TOSn2;_N;x>+?ysDQ(}iuVqs=}=NjL=C?_cB z1yVD!*1e*~?m}k)Mx6E~j2vX&XeNW8^+TAj0LFsV$3yF0*b_p~TqoMvTkeO3 zJ{Na(lhoBsrqis+=#He%1`+1x=f@3u8=i6x`^5_Qc4Kq%v0SxsW|Og(AXNyv27A1* zpg@);gTC0onQ8~reg|-U9yjOl#mX6TWUBShMv(B0CQFPs+|Mgu?q_D8c#+SIkSjve?D6)_? z#li+poMxsWj`HGb`Weh~Dsl&t=x!wnsN~Qu_prYwB;?B`3w2gf`GLFO{`^J&;=o&d zUoii!$Z6q5rE!pO+TY`;EE z0zDbYls}!>a;J>!erzAd#KbfTgOTi>MMo2`u&~%6)~3hDGm46e8s_)+_kA6T9M;FN z?gFu%4hm8^+C99g$r>jcZQpiKu}fV~c0=F}GX|i-fI{Nj!EsV;J+)yEZff(csRM<; z%E}7MCuU@HbhVcaKGGY*hRRz!wE?nmO`233!MFuoByGxn@0FF)+uDSBW7&(_^~6yj zL_aFki;r4?)$CRV$VB6sO*EZXQ+*qo!fBQFFVD6RphAp+N_Bt?esB(x^^kfHDmbL1 zq$@W_dd$na5eHc%B?>$V(#Y#?MPn{FVT0P((<2ebv>)|BD+W=%V7{@R*qF{e4@fT3E=%Q#*Gl`)ZA; zGBb2$=J~lfVAS`Epa`(Ds}K_td)R2KnT{(dDH%6@zNHh~nz!r@+)Bie-Fe?|acPN$ zg+-AhI9(0392^|*_^$45^y=QwLXfqBztu4!su#9rn@_i!9|-V}URi~MlV4vqWsmC% zA;B;&R|A=RI72r1drSs z=UeC{A6mbfYvexw{%x5U8-4_vSg@ZVsvT0S<-)Cgt%M)%F`h1_^F2g4@Y6_cq__=;(B4Osf>@ zuZBtU+*3cl9lX2=;Myx0?1uj3z198IVeX&=dV2Z?m6q`gI{d-iM|)tRMk*+RUJJId zscU4E$!a!fGS=`9aDA*Ce;I!&~n5 zb1nB?y)XFLo_C;6EUf^`!n5IxZD8b!PiA2`DHrtY&B~l%w-ID~SAhOy&}h zMxYy*mR44UWfpL{$ZqiHdO7aB9wr^Q!Owm|(dgH@-k<3V*CmQ+#k9#n)4`|=Y2)hDa$Onyb}I@eCtxmBn1dFMbf z__pmUX3UYbHUVd11CLMs4M)7vvqmT2%4vH zk<~bF(DwSncTh+cyCX|Mr47-<0%Sn7+TN`EXJS^C7^&O7?9WYUP#SqoSI7bIl1df| zT(cwmQ(4@z5H(fm!WX`?z8USGG^*{rroEi!{3!Q9b@d{?!vnc=bvv7aM+~ptKVJt| zpV>V8!UX)%?dlBvfOD(@Bv(RK)4QwsZUAhMR2xA6upq-Y2LRfr*&9R0M}_NTAqW7j4I1j|>MgTe?LoxDcSv0yzDbjlliMEs>IEW0Bcprw^iI2SbX)Eg*NK;zP2ukDQOl>T z+~GZbJFfWvAZw(31o(3!B5=)Ss#w-G@V>S`M$ta5fc=s;LoFruroG`u75@GE7h69P zHgomz#G4wDaU3iuzJOw=Nei)_n<_=R0AQ-=+T$fX?3+G}#op%(3b*bqDW3EcE5U9%5zfLfH zlH03`FXyK~S>v|v<*-QU({%>)g3MzsPow&V#|KeSQIUp_=;$nve9GF7SkCtDMf~_N zVe%j!5SI{;a@Pw7rwWfd$b$j$zD06}w7WKU7`gHtc7Vax?3K^6^XtAEpK!n4!}E(! zS#|~J3LM&vU{Dthn$YRr5v@HWCCvx$&1YW(Smd*@iHXZhP@*H4A@{~F^3@3>Ba~fp z{*Q1&0s~}2GTnHW>f`?IZhvEY4^W!DB;s&4&9@76+xe@eVUVi}S;-Sto28xxuax$A zSrru(k$Lme{Z+D=FZ7x#iWFj+$Bw7fG;G97k$9iA&Cu$!CMdoyae) z**e~tPmcD|?Tcma0=W?wcR-%qO^~e&9A5GLU%nhceZci_eCy!g z0GYtzotE(3PFK^(ij8yL7e4zi_`aAoK^v@IcEe|VeLch*USc%t?AD8<>QPa6?<4c< zw46iZ<6$N`LZYfQj)jL?aMJgefU7EKXb=}hyra-3B_Cu!#PYhIJBsA{1FW3kT@Lt= z5TJ=;z*rP^=5U~tlp2p_`Q{TM9Ur9t)8pOu^LgFWK5u@gkc2c)F%DLegKv`v)9|cn z*)vz+mZL*A%1qpR455_>LFer<@i^Vtu+Y#OPn;SXec{MTUN0>oG5`>y9jNhq`F{RS z=XvMVqTEU;Y=}2SYsUdXC1*|ZJ2wdg zSYvYA=e}O5{CD23R%xv_E@Zf!!;FNed0Lhip_cOZqwQcf!T+R!3XXaUKbVL;soG)7 z8|PCTyG*bP+pAjo$#OXUmcyN(;NZyaMKnSZ+tE^wN9L!4=jZ1QAwGZ)b#B=EOfRBs z_HpSn-E3`XF$4|?o|6iS3KE3r;7_~3%*#y<*C%T8vSl?4v>1l;P639_%E}r7C%Rx= z$xml~;Whm1HR26Hz`)YxzzVwt7!`^6?+ByU2+jD!X*@gm&*#I4R-+Xkj zT4&Mv`jMZ?a!vdEy?d?a#dhzqL16+&&f^o;oAZtQL}w6`n`U69z;-)HW4?I3OJdIA z8~$C2BpEF&Qfn;I%t9swV4p9x(q<+m!zTH)W9fQcv=Z!kUEleh&RSR6&Ng|4d=72Y z*tzhc29PQn(2T6)WC6NJalkF^t?Co0^FHI`G0?g#OwzlgO(}(3DEe2UEq%u22-R=u;w%TMsDr9k~FZ3#vl?P?g&^ zA_IBr8mG4&v{c_6cXZMj?>@hcWN(Q$l!>=xnup*7XE)RE%+Ui1*&>wyl$O0BG7{)xk1ts+xLHVjcHM+i+mJP1z zkgY2#FRz<{WiYmElaHT~NTWnbKKuSaV<^%LQI*h3^6VxGpLNamj~||rU6@b}Zhq5L z|D_;Bkl4b9@BV7z?LaBQR%^>xB@@B1ytK5|e|6q}XP^6pR4m?I@bp{bk)ffal$4YZ z)ra!wQW#E>va;U*J|(HJvEQ6#e~gRk-SZ&f`*$3?rPl-JOf1KCwI(#87#JA8F(?0| ze(~z859ye^H20`3bj7k2tC|t$DtpJwCR!qi4o=N(m~tz4`!Je|J9mh_5$rVYGf|dSaaoh!h<=mZw}6j**xt<;{m}14oeS zL!L!~`o32QwdFoKs|wEH5_*>FiNEX$yr9F{(??t|IW;wPN+!oJ&HOgX&w9o%(}?@2 z+oF?NYhxCN4jDD}+6FX)nIMnga4EY2bw$K$FOjA~MjO1XPm4k~7)lW(!>HfgwMMeY zfdL{;d(-g`UX8Uc&Rgj{(TSp8&!lSsy`^J5uh?8l(IEzLwK6~ zc&QH19X5r#zv`y2>BsFgo~4$SvV1huumA!I-q1XyBe-XVVR%8^CzTubMq&#Fzu)Dv z5Z@s{;%;0Wowy>E5QTiC)TMRas&(_S_H46SKlcM$BR3X>7xSmvVwM)(z~g=H*RD{% zr=p|7WJXFxwt%@b%$WH!V=<};GY167ZaP~L=dlSvIpa05_k6I;%+UU#kGq(7RhX$e z=;qV5#FG!#LE#|drg(<2waqqX#;R6MCK!6MELo9AAkBU7Jxw|x?+%IM(`}}!fk2U- zbJxx1K&K^}4eZrND9@_X)~UIGa+nYq`DFLaTtRM$rBu$cNeN)-jkfZJ8eg0 zjMeNYvg)8aZi7QZvNq-NDcCF!#Yl&8&&LaOWi`efYNHU&WF~1yd}v2UP3?Cor3pYE zh^-04UYf*@N5@x4IYQoH(v-C~o||*s1V|pgGtNA>%i+ySUi}`t=3!zbWn~252DLmE zTd-QP;)fp%416xQKBs$q$H@r8>IC~telNdw4Z-e`sKMmRkG_2Q(r`uI`?L_WfKhLj^=W*?jX(r0(F`q}uKnnW6t2|(6 zfPQ|(tGfyRftiOr5Xor_+?Et_UI4WyEF88 z#FH48!wCa{O-4BAi&@m{cmr$<&;9JIp%KSw0n5?4I)!>v4}yF&Q%3(D&|k2CI&DF$3LwH)S5yMVb0l%RcJO5sv- zpthd+K#uRkaoEu?l>Dr#(>y!e7=~Y6z!5;jm`S@4pb!VknePZ#jIN~rOeoK00lR+| z`%5UHdvVBz)E#g4EGvuVV$-2sURYSTqyM5+&J%FXn^j{5dU{3xE$P7J8JBDBu_@>d zCJD}@F~;#i+&fONjaIxT+Se?%kvd!;8w|7 zstz?Bs##HgzJx6>A@cD^u`=Ii~D&9hvd@%ZOyO0bS`J;2I2^a;?qTX2>zqC zj~_o8p6o7i=dq!n=tsqxK&M@OLg#W4LW|cq65naP-bnus@MzV-4_;-a6ORlPzDGo? zfo@P&M~4hBEZ|n=GgYG-pKXC2$Ibewml*_hu12*IpzEYJ5FgVg3JOG!zIBm&1O;W-Eqkp@2pB;X0i zc&R}@39^+4Lg}lYpDf^C<<;o`e<7VE^95;6L4gctb=@@@(X4e=1VZ@t8S_Y>!&GJ* z(GP<%8H9dy=AF%80ia2nb?@{Oup==M5g8Mc?C9udK&NKR&YgjP1=1J3;d(5)jS%F> z0g`St-?j>RLs=OaAyXSlpf{!86NOcA=JKoIztpreW3b+={Cub%Hl-~Pr9rQgod`2m zy^`_6HwmV`m^=X%pllv2gh_k5T>(jC^#H2%;O47zsW>^H>y>K~>yu^+#P#Zj^)JgS zDu%;c_auS8BHLOd!NSPCj#5kuoLui|*=T@n3%udT#LR3oQNV}ayX_VeqMCx6TLS^j zhjMP!VBfX2n5jxdo;nhu?wf-}ZLv<%ynZbUKW<}t)@KWTPC|v`2SM_#YQBAJVV%Cx zgkAn6bkm-toW0ahDBy#Uk+2uZquboO9ptLz<{BNg-$0%zw}6iUnapluvNQy}9uU%3 znl8FFNCxG0@RTB!Qgogy5q!vD`@M+dy71pRC)Tz7DS}(g%vz7;6xhk{au# zuP3tpZ_~co4#+4Zk^ein##$3V<{uxjBXvU&)LlT@+cvN3+EK*-QMJQhVqoAWt#V#QTG|U!yh7mZ8Fev9dWQ}s%sr=cKX}}#>dt1i z?6Zr9K<^c};~F50GflogSH9>>I2X<5UH~0>aq}ukn?0f~(c-$uFBFRKwfoP@zT0NF zEsSDqVYl}~F82~19E#m%n{Nvo2JSa9Ihobg)@DA_3UXf^Q0Wj}Pc#QWe2>o;5fBjY z6VQN8qsI-0Z|a~Emhx!^bR2+|4WHjD21OQZN;J-4=d%y}O>w}~L3up@ow>tF!y|EV z@nInQqjtZ1`EtGRryleOEl=tS@PBWGpe<3T8!Mp9x$g`4k7gVa06qb7#z?MO70?X7 zQ_Jt?TDZ|>-4+Gn956X$^-Lb}yyI>?BO`kYaOLS?d3`Rh9QyT&b;|hzCnhF9Q$Y?4Ac&w&@ya)OV-PX}6xG_+W(>%CmG$CR z0zyK82%Yk&aL}~0aNmoOC5~}NwSs|pjEg0<`g=w-y>Xo7(A!3D-+D+T@DNi?u2@$p zXlcQ7FFjNe`axSsz}V)ao}O3FjiIpox>K5u1aJU#gcW-nt}ZV;?8>J$bX9D&VLf?Cz-%jY4uDK*!xIOn+P8dFO#QPS^dsRjfWf_wvb&-(x0qQ$P_Z0kTR# ztFq^h1C7vc->|48@QtQ~0tr%uNu1u%*ByVzM{wW-(}HP-=ae&POJ#i|=<#oI?y6hhJ{MZxe)qW&o%*{!KhkP!7PPLRNORys2ppP=u;6cD8B3JOSv* zj*N|^0h06>2WQ_z=~n%$CG5Rb4rT->XSIiuCcj5%P6vbCaU9jv)Uv_lLGu*kb!uQr zAY8uYvXO?|Z+R^zFP{t=P%}WT2E9(k8ccn+$YU3EX7E|W0S!PGPEJm;w>nW!-e=}b zq{CeY^Ikpogi4Zup*xFLw#Itj!e$Av9*UsgDIl9d5*N{6j3D8Bfl^^v_aLq2e^BaT2owNM6PI@#@O&kb{MrSNMs za|BN?dt+9f2KXZ9W_|+gc_f;} z%8_lxCq(I?^LGr^24}qoU!r&ifP_xV$*BffICA3R{$St)Ks{N2tt61)*xNgb)E+}Z zevXg7uT-Z4?aEaU>sf%-0Er4rbKrCLj)8fjPv0n6g`7XC1}rUcmeh|VKM1zZIB#p{ zLFZs^&$D~LQEHgw`LyXN7%UVJ14R`u@{E3-GYNnT!I(@WD0iS+3IyO}Rd2`&at`+4 zOK_vnV;kN54rZUA2$vEta0DjF?9yA`=lk_g#E`@;49wxbrXez*^j#rOyST~l5e(O4 zr=+|C^%6O~1k&30GN`=({TnxZxfjjtQU)B~d?&gIt=xQO2q|#~7lTp^B;osW1pk2s zaUUgerVW(CpzkgU?#Y!&W=5J@w{*vf(^Y^;~qQ8T>|K5OB#XlqbGs3^P_!kBLpD5VA zDt3U-TgTa<_|zMOhLm_er2@k<`)zHsMi;2(<+rvJ3v!=M?h7fTsQN#B8#-g}5cDL* zh;nLz)F@2)VZt46heJ0w`|>)h*XKtu@UMlN$Y&crrTqQWT=usB?4fkrLxM^^so&2? zw*HLF&LP;yivB6~cZL7=C%_i}EC!5#^3P#_5&p#sFv7odfsBWL*%BDxU$Fp2_*W~D zV!%JB0F3YtDgYz=g9`tk^*^Nak68T!ivMW!Kb-teRQX2}{z+>8Skga1_5T8rxVh9_ zhh!)fJym)AB@mT}C$`VIq<^Pq`qpA^?`1dj*}26>NCjL(oehU;OU6pp@r^CXw8-Ctg2i|H*5>Q?^qHQ`+1U&hVLmFo_RP6SMzxHZidmG14G@os6&Cq5*T;v)UM zqW%RAES;;9O^i$PO^*NORmSQie!d~4>=X7ASRRLLTxxpEbz>oyS`m@W-(>f!Mexi( zf9cq84035U797uYxwrKrS-6;lJD%O0D@HoVfZLrJF_`=#xt$5YVY3{rvRT7nb7ndX ztGZY?p=HvlX6rVA$1SQ^^z2R&GUda#@gCWG%$_@r!spIObmk`RA|b8%T9FGM(J4)v zAl6(ll$f-4)ziV?V!OZiNsHc>{)%dIx#ncxU->QLyNgwkGEUT=as?bF4Hw| zp7ja)3V6(A?i?GIJ%Ggx^VTu#HM-dB{;E}pD1Pw9^-}1v6E-}oA}ys~Mp+ym-^Yl^ znX=PY=_6rcLfGp+;fv_)35${GtJ=hL#=XTFqhbz=wzJV?WwYqx=&sz0i-YVXC-j^j zrx#aVjhVt+T_UQF;?W*d?+i>QS{XRlNMQcX-;P~+WFM}q+_x^L50C2Ohk4KK%eLy7 z5O?Z1rwYz8ntE~)+!+z8=}eTA2Kj1Gm0;5P0k}z}n}NQKF1W{#kWIhR$s|Ip{D?JH z1HRjQ2CjCf^7DA2zkZt~*nh4?P-iab7|u8U74%Nuxr`8Bs8jq8 zthT||5AliLy(PVKv(nM?_05NOF~9iZiM|p0!uRY81qI*JPWJR_(s5{hi=!Ge8m$HAF(H?17x zA%x_IGi5A|!{w2QWn-!}WgLlC{Jm$Pmd_@nc_YlW-u)RwDe!zOS=o{8En?wATB~_D zSTDanA>C4oNAcsRXfW$#z(D5Cq-R#3WA&QbhI!pXZzbb9EoAyWVR z?jK#>_CuaVbzJ{gEvL-X(`UyGoO+~=K1tPeC9mH=Efw9FW1S!PI@!>=EZi1f+n9W1 zLl+-tyOu*gvIJhAh*M~MJ7!2R9@iY@?tyTVc{W8`XH{xVX>yZB-*jd3fKsyQN&)mfNLqWG^Uq9cy z`h|*S;TV&2RIg$Gi;P{A=PuY*xf{zn4RfgZfs(zrc=t}pW2pR=3jM&Zq9<7n)1qE) z-zj4E#61)PV`kvhfEl8JPfqVEVsYo{s22^sbH}=ofd}_y(Jal|cODh0A5>~JXc1Qt zQWvCkVxG%a)9P?+ze-IY zD9^-tNm8MeTz~9#0&zTY4)&F?-~MD;!kRw?ADZqWsay=NX#XPWxmPb;yL^!|Et+nj zO2W(;NPh2SsIG2)b>QcFf1dR=?!DXOo7Cm|iyM-*O?;(>=52*nSf%A|=kjuj-NIZi z_|ye6vQt!QP0K0#HvO^mPNf9Hx7;X^yiT_nvxgGbCSncS#QwIvd?DxnOIwk=(inVV z9=`A~`Ct`)-*07XsK~jS*1B4WVtIt~km5jd7qP}W`&lv^OR<-}xXhUfJWJ}gokZdo znq2a?Jt3Lff%&05DO90add_Vnt;28ZJ24`j|2U;TcEWH!&XQ~tfGJ>##-v%BI`_UJ z`g=~SGU-}hjx=!v2`+Xlx**5-&zU9+B`<$nzKLp(*taL8D|ZS0nAYf^l>`%a*QiY< zVZoIU>B^1jD1Pku*BWzQqZQMFowgpk%_<36IF}}IUP&@`lDbB%;@iwcIAoSDV};sS zy9CQ$Wx)r2QNytlXfvZi%A`yGo{o;9JaeeA-?n!-_4)7>S!ZVxAMSmXE}OpT-LAy& zHxvhu{nRzyExpP>x?)MXa)G~_S5uf_c;+~t{n+gnacG#S8B2VUhu7egTNF6VPSMRw zczSAfemLTw{j=W&?%y5bDzF9MX&i~2#F&S~hVgEPm@>yMnqjN%UxHpFcKuV zKf<{vaiHa%3(`pJl=!oW$TIW)tyDy1xGP1q34WyL1-%Fb?ktMi`C#=)p<>0NhLx6I zW9W1;csA|h`fQkPe8|*-b+*r=>x3hy;Dx3C0@7}VrsWcN4y}9U&p%-)$*LN&7nl4^ zlXsK0u;e9(g{#NVtg94%R(>D%`ubOC7S~ROD?38}>}%5TPH}?F_N2+j2fS2*9_MRs zsnNjQkA~eFJnFR?)gNCRKxWHX98VvZDhPd~ea;#mhDO<@Y0=26Ay2<68!=MQux#fPV2;!WmD@2svx3trFj zq30Pt$AG|)h;iHYY5z=W~B$E<~VlB)*$azc>In8c~Q_wihS|%gEF?@s9q(&!eu|Bsi(w>d6fmH%`2ErcFf?UPS%Dyftp85V^CEsZE))46b((J>)I;k05~ziPSG8cKm<;hCxu=#XKwE zIQi-YWEjI*f49*$mD}OQ-fl9B3XWJpwMt`YK3+moF^QPSyyVMe4Xkg1e*zahMG6l~ z^J@7k?8=_K((zLjZ2uuAA4BLZkDh0%!)!FJ2)lVnDJUvhrY6l-HdP&@1G zD4mRzV2FHQuCmb0WTzRLr5n-Pt@shxG<5xrHe_bLfImzSak>+9V8BX1Xo%K-LS2VuFgRj2Z+>jU57sZvdW+|k_ z`ow=zOMs%HFa@Mh4I)jD+j)mv1+Qn-yijr6QW5w5{FZW7V=6Ojgpp9rw5IL;|E`c& z!+2u);2u-hRZshZ#komm%E8rtG%61}I&o&K!_Iv!#pKT8y3n6~rFmg!j2yHElnlx-)5H zdSbFabZw2LDZ}a|wqOd7V9Aqm&T>lH!%Cu0_c3pWV z<|cgP9ZU6`csA6`?@y&j`)OJbVMc}LwlK4+RjIM7*=CDjYsUOt@LP$!j8f5@kh2S} z;$NpkbwaHU{BJf8g1seA>_PonE&uCr2R!H?h|0uV<)Ugs;M(g~-VbKotlT@;sumx7 z#nvkBX3X0C>cbs0A#28oTCIqUvyrr|r0=|Tx|9F=YCWg_1g&45uN>^;LuIK12f552 zaDMShjHNg`#_*~o|9ZnGi(16&&+hnqzGjh!ZWK1c+u@Xyl;Rhv7!sZbr;MVT*jw;v z85Sllk*@rpj`)~ssMy0-h6C$auz*uuwYpj1y=4-Ym@<^?6E5cWM7mzEyTsF2Zfyq(~kHG=rHyFH!G&);3`UDagrCuL;nIag;3MP7&TEhn4ZFkXi#-qxv?M}F*u zjeOQpms*#v%YW#}lKM44OZ&Q0)8uYEV4iah6}9h= z3y);f15XnLs4FAzIp0oEl```FI4!X2ZVkZBxms zja_`a6;BVXsj2>(00(5I^dUY=Ys0)Z(3>dOMUT#1R^<|$&cdGkVOrE38mYfFIm5zi zD#)KotCP)cUO0&EpuILrGb_1A^(PbkBo`cJVZCkd0H@9(FA$mA$_Sg;+rmhYzj7Ts zxc2l03flYQo)2=ao=Q@A+$yZQnd`FR(PeyBG)`*juXjx{8>-FF(@+%1IJ>b^8XYt^ z3ih9BITHxSmkqOCUkWuf+l0cidK49LN8jCrk7xNKY=kh66%Ds4s_dF4u#Dn=e5|3X zFZW1fAOEY46~*I6a_&rHIeBSBJ6FF=7!|tSkjtj7p{4&V5f8UT=%DZNU}ndN(1)&9 zg^Sr&B)F%NGME2YKm>fiAJOLk~kQyb7j`E5F3{2EYjlB z?s+%z1eO-87}qcG5_y*j3Nba>i<+Yy56`pGX7B3vwmhLuVPk936NV-^9}H=>ey?Im zJtocFCt7uA^bvZKM4u?#uC5{$>`Xvsa(wv36(-Xkuh4JhQn`sMWxpl}J6Ye^R|v?; z#23u?b2tQ(=g+tfV`qHCIZJ$Q;zrt-4~vzo#$%a%_O80pBD+38(c3nJ!L%-_7~7vR zSC8gVbQTNzlzI$pxaC=qOZ_R3>RC18(|*Qj2@_JzR>sLqE1XwqU-^mkt8)qJ9>q@&535=UTsw>(1!`H6M~wJwSN+{; zrH_o%U-g~*`9QAse$SqBI>}0}^~msldAJK2_BH`q9=$;1-1&W(%e=^p=A$qr>FfV* zN4sNO{lK4=;*;R4n|f=pwPBZ#+^BpBuirl6I?3g5%~6R4iQMpSZh!p9e*9Z_WLonV zx*OMp#4ux3+f;X=A6qJX#9i^mPm{C*@RRhE&}#QuQZd+0+I1lnYy0ejE%j|gV$@yn@8E>YuSZCaP`F}{WO?gdaGvxRqS4zPC65*sC5x`Te^vDZITelH8d>RN1^9h zq8Jpo;ooo~5-QrBz!-T%`RB|dzAkk?VL`R+GkbXfqfV%k`=RHe;`TrhNOER`c~gnJ#wG7m!1zOaVHZ&i%UNzYAYY#b�AN)pabKi!7 zT_vBlKBhTH-}Cto3HxK&-EZPcudhvho7L-4uv$Xd>$q0*Phx2mgT~uYHs}JrM#>WR(@xirj#d!(Jlo)7q^Lwf zH%S=9QAK*&;%;AS?JLn2#?|vX`!g&2L(MG-kB@@!VpJ81W)uc(GOr!J>+*CxHjKpT z`@Y7qi2nY!hMoy+mC!I^_muNYgWy{air1cBrwaK9LNTtx%upM~QxWa4rf(n9R(dGG z6RhMS7m}sy5mU{q7iwWt=#>j6^-<3-V~L;6Gr9MnbhI zJ}+eanDgpUCHYZTOlL#{XO;Xqk1Q+ET@lKslGwZDIq_S29r0`vL0 zQDkdy@?gLgCTF-{VvodZ<&(~!)1WT>h~amCSQG{eenGefg04ngACYZ_!u0FarIgUJ zmTJYc!4JCTzl6cVR9<{JcE2LME6!1sNNoR(O`U+L1MB;U&d#GqoOnoP%I+eMf0~8u zsLfxjqNMux8~*wUI-URWzE4h>$7+!!MJG=D)y2@z?)wHArB{QBdhbr{u1~J(tGndp zfwT1!9yR?J{lX0XW_y4CZd;{PYsBSJE4ElQzo^;Rf*3VwR%6tnwP)g&UUBd5oSe^JIq&tX*YkSb=lw`F{;3w!gbc2bl|0e7y=U(X8x=hj z+HXUtY(pN~+o1V*0K&-4B!;!Akxg^%p~!-qz6LEpmS-rb_NNkplLU`B*O$?kai3&( zrH6;-OL0?s6mNI=zdSE}GEThwX8EW3e0qw^*>h=nqVdDDb!}3c|0EGobV2=l5<;Zr z>$}l>&CS9L(z9{tm?fUm_&ok8>}5f$3%glW-y8hLKB|3jqeFreauM%I3VS{Ve6o$1nO7R5B(8`f z=4(6G!(mVzD5nQ4_;;Y~+t(%nh_4B3H;QR|x$-06=08KJeN>;a^ z>QWA>?~&B@sbl9}V7VPA|lbM#8^Wghi#kw`@!pC`8}wggm_jb(^- z!2G?;+F}$UE^hJ_a*^YdUCzT7{e|G$f6kDHwIF*LR~wnT%p9v{to28ehx? zXdz20O!%|ZJ*T3*LO-q)4#@5bZLz7u%l$;^4*4xkio4iMZhSqbKYBu6RHT>d_j3Fr zL$Au;fXs8o=6$3CwiGUB#B`QOC)%K7na3G|H#!T_Q^#m08$JZT*;KyWP+2@2Q}kA_ zl)%taz+O01Y8^7=@p|{0E6)+3>inZ>cQCF}h7>bNLw)kX5R};Fp-Hm#&dL~J4$xp{ z;^viZwi%>gTrU^5P|XVLOf*G1Z)=*`lv!jhXsXZ%BN?T#o33pKu7?wAt8z2zwT6;W zLxF>8HJ?OC++%AtaWAVZ&Bbs;i(~Zhkk`U3!@D&nHuP-z9p(SZbrBV(+lWdw%JgC= z=yI`G$B>}=ecCc=HG-R)NejQlDM+7NxeB;Ib+pgY<1Bj>o31gV(L!JsR;U+eMvH8X zuMsWuS%+SXFFE(9v_E+l^JGYSAsRL!$(`XH)ZUlu4p99cxiPrqkfR&3+?iv?2UX3J zI2=}74q>5X$Brc-QwC)Z+^~QvCuzP5qgsKQd5l&3eVt{3@->5Ilzr=vA71gMUAp zBJRn2_gk)Dwr$6RyPxfDSD;Pc>UcIt(j&)woeYbM_m1Q7VpYQ!JwT z?P1{7gStEc@CTGSG9ZEGGxD@uUq&{h@#MX0er#sCa? zh2=e^2A(;kSB~eK?u9Hfo8GMR3k7c$wv`d&>N6#naQ_i6Ok$GZa!kPYJX~VuZ8Vpc znc~)1(9g0Esx|I+(UdVIZ7FpXYAdHYiVlOz?rkQy4rGgZb?rSpsm9Df>(Itbv0rHP zP)KFH6ddE5cJ9%3SoiGgKF*`O65E7v2^(A94C1-?;Mgq^Ir?z9nWEFTBmY)_DrzUP zI{l(ntaL=Jqr*+=coK(NoUvS6=bABV7_!tETywTHp0_nIlDby88>QJ!x?%gwHL?q- zSRs;&`(4RuoY!ov`HlkBilE$*3b}moX}jIu)b+heJ0-n|dq)Q+4W@djNJ-wv_j<2< z&b*#ky$LW@R;{9Ks{birL>XYyq zu3fk{yMa+-3y!A)L zjQK7u3vzU$o-h$Zd$rf~R!By!d;1FK<#IA_{P(ueB7(el7f*Bvf>Xn+ozKDOHO?VGr! zu&#yh`GA8$ks47i$2+i3MNAN$A`vzHn(~Guxef!$yrOBn^OTKg9zDAiB~3Q+DR}b# zj|xGFZO%ayqTC|v-9}ljk_QlxgbDKJm)+nYP4x?U*XHbx1 z^!I$nXe_>67woccIj({HxSbJcXL#nOl&M@!Ra<=`JcJcNXkrrm;-!Uh4y5q42gW*! z;d0Vz?hh(vJoD|1YGTYaPJ;18V3nEVFqoH8dR74`;3p4~ZQk7QM!u*xt1DE>qNtp= z|DlOZ3P)>{4u}-@?8^~F&+2%Xj8HdjO8=Hs?kV0<1)#HTQs%q?7JF z?}I>!{d#YpiKin`jiulsku$w4BLG+wn=hztSH)DU#0Nn>m;6IJa5Z!Z@7tqvH5u~>U&hT zi140wweu7Yd$$Sb2Z&UoDKTph$GM+EnE^3Q+jo;aIlIVR1O;+DRoD`EEA(?()~eE!b9B3``xU6A;|gu=neNd=0&7rpnpM)Uc?gBn<$ z4sAa+KB*!;*IZ;XI8$Ur=TvswWib>=tR+hDikMbh(wErqcR01X#37%dqC?YZ@zR$R zw=Q;|%UkOeoWe1iAqev$s6lH^4Qy^n$k^fKCGZ*7X-Y42Am}2q%*9MU7Xagvxyn+{W~W9lNLuDsOqL}^0;4=0hcZq56I|n2V-BIk*<%G*TfN;f3-RyiN)xA zHOyX)Qfpb<>TJw2YHQAy)S2#kunJfN{7xJm4|g0)0A3QrlmZnGY#4=#5`$$ee#}zqGxPUA)quC#1*{Wv=OfIfli{H)p@SS}-pxw}k-W3>Xn_wBtXs zF{jPK{i4tv0@9v40 z^&>DY9ePNK3mb&`@X<2jY+QXocZU5lC6Y=A?Y>H1zUEAZ)!e_^cggs^&PK}ZmY5T} zh4rJfFB9ulB;LLGRC-tzdWUd@rQFL<02IG!jGi;MdbxKYB`Xq%q~a+h{{M*#pe`Ok z5|cYdORCuKfRfqRX$2fSGMU|Wv7S=3VFI7GpX~CBX?3fjkX>!5JnpxFBT`QE{&bKp z1O962*pzPj>!gjjAC>d5*A$G#8a2`R)F1Ut8O_aM&?cx87M+=`y(^+WP+GfG$gz;6 z25t4-tBzm6^u``Wl&ytiL&cK^*V|Y`QR_0%($P1LNS3YIEHr!e!ZC`D4ZJ`15IF~% z;I!4QY68_~b2AGE?G97?iKU>Uoo?@LlmamJ#t}wE7aZ1|u7e!%z;+vAUp2B+Q~r5A zB*AK={e5rfZcLCgSweEpetHk$n(OrBazgV1{iX?CW^m5hc5w4o@Z^reWN>IaUaqsz z7zQSUhDwQ}5>r$biCCd6k$b&5mELt7lnTazp3Y1p1?sC1yVTxBh)dayHW%neDjCxq=P z%0zLW`SG{4OrogP`nPZu-2XNSHQwE;{9A9~V!AhXV^ls2GOMC1K!F<3(t(u~ny%aS zsu2aT6C=o;PD{BCP9 zZ>u{`)~FhNG84ahi1bY>$F=Gq{kqfFI`$lQf2+^@c6bg*a2rQ}N4o znC%XD+K1Pl&^F?+$+LW9I%|sGz#KJ2H$ph|N-Tk-;_894^=GTWwy_k4U~11QOY;6d zogd|`L+j6_@qmAYq}OiQhrS?AsboR4f(h-$DB-bbTy5UqbmNwKC`p{8D0`1v2rBeX z(TBOg|9P^KmNU|5<_&u!$r`_nrYd6Bc+p#Ih`Qe7PBWuuM}+jW?9p*L>zUhs`C}|; z2R#>g6nbPbUlte?pKCsA)E$2qH&#(kjF=?jHC27M5jV`Oc0PID>%YZ(<^(<~Ox-e7 zS_5HsUC>RpcgpqMjSqL&VR%+&mDgs0Z7jm*EN2E*m@ar`^bbbbu`n+y}XF?Fr<-d_f>B?YM0=ZK=o81gO+5XrtX?; z(}ZU?aUV#don#t60y0mJ%Abipq->7BM%yk4ZH~NNBU$cz@wvbT8{p!kDIrJbP56AF zQl}eoiST}1lH^pj1sUNi3*^xoUpx2|hBBC*OMiR{3R)3jv7(!qZ7gE%GZ$w(%HFW) z|6+hYSPk_b31KR%Xw)kPr*2k z&=G%n+8-hLkX#Ag4-*b5O4RhjwN)FATIPokY9RL5kbCc{gbd1#z7XA$X&mXaV~JD} z$|I6|tvH#(Ih7Lv;V}Yq8Q4vXw-2oSr)|P!!i7epCw#Z7ehHb0UPhxH2m%F8x4bIo z%)qfc=b!a4s&b}v;7<`DFwVE6bQVQBKL!-;$U~o9QlrR{kK-;%oKl zZPrPTX!v>6()q<5=$=#ACnPZvH>Sev-FdFx{3`J5qEp{%7O}BKc9^@K!wz`T_gBgK zAKshlkaE?JmF_hc*l0Iy5~>b+!PCA(8w)@kN9s6sA$V#Rx%92P_55iF>=Co=1s@ip zSBR+`woTR{u@jzr@~h+j>g}Mdc%hN&lUkH#Er(lPT}MT0lg7|i31;BGl_Xe&Cc#&C z^hfJ(AJFS7;dRR^=0}HXnWr+fG%b^QXk6Z0%gLULxgrF}gVg^FpHQ$tXY9WZ_+udX@KaDq`#jCK{Yu(x5WPg3`B?( literal 0 HcmV?d00001 diff --git a/Docs/Documentation/GoogleAuthenticator/FirstLogin.png b/Docs/Documentation/GoogleAuthenticator/FirstLogin.png new file mode 100644 index 0000000000000000000000000000000000000000..18d4ce76e69dc9747ea629fe15e6d99ec1feefe5 GIT binary patch literal 21106 zcmeIaXIPV2*9IC8djUa;0)nEVA_N3!(kuul#Y%62fRuot1!)0wl#W;c32l%fBE%>V ziUE`om0m-S5IO`55L!rbHqJo2uJhxab6wwi&iT$6e~ip#?`N;Q%DwKjp8XhlRbOlO zjsrU&5Xf#F?TgnTkWJu6cDZd^z+Z2L^@AZ0Hh;$p7q04DxFCAf-Ob+7#SQ{F9%E~5 zeNyMt@vpaUTU&pvmpHM*9dSJ*B;vYtd1Xa?MWtw!b+u@6yt(-g0j?jFK|KDYH5J>^ zppy^kF3+vrZ_O<5XYk3RU%49|RW70ivmq`!!B216B)0WwQsVW*#GQ9WAzjMfHftW$ zSlA_MhW(TdsZwLR6TXj4c-tK!8>aQp6sM>+cYJ*nyCDzv(5^dIAYJS_T!mXglJ?v- z3+nu~KlFq~;nuHGA%Yb_t(BUedn>LJVuDI_wiGL6NT1dCv-)`g|AAfZTe)hbeWZ(| zk4wkP3P>BD9y_fVn{N0bXrJ;Z|4lx-Ootc871=My-}P>Oe&0`HGCv;Jw25|P%j0q$CX8yI#SnsOn1vhs)(KAwVQqqUjc8H3Ks<_{=SH6Dn z(%;L$|EV6n>*;w<845)p5K;(PDK~cqsEm@55>)y$^z>;-FhkPgzN_bLA4yjavA-U& z{+x?;9=7g|_dFflTt(NOd)vm%%Tx96;kAu6{`@7UosT1HCs&WZj|C10UHc7GMoJpG z@ocbEWo=aXs-usci}6KAn4PN!*h5W0UQy-O{QuK$SUdi<(uB40jJ(|MD}VdV-z!z1 zYX|u4K!0iL*CBC0u+Zk_hD?oZxUHkmum`4yD z4S_0~7k8af2UfWKcNtOseKsxVz)Pu;IRP z_7wArJnC}B8d94shj52-T;P7>mZT*6T*tU>N_MoauHPY$cK>UliJt{y68mLtirMd% zvE|72io1*}*3+!t7*y~CHDgEYb^m^f zsC3xoBaqiV6uqRs9xJM0J-=NWa*3FLlKHjIniR+Ro zJ=$1yNl}_OJ#4eX$ z*kjIGj0@thZe#L7*3Y{(2}tT#Q2%oMG1hH6Bdpn_#RL7xXDG9~jcSHxzUEeHjC#Oc z>}5T?DW&2PJ;^g_W0e4hz0f`)^XF7&zQdbt$?jVcq%skvkq~VLL49GkGMc!*mDE+u zSwr7!k8$l&9qg7}h+g_O4F8Hac&e%7-K~kaF`w~QOT7+_(K&vVi3f>__H|*`sRGx1%F<(0y`+esp>G*g35#XyZ~&yvg!%LllxRqyzUTX%b#CMo+uCMJbuV z4ho}SYWG^X3Gs8m2+w-kQi4HrbeS7UEyndgYwKzuss*>;NYB#KMT+$Q>{uE_DyoiT zB(!4tj}@X6B{R$N3_c!HGo097p}$pFWapkPG4EcR=K_lfA^e8uQ2xL_f>MfdBd)S%Y9jUQvKw9-Fplf1Qg*^MbHD3rRf}Z_aZ#F()n_EYa6B#`B3z3U zvP_H=Q@j6DnQZAZFkUp$jjrBHlzNu45HTbEw_By23m%=IihP<(>zqTWB8naG1y(AD zE#%71NHM-n-3+vPm=v46GGo&&a#;T0jU$=ViT=4rpV1q{$T9y9+N72arQ6;mV@OB6 zcVRLVd?{IwGD9>L@3>X|3CbAz7`GTpCw)r^ClNo~7rMVRwe&r~6iyJqjiQ#XCUN|T z6bbK%>QOk>ZeO~xY&=^UqJx5QKQ9dQNTe*cl4>}U`F4_mjQz=Y8+`X4Op%VNXT-cH z$Lxj$w_a5#CibJvwDuv9;13UG8UEvu;0=J zu;cRZB`t=0a>-03CA**FbyiHuy7~EbMvVK#(aIEuCf%Z}8i-_b0KH_~lb`4}&2=db$aR%2DW5mGXW-k)DI{@}IEiraLU zx-u>>SZVZUc{uaq;!@F1kF4sd=tN;HR|?HX1s5b2a6XrG2F^4HVYgVI$LB)$RA@>xw$XrIH#RMvWZGSPJc{1%eW^xbLMo!1Nu!ex2#bR= zx;jlcf^|`-GXIOZ$mv(c1=acSEq3|G0)1#$QjlBJPv@Jm*AHVg6G#TGQ8~w^Meu~_ zX~ac;Wn6!&pGzn1P2XnX{VBu=woWlb%ku5u&n4q$mE0h03#) zGK@Y#^)u7vV{V~5-eHQv5uBbDtK~oE>6pgPPrTZ@e)JhtZIZZ=q(>AQ6;cpCd~}bh zR&GDuAW1~<6O%Yt?K&sO9Dd(9_0`s9_0SxtFs}qv6+EL)7Fsvl0H5(Hkz!p!DTSA$ zs(PlBhlMX1@G~j8{)>6E!Kemebrm5iYm-AjzQkMRT;up*S&LQmr8(N5RT=j9LE^nR z#rdBGRqB~L>$|B-RWi;{>8yyZ<9(3^=>4!;r4lJ>2HO1O@dJ})#8T)%E7@cAWdVkD z{`IYJ>f&@5Ee;(@?*E`={>iNB6OVp0skNH9Gl{bX>uR-+vrJBHLG^g`%Z7H^E525I zMwM7WsqJ_|{A^7ZoFbSUGQ(K?wsOYB7fp{!QRlwFseUF32o7DH{cL=1jts{`jcQ&* znZUn97_k@0YPa)wsESA|^`2ERtV;1Ke?Ne~{n72S8x&zqRdocgF$&AHI4 zl1$!H%0zv2w4D%F6S30u8ja{Wme=PuSF|$Nh{rf4zQP3fBU8Go$EMkx|?O=lun#mHk>(QO~}5zYU}-pspsgom>_~Y;PshBFf@+sI_Fh-z<{z9CAtpsuoC3S9B=HR;6Q5RZ(uQ zx~RkfxKAR5adxnRXC_*wFO*zFwyzoJ!CiOg?XFT#)%H1}PtJAMsw-NO#4L%?YNAk4 zp=7L|2LXwUl}{}H8M9cuKdWx$BR&-y!?_+phxj^G`j+)CoHFC)#E)S7R@J5_=Om?# z)aN}fLoyd?e)^1x;ZjI7ZdJ(&9f5lMsm@pCQd&yKqY){uT5i1ds~n$KBN$llzqQS* zCNhVwsTPz3>i0}UQZEi?5b?;x#BtxGH=}WSll-H7=;B@`YIywCq{ZNsonfQ(}}Z!AY9h9&CeXMh6lCv*>Da?gf>-^bbSBLc7hmwL77u>z9ON0_<5yBCk~Gen@|?Jr z@=@gC6k~y1xXpH{C1pmW)MYOPiDq6BqRxyTR_GgM)~|N=%@oMw(Te-2OL=hwtLoH> zF|ljIr16~&P9DqC_1J1AK^7O;3(=cZOtQ*L22seBcIp)B&()CiYW#klE?wr*ZF zl43gQGDSYxjzrK&nb8rEwMd+!5Hoqce>t95JzKq~IqKoabC2Bfs2__^DXW%(e`zSV z_~)oo{+Q=A?Ir4`7`1ZY)LXap%nYtm0b$KYGy=b3EUINr%&0*?)x9m)|*Cpb%~mC#&$ z4IaiYx+tGJ5jk>;8H?2^$k7$GW)~h0d#1(IvxR%B0gbZHsq$=#*}b#TV(}1_12l6A z$@qS6!?+-#FdChX-0Q=5Za}akM%T+5AgHZpX$7|5zMv+E6?09mF``Eyq{4nxLrX6m zl@d=)Ur)I+g)?Pp$OWtcKAX^gP~7~UhHkh0qK^`p$LGhl3>nvOm>i zk>Zx^RXUCNIZ7FuP&%={>lhiT4Oe+NC?I>NkXX{cyi+2u)HR@dy#jcwVQr&T@)g}@ zf)*Z+qPOJhEcBvNM0PrrBS(9e24CE0t)|J#%%sAcj$%&YCEbgAW2JW zM!0keXEoL0B@a`k_n)ztAvJ!Ye~$OKIzdb2?C5FlA0F@bGNt)8EL|uOup0G|Ne*~x z`SZt&(L(ZaZ%_3-g= zqI^8!D+At8z*+P50`b617xN({+0(l{>?OvjZmDyc?3cN_G%NSUB4aLjYW&Fb7{S_` zP&%KpqB1@PQ#>!SC%^&L>RrV-qhp}mp_Cj^J7dLNIwddJKNq7=xN;@1WB-Z8+AZ)O zhoGbSyNtSeIRj6ZF+TU%(x!JZ3P^dOf2bFo@K&1>#A(jytEiUE=Do6DZqabNy^_rQ zV=+Lyz4WbRK2w|&6P-t}TIp^QL^Fw$=_@Vr;Q*0__m7(e94r^B5kXqIDPWkC?7p)d z;bH+V$HWl$z2eFI*xcN4p5Q{RPXF!>m<;FhwVHB_N1Lf(TyigBwB=ZLwKFuzPiSOH z{%qkD{zdg-dKs0`-sfAIVbET7?oHN$D6)h5rGm?WD^2|WA3Vnxb(OLE-X=idNEI(EripNQVD*_kMkjr4Yp!%>yAkK#63b)}SxOjs zTcqvq_bgHvv!pyL+$*pl0AD6UMi^-6Chapycbh%oJC%Q<+g!!VDZ;AwWZArX^Uld{l0|76(;qHK^FD zbK8z=RK{2DgH^+EO@F7>wW<5SqxWI2KVL6;gEWT0s+U&h|DO}6^T)8~K6Ku(-%fIC zU(wWuTAS}LvIn+n@ERG^u}-k%1ZXfENnEd#!J@avMcLjAz72h~ai$7UaHfZkS|c__ zGmOMLE)N@3U6(5}?=kXRIJvo4CTxK)QHbWY`ExK$hJRw})=AzZx4ixw zPo<&i%7N2E&!s`Ez{GxR*XTKw5&Cz(5Ja88TKDdK%mG#ac3;w9Z<4>_c$hV`1+)Qo zxukDl`EB9e_uGqLu`L(3<;PXrb4fT=qT{J(<7gjY-qYLbPIb4_>=|Ly40n%A@JiNJ z$4NM6mZ!nOJDdy7HN)G1YinF%Gk}C$&emeZ)Nat_gS`*Q+%U36>KhQRZ(jJa1nJfQ zvTX^!yMr|pwxg57{N`m<&~`LWeO3Rm-bJWB(k#E+yvJVDgEUg}wcXji*Ssfr@T9v1LE?~HzIGAT`M7s#LoR<(JkN^4CMOVuIhxep zB(4G|zzvORV#R#EX~nT0hT#*@kl<^Fp7to3dS1AjXUR*GC~49hMNL8p@{7!YwuM206Dzb~jJn94x{)?udVddULg-O~m20nI+;9!d{$Oqtl>bT&zG+Rh z-;V(Adu4dx6zkBB*SxQ)qC|Yd=vR*cHUEQ2sG!>X12%^=QjJ8h@chLgY2?@HXF%ck zmQt%}^xx@+@u>X@gu++GAX^84ETQs0mP+(0e&w6HvcbKV+D_}q@LRdc zI?7Vr=jy3(IdKxe>%o5|lwI@s??s@(m5gG;p??|w5(*gNHLSWmZr#?_H-WodqRygJ z);+M|E}$F{g}e$@>$VQQCJ7Q_d#&5-hWcLX0dH$A92~il`iOna@Ab0AMjCsIiVHO- z3zTEi=)93i1gpGL3Pf|9xrr=hs0N58h;4^?*baSnr<~#WZ~Fh^&0((TbzX_is2svX z`YlOYcw`wC0p*VA7@dp444GIdE^4_)6hik5a92;!7(}%su=^CBo zr^hkC@2kSaZXQVRUM^rCNXa1<1BiG5_(u9rR@$K*yn2E9>7iJ9b0Dbz>jj{1YH!@bW+_CaZ48X6;$C;^M_u6N*Q8rk*2L-G|+i2 zAAq#>v=tU)UbO+S9LleCmt`bV;KX--S!5m5UH}NVI#|8;086)q0MmMZIl$HZ!D|{q zT?{X*zdf{W6tFiVtWdJsD$la{L)sk73#s(b{FLS-Z=?Z81KYr<#UXzkXk8UY_dbQZ zxO3gI3`UG#1RsA0Z36>Kgo#GVY<_2h%hx*#0eUR(s{ef9^}Z^?83_|iX^^nSa~ zFI#Gqvui3m8d3fR`%>3l8yO=Z7{zcWjeK{X`}(q=1a=MRqCOvJ$F;%KYa^z>Du47kmf_4g_JIP}e?*C8>#{ z98oYQnvD;oade{N{>mHGh-=l@I=R3x4l~>-|n~+VYE7I)Y%Qf;mSU(>pcwsHr z6ZQf>-meN{MfOcyU^2{Rp5MaX9(Ygvm?JCJQ*A)>g-OQWV=a>tv*x)c>)XvODt!l7 zENX-uMAxZqD_K~0O^YrLa1xJNfH8)i5s6mKGVUENYKqPVI8&A&jb~WfH3Ab`<2>)`g$<{h?dO^ zcWT0ZvHvOzrlHRG3GN!a;Cf>eWJ*C>t^rPy=Z1JfgvYOx_2(JcOL^shzjdDk&{Cnj z-G^QJ`fLqI=YIpeG&@lJUJZpKECh++2I&0a6P#s?h#&xk98J5|n|L4|(m6nIpSVx@ z+djS{^7lpnZ$Q7&DO8R%N7h#v<-;1Fgu=Tx!^YR`BtA0KA$6_dtUUB%d&MvBU*Awe z2e`vglWn(uP(e>FbO~^5TO)6BU3HflK~97KFMyflTe|iR9IvgHRB)A@ z`wGI`8L;cR%4@MGE!W0{wfY6_ujQ{y(0@lZ7&l9{j7Ui9)SqgxqUVvF1I$ zNKIj`RBa?G9NkU=l>i%i{Wd^oB9aR?K$hd=F+lb^A8g-XfI%9vKo{-pHTf|zHuvT^bf+m5}YwV%-ajiMzm;Ql?4CTtws2~r30tbK@0i>rwkQV)mKbRxM zZb5%}3zxu&HFvq(|JyS!fs#s^ee5x-t0a9Li1H8Ej$Vb>Q8#mT4&TkDI2n(0dE|or z8%>e0hSy{FG-=M6mOvdy;4V9y+d zB)-U_Mr(K*zef5r@vuxwz&DLS6iF5P{&HI>pql*J%L!Z8JrWYUhHmWIZ&}cCmmfGr z>AUp%tfAwgfcple?_jO+UUL--!xoioH;q$ufgC6u4?CslHKqcn0Vq>os1p*(#Kd#W zg~dzmpfm^g58??Vqyty-)Yq!w|BA2tVwh9d&!YPBAA@BH^86lvEmbx~0uBzc5Bk*y zz~g{gU_e8^Fc8#E*W~!tsMOV)fP<%9pZLumHUT{do=Q9Mn;uRAJ)F!q$kKy6;8yvc z4=1p*hSC7g@xQzdYV^JQ$4frT@!vh`)^Td$dRyvUT%t!#E$9u5pd_4+#ezx-5Gy_y zYVudn{`dlrVBo6!Z_Mr4Hqa*c!1ZOF%>H70-2Y^fJR9dPTKFa(v`^;O3U-CGk(zo* zLy&P{;jz5Jz;Dw$Bn|+cl7`tQeBr-GY`sD0xJ|Mfq&ZN>8e;1utz7{J0Knl}3>f|z zEfO<|1;+WMgSW>)p!^T@B3;C!rB<=B>g6~yLwT?>|X94`fEF(q+CjgxK~vP`^t7Ueslz?ay&3TZ32O_K3~F?A@7QGvrHm%J6p(E2ikXfaizB0us_7x<**n zn4`JsuK?Kt!1VF2?7i-Rmk$H~`*wcY!;MT%&LuVrVM2w$xM?^ZFZ3v4Bbw;6mY~ZID!(kyZ&uu$W zrk*;_cGUn6sE?)l6QrH2vYp_pkqkCktG)L*-w$%w38QVA$nSnErRIBub zFno(p?7NU}J&hs4nF}1(((OoIu`2i6dhgGC@o~Ce^+@upO_u6N)jI__CHrVXRaATd zDZl37Wl2k4#P-L+F?f_Gc$YuW0pWaDhE33-40hBH=GSHcSMrF8JYR_F3*-nc$rQ#tSD;=@utghOx(r+|u4bY%JR^X(X$W?uN$ zZ*ks>>hcX`Lv@Oi@hhDUmVVAt-9rWL?*bLee0ojb2A)-pqbYo{*OB23NJOGPeIkV3 z5M`!b;O*LXE`J0s5?hra9-x>v_Q4ce8}(3)hd)UUJ1~@;6~`McrEhPf8G%Ha`}JX( z1)AUbOfN^;RvwM3v7niA_b{hQEu4$K9TQyi+_)GS1n8$!>C}h#({@hz3kRnknZVoL zVJOv_IksJqh^h}SAi8;n-dXNb@Um+17FrJ80%bT0>xKlVB}o}0iChZ!&9Am^ZLBs(y*RJw318l6a$Q{03psNva{#DRRx$b#w^6&36~Z{`3KnoEp%QJBvDO z*e|rG0=E%*53BkhLfp%VFqp!5I9z-;79r74D#{=|8Go5{Q;l3t!-u9Q%h>Db6@Rf+ zs1|2X-o`IPi4Edf4~BhgC_Z^iCvN1$w;?p(0Y-png<};p$)%or9!(EJ8Hr zVH%})(mW`Y&HHm~t3_I}=XW$sWbs#5kD7BSFcH3bcfULu^P#)K=XFG)EwH&(5GZ3h z13u2HfFC5brD+Gaot5ZkQkLNrLr+LA8WT|~Z-tZK(|E?oe&4UFKFp;jHWUMqDB;Wu zC2!#z+vawD{AMGf(0F~STupxGXsRsPm^yt=;1aiw>NcY#wSMb_7F_c~;(qCTp(S&WKl;WO|;+(s&U;WK|IRENfRv;?t2I)sU{eG;7~uAIW(bW<>YLSDxuc*}hQ? zJ?M~~WfT#r+Vxc$a;$1!k3@>AOVM!YAdEnVtO6*331Y%d#V1#Y}>xOqNx zczeZA(r9L!z3W5?SNU|q6H*W-nQO84o`Sqk0BMH93m>XgGK?~EBVAOGeg%yA3I%+D#fj68X(ap8y3hgOJ8#Bi$}6Mqbk zLl99l7ThAn0WOy{rXx8;?q8gksK+#U;?8X0 z*^4SM&z@|ZiG(J5y6Y+<&_#=()8WH6U&|(i=Ob@3DT_5}nn}&eTD60na6ymu#hT*f6 zw{jygzx7a*vG}=oF0B-#-PBwUuZ(xAqs6!C52er$PUZ!2#+zhYlT#(bE%Auj3z#1x zt!cKyY2b!u*8DNcm}kM0&#Z{A=VDuJ`;`I=4_71mmc{XdyjD@+zR#kQw+O<78tF^w zrGY&^`^>7YD3}X3;+8mX^WW!ux^ZRLXzO z6_PkU51)?P5of;7C~(rvw-PJkMq!IXL}s@GaiSV>+(Zx_81+I$tbzig8NbP!qcBQI~~r9TBW#c7SYC5}Mfm$90Ga2ZYK?rI|8n!}0^Jt3>X|&u}pP94vRnI0T zpdD3VeuML*J(CB@WN}2xv&#Hg9yqre&#JD`EW(2lsYjFOu{LMkWe?5Osp*xZWfQ!x z;K!1($h((H=8$%$uAs|xJ8j%oVpBho(u8Ls&d!vH=_?I9m`~6}n5*_>IS;GF)v9LT z)QvpV+ECU)v@+i&VcJ37ttly%R2>8HZq)qSK_m^mo2pc1YlquZB9 zs$SvJgSbz=?;F-DqHQ;?TWcpn(&Kb&2oDi@Gw}q4u8uoSXl7f~eh+mnTd0ymfb7_2 zN}la>2u|LL50M#JP(b>L5b2}JF5=&s59Gu~Mi%3Rg!vO+Fp`3{LL)0%6osMbk<}Lb zgSI3b(-!43Mx2P8!3_=;+1%IarL;@5@Pw#otz-m3156SFJ4Z!ynfQ9?!4;u9ckOIDQY zml5|3aQ#MB-YP15tCa&5i0?*OZj}2=go0XHl;TQ?R2c4P>GcK5nr}km|)}aSVRhjB$oFRt^|otq?^TX&A&Flk8V%DXCH!2eVaBojJO|Fo!=x;cAubPX{wOFi`t)=~ zIIf>Mv$Bw)TRLxvte0tFJl>9uw|YzTC@b&uB^m6|J9lUB#>I^W?T+AN?;|O~6NUTw^+r$5Xti*R1b`ZP=CLB=~afP4Bbq@vNCYK)3lJw)NS@h{iC7DdSA4 z`qF34lTSpg*N@7^ZpYK<(Wv_5NP4U|q~Lg#LCQfv*Rg>wPv6DsZ&dExrav;`EW@^n z=rTLoxP&h}gGA^tcah^|Y;C}$A%V2_UcbGrqI0ZWAu|4GU;k9!MVmXQyBbMWH(-10 zN%quVKVXwRdqFAlLclH^_N%3HR;5dEkX_W-@sxFOQ~Nj`uSgz%PGEb80&}dMLQ^#8 zAczQMu^I^ZC@|7z*yhg~nimsg8{3LM!8#)uG{x^?dC!QjhUlQDu<{xH+lztHwKfM# zv;N7t5J4L1ps5jfFOk(2ZgO2~bC_NGSET<}X~{)yACK?ya2yGE>4C63D(h8TDr~b8 zp{c-m{7;p~N7#&u?hRb6dFRG*1CA{xnr1ny8&wyD?i~N^LZ_&78~XxeSHXM6Mi6X! zp$%Tvrd4zO)(ii0?fTlklm1n~zh3aaBM_`#b5|eUw;un&+}jd8hPE6HIlnEJFTR9W z?(H=W-qzXur>mI%=xyDvTV#nMn1>L^p4GK~3*bN9C_C~$byM`8i}!zzm@5kvwK8IAa;N&k^7>du93C^YZByrC+#A6bs3GkQAH4fvtnFEeJRQ=oY|q)*;7 zpH>=Ql^?My%Z7lbOzyjb_ZjF~A`dbZlF{w{WPJ>QnD{{-6(Vbc#yRsd_cr!=Ih~MV zIAg%wh8y=b>Y5i9eq@P6T1lqx3-gF;;?Is~u6lm%E-E}Lu3Y%8?;BEHndx?thzKMU z4TF?HvDt4tL3?j29AAI0S&_577m1{6 zCe%Bub}8TT?p>_tRDAhqX|iX~F914(Z%f(n?uOD_?Ikm`Rgv_xrLl-JNvE|#y?AaFm*2r;hW5-CoIWc0N6`xadf@v0QCM^`BT)Qm`*qC5vn0XYrQw z?dQp>E4I2OXr^;ne(J%w*sV2ItJNncpD*m0@@=JCkW<%v| z90!>qt^1vg?mJ@je152HEX7fF7rvxGgf_;8udeO|w(Y*ptwPMk-d4x!=QNSvR!t6bx zu+U?RkDtvN_e$%Ikv~M7U6!3pxiX){k$N%w5DS+|D!$A+HK1CsY%s=%*!9o6%`$GT zbZUxKA0Hy`$-GT>M5)s)GH+r5{*rA?^<1q{o}_k)e7`#_Pp#vGZuzIBp-4D_XcX3g zzMAu~UqBG1C}p|SS7O_b9N3E?^#lqDqjS7|o>!SAC%u+!C1~^OKrZ=ij@Y=@^K(aV z0}>~bY_PrJnA!Axzl@JO4sBNLCMEAjqZr-CYG)>pJoj)TJ1I@&WoM@^quIQ0((~q3 z9a|H5N@oggxa3!EcbuEf@>Q70Bi|=y+1RF|h3N}tD1^C|{y(zNq0S5s80~bxGsp|a zGgap|sshP-PM!>>z^Ni?x(^8+hp#b9uU$}AIl#GUHex{!lpk9d_Lm6|Y;2i!8_Rx) z2=p55T-B4X#b=XjCK|?Xy;if5?8aIUMjzN-B-sCG8{|Zf{VBIuo-NM)1P5yuqaROp z@_W;j?a-B_W%?f%-s&QaDs{pr4G zJzj2cuy&F7nqjfx7*!5F7X$rODv>^<_KL?j{NVk;?08&dx`2XX zP4^dh=FoNx6!iW0`fKF368CPa%np5|{v@1=prLE~nbDCodSQ`Pam#Kk_L~d>^yonM zZfep_rMoOwFVGin)ox|p{L{H9*-h|(;)C00%;(y1frV?kwb!+G)il^6sy8(sv)$z< z`wj4|_}a@JaHGxVf+UN>-qZ&iw)iNI^m=eZf?oSN#O#+UFj}-|7K(F!EjU zRS-)hyTIpg(mrSZuPe#rr@Qh={(|2g#dTNv$A?;}@Dn#OAB#hFW3pMIq;`XiozN*` ztc~T?-gJjtv16T}9h4I{{pc4r;!q>?5K!|4^OG#)yeR~#=$;h!Wi8tc>~&!9I_oPo zjRH{qw_B<=vzFZj#Y+=c+;^67-hvC$Zx&WUlUeod1t8<&qMIzcUxk6~3kU}DtYrtl z1xUH7jMFT4aRLtX78jVdap6z2=_!!$kkm`oS#O#Fzavw5R9VX&gR6tP;s2^=y|w+X zivIPY|1SiZOWRf0Z;{XSCcUC13`NZB9kLqTj z%*i!ynxEbN8#vhlaH{##_8T}k0&vQRGx*6`b^xRRxseQc7Rp=(;B*q_|KK-piU;5% z110dWSv@0XTppIOW9f-eP{;^Y3;spuzj a6ZcZ8*^Y-HCTsshp^m2h#k}*@5B?853l{GH literal 0 HcmV?d00001 diff --git a/Docs/Documentation/GoogleAuthenticator/NextLogin.png b/Docs/Documentation/GoogleAuthenticator/NextLogin.png new file mode 100644 index 0000000000000000000000000000000000000000..35adf4e2ee594fee036effadc86a191c3ab5b792 GIT binary patch literal 15031 zcmeHtXH-+$w{HNYO0fV+5iB$jf*`#rs1)hFgMf5G2Z0d4E+Q&TL8N!-gkGfyN+*<1 zf+8)H&=N`rdE0Z2lK;40-ne7DG2Xr7@F65~ues)2bFJBaYd_b~xRSg7hO*%y zhb$7s@4bz9WU8^@WC7|fUZNBfm#AJRf6)8zfzEybG%nM1{1%TA?gY1aRedI?O@Yil z@(dX#wLOZgbm+ngBe(ylcRg+7MyF5xJYlZ^8Yfp{s-%3D%wTICHr93Sxqwn7)feGs z?9E|At+!exoApNDgw?50)<|cG$SS3^$0V|{o$#h&`YIAAQZ2$S@=olmh>7T;s8oEW zQEb>5nFUq@7Kd!dSbiyTWeLL;X~nA4ipy}-J1t^hQ|&t~Uz+E36zoIVVl6CcinQ7l%cMaPuv%1Peq>k&fs{^ar2q= zhx=~FY`3JYiIhy^iNta?3JUyX$|p^yi9}+8IGfvT~T5HT@G-bdFgtJ5!i=h zX9E*o6V1Cab`W=ATYJbo2jM_>Phg)wAh|#p;H$fXuPt|=yPJoPOrZS5zedOa-+z(8 z7rFl$;_E7Z(L_^+TN&c*z%4F(U0CFz0xdT;x16{AeHlHK+yAfwzvM4E`TBawfWZL) z0m1=d!Vqsq@HJ^^X|RYWSX5L97$M~Iz{A%zP{_mQ(%+N(o=3&O$Ijc?)7Kf|!ToDq z+j|f{U-^p{e+l~Y_qU!7fzC&gJbeCH7O+6@uP5MZ!Xn^5a|5h$zo;@g&VdeYCMwSE z4jw*$3i+_B8T%R$yM( zrL#f?Dz0zL=;G2S?$HI3o$Gc|itN8}Lq=-y#bDKELDsxBR(cizRV8}G_Uqu=pMc2WnyFqlzamE*_9H>$ z)ZAf8g)D((!TIQ67c!aXzbJo`g-&yWhReuu>VPr-km2TGAf39-l<7;qDb&NFWaLUh z?4GrMPxfn|PTg^85Ip!`N&eUL|1Tyx^`)n0jxijOzL8z-Vn@mnslhs(-X%!+#6|SS4nBS${JsrTWt`fn0WW zhl2l^N(mHh#_JhQp#*NI+Z0c>YPhRWRIGYfr%=3j7I)!~O#quZkoyVZ!w5&pE$DJT zC^_^t<`X~haj@pD`Rig%%%P#(VFgdMWIAj|U2CxPn>=zZoz>y1|7f=}MdnVt(_%re z1qWx*tpkFpoS%WVoWdQ!7fJ6kS#w_Ms1ts0dN&r7bA!#7z&*x6@v)*#u~sXi>IK&C zvOC2z;$)vDuLur328&lAKC*OXhURf;EycCZ;eb859a@kUu@NFBA2 zCW#($JIHJblOs{y!mBV8znrID{#H%MJWtaiBGK9mUE&jR&MN>UbE46DNx7~78bg^6 zEA>q;QRQnK%P|!@KeP?K@i^2>KH%Mcg-g-?KxJR|isH7U=6Ry5klzd6vsnO#Iv2sP zcn+#PD+4!#u8uyVfjG6bDtB`P{AjansN8%I71*w6ME@}b_1oUfrnDie;3mhfA=p5H zz__{?BL(r#yiubrEmO&E#8>5?u77v|%Zh+x1?hSq4T@GOS^ZiaA*!ZNCpkDO9XkBV z)QEW(nfcXG7^L?8P^1IWY`u#CirL_4$A^k-&`iNJ?V>oQ)%uvF>!6A+6ctBV-!OxU z>b2QBar&2XsvdX75#ojy%P3ujH(fM?z4J#V6>iCj>%14l=m$IgAiBRPYr1L>5$7E2 zAStvrd%^*=_fA5h{;trybOR!uaQy;*0#^nscvHa=(F~g`1xFWzKD?ceDv5i7BG5rA zXNBeUI7A|-HrRh3)m+=~+(F}-0H;MdL)t=HS{Y@K3W_$2Q$}l6ZiF{Xh z&`QQ7({pTFE{#@l87o=@v@yjtBA%zV<)+RYWpV{>{G|H+elBg|<=ppuxvH3Y>0#WSVw?NxhVT8fd{N^ZSC(u^Uo=q7Fqr9FwZ}{3W5DR4E(Gj$Tlfy?t@c)l z(ie|>Ds8w-$I#Lvu+#jLrgm{e5pCZb(gT}J`+9pi<6YY6iUH%waLOtB&eA_|V8NVw z3xl*{4P7383W9v`1*^``Pwl=DB-_qPK&#mBV_blq3ST;$jnBZ8RlMGl?(v8&%eVrd0 z$>`diWL_ayrRrX^RCL@jtHMj)uSxSz+kSQ6E5yO6FYhdt-EFn3?*Mz5Kd8OkP03O5pjF_=R>ZO2z#z8)Kcikc|nR6jD$z3q4IvdM~J}db!JSO06t(@kC4PE&E^*Y#JXnHg1&}p)MFKIr8GT zw#&<8zFY3tgvMU`ikQI63R}=mnvQH1TEdd;4@j;F`MIm8yEhU+rSY7QdCL zpPwrj-`lurNNFi{5WwTTv*;cCWn?@8y5vAMH}^w26_c^Gn-SyD(0v{wEMrgBtd&%4 zP4$E~uLmwaticlMmH=@x^BrVek}wv6Gn-gjL5KV&EnOVNt#2EF#`Y@C2R6L9k8Qdg zmCl|^5Ep2KwTfE|c}!*Am<`C&#H4?B?;XywJ{7Wh`?G?kuyC1L7hRF={1joh z(KZ%YS%cic+`%>PJ+FfdRH&U+m$%aiVFLfoIN?lm*DD24{x3ebts2_-4M`$((dITr zA--eeN?Si9IKCi_56oPx45Gz*&6C37R|e|c802NYghCJ@3<3n9A-c&t0jWyu z=;95FB)voN+t=yOnO&k%wHPw`o zdEPxy@O!tFndtYDSJHjARal)f3IjBV*VPlGi7hPS4?pYn41a$?xxbPj>DDRK$d)Wi zkyWLz$K}$N+&6(ZJfq1ruE|-fshi?zmZ#fVnRu|+ny4_pG}!(i>Yu`kdbnO`U_jI_ zJ8HS$vUvsc=NH>{3;#l>|8pUPz_^E-tMSidA(1?n;mhmOb~!K;92|?^&oio=Y_h@9>%+I4jLi6R$%CQu+ zw+UUmHU4qLNSa;*=B-3LbhTKfqbjW76a}ke6Vt8pCEyQU`DjpgX=wQqg?JCYd96}&3eljkf&+3wH!skg`soe^xo&E5hvZ{0xhPBom0M@ z6Fxo(&XaMvNYwi4Z1e6-_g*4(OJQrP86natpIAPzvKK)mPH><*SD7W>Xae@d8lJz} z1^HdTaodyk6rW8!zJt?|M~#M68mY&eO_Dv2pewf?m964&Hi@jPC5~I?Ph0!vTitVv zsvlISqS^D&m^L0%4A4{G1Qj;OnrSFNa`7;y<=%`&J&$D%qqF1lk$7cPU-ccX4dD6>-aV_+i;~{5oV;A`F=kxb{%lM%+{U+Cyy8YFZa%t4I z&qG3Z5sG&rNesQgT*`$L*?7Yx&~;dO1KCfO2=|VrePUU_#ZYajSfNd~xoOD6oFSpO zXv?^wC7|y=I`lLm&PhLxGC9O`iB5fLiC!>#_x?OusGWxe~dnLKr6h#J?3 z(7>HI@jV_zhhDvbq)4{~XL>fX0mlV*>y!zu5xS}X{fXvBO+VXiA@^`*ejg6+Z4^~( z=wm0N1R9&jbn1s17hnsoj0-2diA7|LuBe7Nba^qo<<>q7o&6a1?y==+U&?(H+Q%m5 z-Wsg7nvK31^{TGXLUyGDeJa2HG)-Rr%8oDsle+`qPt&k9?0v|KoW9= z!Vb7~=mEtHD58}~mAwwknHhC<_14jxschuO!dzy&_O+Imp93pEocKfE)IgjFRGM8-XM`z4OV7=U`@O5*EMXMVR? zK>x3Lnj55od^TW3V#@prN}ycI^G``wnVbQQRoSm0k6@87C2>F%MDwf;3F}48Fc6dT zrQ5+I7RY@9fD>$i94~$+e*jO&{N)JlZBAek3m}-d|25wK*TzGS1U~dBuYd+r8nPEY z!sV&I6qHt;Zn^6a`j+ojyC60NY5Kf;qD)jY7J5^?Uf7VPG~8}AuV zUVXX~Pk@%;O1qHV)>!s)bbmvF zUUBZc^g}DJ=j!e$p17#8OInwanY^M^-XJV|3=->x+=UsRE# z_uyQu-J;5z$@s3V7~IXxWka{1V=A{M_(PREJh1gl^3=ANwhx3O-_U=%na>!#Ks-}W z|1yhB#!EN#(5c5l%2I4?BPDphn;xy#Q&UE}gU%}ztI&L&DC+p)ZDHd}X-VfF%a8Sl z?~&`OYAEuk-1pX~`>q2I1Dx~v^4;Q|Kja!Zpu&If3#1)+n^4;PEneeVmCIcIH5u7- zawxR^BibH37~e>Tz&(@|N9LO@a?FSNPos>`5Pb*>Y{V~tSrS#B);G-Lx0B}7t3w}oXzi+s-4`-G_+nZsM5J&yZ0)v! zSxEcvI=8T!HnPz*9VktR)#gGLOdK564C86zb_${P8ez1Ij!rF~YRq;5%z4kS7qoq? zbJ>2#n5*GRJSMdjb<3>6H(9jF)6CYdN()iQc(=cKw;^$R%&p+-c-eJ)V+tCXcG}nV z+nw$ZSTT~vgbQk(CTeuGf0B9GUhv@x2Mt;_@MWmCBP$Al{e;zaMwdm$2H9EPax6mR z?|hikrD5|#9gE^}W0)>?_S0<1*H(G z<`U&G2qnB-+$8>f6ql^U^KcFPW2!3Gj+k;dGw(GcnK@D8t55jtdphZ z6IQd$*nPSnJfL!@60v-6_L}l=xkG$5gX++{o}B5qg6m%P+4qY+6#MUuBVCQBcN*m~ zs_$B@Ny@w~H9aRm<`LlbDSh=p*oOn9<0+2gW)G5ZDAwXt^Qwsl<$mVh&(d*E_>F#1 zI~3g28aUusC4?06PHlx}gSCx6kEjJXjrd#hY!ptYQ3=Vdj2Gpc|B!pTJlF-_(riDj zZa?l=w!li+=4O2Rc6?c5LdLa`ud6<5gPEfm-2#dluB=*v$Zwq$-%)seFrGqoq#Jyq zgKNRp)J%Ng0$k0q@IpBE57$S8vATAcaqCCl{%4|O7mP9%uIi(}TW6+3T3Cg>D|-=^ zP5vymj#qIwe6r50z;X#dr_S)qJ1(XL^D;t+ zjS?mM7ay~4uc!hrS-evpo12N0MJb9U-juzGkTo9O1!L{8@K`V2i;PdFU%{`SP?ryo5X z4mWHzQCn|(t?{hHpl6ub20B*fVjtG5$&oUm@{6Rc#QksPdAqRkEJaO?+gTR6(??~< zqco+d{t5vz%l(}S2PJ=py)8*NTKf*O2_ikISlbA9h4`6m&V6XOG+;OJwZrm6vXJ1A zf}qv8nB4b1Zl*?vys;AsjCbeV)wF!?$}%HWB;ZL~@YKh>XecKm8eTMWC2(C#vS}Gl z2X`_PeIC^)Wj3HI(N)=n#XWGY4CzEwE@rO|mj}qYhYCvZ_<|cfQHb*nboklP1l!j)r*hlT5Hf-+(PDs4~A^~=cG!9Wl z(V?QpvbD@MwGSR{@JLi<63gl?w@++jG%kQY>}c`3I9feU$jaBKk9su4`3C$lR;F@S z$?DHF9<@roQu1qYxuRrB-nhak)5BSdV~`k*UCN~4jYLIA zKH_OykdAouR|3XK++zjY;6L8ctTNiD?z^iq<<-fVSbL~kr#zE#uoL22Y6MO$7EnBQ z>YYJ?qQ=Kf^`4}MDILf*RMlKD0{K!YcP}s_o{E<^&=NLthSs8Rhf8O#?~w=eMFO=@ zplAML5UgPwX6|B)BSbx0o6?|R?WByy|8(kF4#x|k)(~$K2vF}vIKPZYK%bc{BMlWY zWlw9}>LonwK~nQ6KId4;iwQIg=QLnOH0Gk_PXDR8!=Ig|9_Iv^ z-%S@*t{r3ZAu3nCdI{|E_*?vB_Tpo)m82UB=#F5CJjYoM_ev_)WcOXo3}}uX^Mw&YJI2^m5sm|a?+lFsHBgSmP;MqSz4ns;2c z$I2Y%IsY^jN`U?mnCg9*6SxWnb|je>KJaY72giUHX>&)Eo=ErghYQ5E4{1?C0p zdrME{UFW>A#C?_}^Y>R*CxIlnYCFHtdJs)7>xY47X$%a67yM}S=|GR<42jn#`FwzK zI@tgvmT$p4ap7GvbI^k7ggU%*FmzYrN-6P777@QFMvT8PB%E00Sqh)BE}2U1bJ_nQ z+$aeo+`RzawQDTg^H~LvTi=vJxC$JriA7JKb%o3Jx%;gYFmXf7qh~r`GHm*uQa_f zn7NEY&0MuPf0~Irdv3UtwP}bj{OuWvCWjxp5AaN@-TgaHwen+jdI`KSM-rXyPblUc8Wm{?9-{~Pc4 z8}u;ao;eowT9_>V_!HlgBu(nGQ$UkC>^Wfa=ggBG%jW}{)Q?D zr%7H2=r10iRa~RN?o_`}67mfN6;UnAW55uzn7bb=(vHRLK%1@jh;* z`+&wG>`aLdNq{MS08339&hj8({d^bD_&&u=pCgRnmsQBPV{3>1TxbE9);j>x`s}9U z#6aSS^{-L&L2z1UPIWOO^tubD99o+3`?$h(t!N zGay4VQjd$o5pAym{y*E2=1d}ExB>vCvv1`wl7t-*7QkUQX8Ny_$Z#LPlG?lD z@S+kUsfu;$>*|w4_Y9ui<0o2%i#`?%)UR^bOO}QE-A{ zbGM|PI?{#cMJzL0oshC^kLcvuN2`t_g~w#cn~!HKwEaFhAo4hx6|1`2$9tdlil$2N zWJP?1c~4vGmJL}U8mc3(gsfL|EDC$h>xSzATz>oE^4d1$Yn^eZ8=eYa*sJ?^k2O2Z$_#gB$D#O+F?TI}6*-2!c(VQz6CjU)U{z^sUttCvw{K!}a{`4Rb5B@ZxZX zZ62#u=9RsheuloUVxA6SzkxAWR{8a?LrlB^8r9H{NQe~T^Ogvven5yBA{4j&1W<&rd@$cfU`)P1LZek$nnXT@)-{a&*S6 zeEvSVjZD#a#h74xEX?y94f5Ar_uuQ)(XuHkQ%Fw539&DAmueUkKi8aSnkt@xeX=PG zWoBHAFWSz8viH4dmfV)YmxrQsql&wY@$*D|)NJ{{h3^dCJO5jq({! zO2%50n{BV1AnC|bFNO#BuWhe-jQCVzmaivg$sEehsk5$vt6B*Yv)1^84U3THc)N== zmjgf-A8b3x{#I_rEBq47B7KrE zS7mqK%fMYT_oLow_y_GW2Y}?{s(t@N%V#0s50C+i@0!?e$--R?ACD3Zt3od!>M9~& zQNnnSh>JwdFiK;_w_C9-T@V6>&byCL6oJWXfw1qdv3wXk#X3H&HQ{fi-Q9H*jy{{) zjHo&$ewh~!pC=Hx*Fb^p21|^;RR^wO4S!vyHh;fFk^<_1N_HLjY>WhqD>b_UuLKlF@e@d@@l;wM1u{#8Jo;Xcj=nU~yCT1j$;!z)seS zyx1lqp(Oy;O3*n&lBApI0227+Md;C`l~OZM;5YM}X(v%*Jpv%nWvKqE+FzyHzgGMA tto?SYe?9cy;PFpC_ixDk? Date: Sat, 24 Feb 2018 14:34:38 -0300 Subject: [PATCH 0762/1476] screens google two factor authenticator --- .../Google-Two-Factor-Authenticator.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Google-Two-Factor-Authenticator.md index 9a098a115..16c6682f2 100644 --- a/Docs/Documentation/Google-Two-Factor-Authenticator.md +++ b/Docs/Documentation/Google-Two-Factor-Authenticator.md @@ -21,7 +21,16 @@ Configure::write('Users.GoogleAuthenticator.login', true); How does it work ---------------- -When the user log-in, he is requested to inform the current validation -code for your site in Google Authentation app, if this is the first +When the user log-in, he is requested (image 1) to inform the current validation +code for your site in Google Authentation app (image 2), if this is the first time he access he need to add your site to Google Authentation by reading the qrCode shown. + +1) Validation code page + + + +2) Google Authentation app + + + From a4ca9758dc3f2b8ffd12a1162a51ce5362e5b13a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Feb 2018 14:36:21 -0300 Subject: [PATCH 0763/1476] Update Google-Two-Factor-Authenticator.md --- Docs/Documentation/Google-Two-Factor-Authenticator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Google-Two-Factor-Authenticator.md index 16c6682f2..21fcebbca 100644 --- a/Docs/Documentation/Google-Two-Factor-Authenticator.md +++ b/Docs/Documentation/Google-Two-Factor-Authenticator.md @@ -24,7 +24,7 @@ How does it work When the user log-in, he is requested (image 1) to inform the current validation code for your site in Google Authentation app (image 2), if this is the first time he access he need to add your site to Google Authentation by reading -the qrCode shown. +the QR code shown (image 1). 1) Validation code page From 61a3fe311d3430988337d2351b92a5f3e81cf038 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Feb 2018 14:36:41 -0300 Subject: [PATCH 0764/1476] Delete NextLogin.png --- .../GoogleAuthenticator/NextLogin.png | Bin 15031 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Docs/Documentation/GoogleAuthenticator/NextLogin.png diff --git a/Docs/Documentation/GoogleAuthenticator/NextLogin.png b/Docs/Documentation/GoogleAuthenticator/NextLogin.png deleted file mode 100644 index 35adf4e2ee594fee036effadc86a191c3ab5b792..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15031 zcmeHtXH-+$w{HNYO0fV+5iB$jf*`#rs1)hFgMf5G2Z0d4E+Q&TL8N!-gkGfyN+*<1 zf+8)H&=N`rdE0Z2lK;40-ne7DG2Xr7@F65~ues)2bFJBaYd_b~xRSg7hO*%y zhb$7s@4bz9WU8^@WC7|fUZNBfm#AJRf6)8zfzEybG%nM1{1%TA?gY1aRedI?O@Yil z@(dX#wLOZgbm+ngBe(ylcRg+7MyF5xJYlZ^8Yfp{s-%3D%wTICHr93Sxqwn7)feGs z?9E|At+!exoApNDgw?50)<|cG$SS3^$0V|{o$#h&`YIAAQZ2$S@=olmh>7T;s8oEW zQEb>5nFUq@7Kd!dSbiyTWeLL;X~nA4ipy}-J1t^hQ|&t~Uz+E36zoIVVl6CcinQ7l%cMaPuv%1Peq>k&fs{^ar2q= zhx=~FY`3JYiIhy^iNta?3JUyX$|p^yi9}+8IGfvT~T5HT@G-bdFgtJ5!i=h zX9E*o6V1Cab`W=ATYJbo2jM_>Phg)wAh|#p;H$fXuPt|=yPJoPOrZS5zedOa-+z(8 z7rFl$;_E7Z(L_^+TN&c*z%4F(U0CFz0xdT;x16{AeHlHK+yAfwzvM4E`TBawfWZL) z0m1=d!Vqsq@HJ^^X|RYWSX5L97$M~Iz{A%zP{_mQ(%+N(o=3&O$Ijc?)7Kf|!ToDq z+j|f{U-^p{e+l~Y_qU!7fzC&gJbeCH7O+6@uP5MZ!Xn^5a|5h$zo;@g&VdeYCMwSE z4jw*$3i+_B8T%R$yM( zrL#f?Dz0zL=;G2S?$HI3o$Gc|itN8}Lq=-y#bDKELDsxBR(cizRV8}G_Uqu=pMc2WnyFqlzamE*_9H>$ z)ZAf8g)D((!TIQ67c!aXzbJo`g-&yWhReuu>VPr-km2TGAf39-l<7;qDb&NFWaLUh z?4GrMPxfn|PTg^85Ip!`N&eUL|1Tyx^`)n0jxijOzL8z-Vn@mnslhs(-X%!+#6|SS4nBS${JsrTWt`fn0WW zhl2l^N(mHh#_JhQp#*NI+Z0c>YPhRWRIGYfr%=3j7I)!~O#quZkoyVZ!w5&pE$DJT zC^_^t<`X~haj@pD`Rig%%%P#(VFgdMWIAj|U2CxPn>=zZoz>y1|7f=}MdnVt(_%re z1qWx*tpkFpoS%WVoWdQ!7fJ6kS#w_Ms1ts0dN&r7bA!#7z&*x6@v)*#u~sXi>IK&C zvOC2z;$)vDuLur328&lAKC*OXhURf;EycCZ;eb859a@kUu@NFBA2 zCW#($JIHJblOs{y!mBV8znrID{#H%MJWtaiBGK9mUE&jR&MN>UbE46DNx7~78bg^6 zEA>q;QRQnK%P|!@KeP?K@i^2>KH%Mcg-g-?KxJR|isH7U=6Ry5klzd6vsnO#Iv2sP zcn+#PD+4!#u8uyVfjG6bDtB`P{AjansN8%I71*w6ME@}b_1oUfrnDie;3mhfA=p5H zz__{?BL(r#yiubrEmO&E#8>5?u77v|%Zh+x1?hSq4T@GOS^ZiaA*!ZNCpkDO9XkBV z)QEW(nfcXG7^L?8P^1IWY`u#CirL_4$A^k-&`iNJ?V>oQ)%uvF>!6A+6ctBV-!OxU z>b2QBar&2XsvdX75#ojy%P3ujH(fM?z4J#V6>iCj>%14l=m$IgAiBRPYr1L>5$7E2 zAStvrd%^*=_fA5h{;trybOR!uaQy;*0#^nscvHa=(F~g`1xFWzKD?ceDv5i7BG5rA zXNBeUI7A|-HrRh3)m+=~+(F}-0H;MdL)t=HS{Y@K3W_$2Q$}l6ZiF{Xh z&`QQ7({pTFE{#@l87o=@v@yjtBA%zV<)+RYWpV{>{G|H+elBg|<=ppuxvH3Y>0#WSVw?NxhVT8fd{N^ZSC(u^Uo=q7Fqr9FwZ}{3W5DR4E(Gj$Tlfy?t@c)l z(ie|>Ds8w-$I#Lvu+#jLrgm{e5pCZb(gT}J`+9pi<6YY6iUH%waLOtB&eA_|V8NVw z3xl*{4P7383W9v`1*^``Pwl=DB-_qPK&#mBV_blq3ST;$jnBZ8RlMGl?(v8&%eVrd0 z$>`diWL_ayrRrX^RCL@jtHMj)uSxSz+kSQ6E5yO6FYhdt-EFn3?*Mz5Kd8OkP03O5pjF_=R>ZO2z#z8)Kcikc|nR6jD$z3q4IvdM~J}db!JSO06t(@kC4PE&E^*Y#JXnHg1&}p)MFKIr8GT zw#&<8zFY3tgvMU`ikQI63R}=mnvQH1TEdd;4@j;F`MIm8yEhU+rSY7QdCL zpPwrj-`lurNNFi{5WwTTv*;cCWn?@8y5vAMH}^w26_c^Gn-SyD(0v{wEMrgBtd&%4 zP4$E~uLmwaticlMmH=@x^BrVek}wv6Gn-gjL5KV&EnOVNt#2EF#`Y@C2R6L9k8Qdg zmCl|^5Ep2KwTfE|c}!*Am<`C&#H4?B?;XywJ{7Wh`?G?kuyC1L7hRF={1joh z(KZ%YS%cic+`%>PJ+FfdRH&U+m$%aiVFLfoIN?lm*DD24{x3ebts2_-4M`$((dITr zA--eeN?Si9IKCi_56oPx45Gz*&6C37R|e|c802NYghCJ@3<3n9A-c&t0jWyu z=;95FB)voN+t=yOnO&k%wHPw`o zdEPxy@O!tFndtYDSJHjARal)f3IjBV*VPlGi7hPS4?pYn41a$?xxbPj>DDRK$d)Wi zkyWLz$K}$N+&6(ZJfq1ruE|-fshi?zmZ#fVnRu|+ny4_pG}!(i>Yu`kdbnO`U_jI_ zJ8HS$vUvsc=NH>{3;#l>|8pUPz_^E-tMSidA(1?n;mhmOb~!K;92|?^&oio=Y_h@9>%+I4jLi6R$%CQu+ zw+UUmHU4qLNSa;*=B-3LbhTKfqbjW76a}ke6Vt8pCEyQU`DjpgX=wQqg?JCYd96}&3eljkf&+3wH!skg`soe^xo&E5hvZ{0xhPBom0M@ z6Fxo(&XaMvNYwi4Z1e6-_g*4(OJQrP86natpIAPzvKK)mPH><*SD7W>Xae@d8lJz} z1^HdTaodyk6rW8!zJt?|M~#M68mY&eO_Dv2pewf?m964&Hi@jPC5~I?Ph0!vTitVv zsvlISqS^D&m^L0%4A4{G1Qj;OnrSFNa`7;y<=%`&J&$D%qqF1lk$7cPU-ccX4dD6>-aV_+i;~{5oV;A`F=kxb{%lM%+{U+Cyy8YFZa%t4I z&qG3Z5sG&rNesQgT*`$L*?7Yx&~;dO1KCfO2=|VrePUU_#ZYajSfNd~xoOD6oFSpO zXv?^wC7|y=I`lLm&PhLxGC9O`iB5fLiC!>#_x?OusGWxe~dnLKr6h#J?3 z(7>HI@jV_zhhDvbq)4{~XL>fX0mlV*>y!zu5xS}X{fXvBO+VXiA@^`*ejg6+Z4^~( z=wm0N1R9&jbn1s17hnsoj0-2diA7|LuBe7Nba^qo<<>q7o&6a1?y==+U&?(H+Q%m5 z-Wsg7nvK31^{TGXLUyGDeJa2HG)-Rr%8oDsle+`qPt&k9?0v|KoW9= z!Vb7~=mEtHD58}~mAwwknHhC<_14jxschuO!dzy&_O+Imp93pEocKfE)IgjFRGM8-XM`z4OV7=U`@O5*EMXMVR? zK>x3Lnj55od^TW3V#@prN}ycI^G``wnVbQQRoSm0k6@87C2>F%MDwf;3F}48Fc6dT zrQ5+I7RY@9fD>$i94~$+e*jO&{N)JlZBAek3m}-d|25wK*TzGS1U~dBuYd+r8nPEY z!sV&I6qHt;Zn^6a`j+ojyC60NY5Kf;qD)jY7J5^?Uf7VPG~8}AuV zUVXX~Pk@%;O1qHV)>!s)bbmvF zUUBZc^g}DJ=j!e$p17#8OInwanY^M^-XJV|3=->x+=UsRE# z_uyQu-J;5z$@s3V7~IXxWka{1V=A{M_(PREJh1gl^3=ANwhx3O-_U=%na>!#Ks-}W z|1yhB#!EN#(5c5l%2I4?BPDphn;xy#Q&UE}gU%}ztI&L&DC+p)ZDHd}X-VfF%a8Sl z?~&`OYAEuk-1pX~`>q2I1Dx~v^4;Q|Kja!Zpu&If3#1)+n^4;PEneeVmCIcIH5u7- zawxR^BibH37~e>Tz&(@|N9LO@a?FSNPos>`5Pb*>Y{V~tSrS#B);G-Lx0B}7t3w}oXzi+s-4`-G_+nZsM5J&yZ0)v! zSxEcvI=8T!HnPz*9VktR)#gGLOdK564C86zb_${P8ez1Ij!rF~YRq;5%z4kS7qoq? zbJ>2#n5*GRJSMdjb<3>6H(9jF)6CYdN()iQc(=cKw;^$R%&p+-c-eJ)V+tCXcG}nV z+nw$ZSTT~vgbQk(CTeuGf0B9GUhv@x2Mt;_@MWmCBP$Al{e;zaMwdm$2H9EPax6mR z?|hikrD5|#9gE^}W0)>?_S0<1*H(G z<`U&G2qnB-+$8>f6ql^U^KcFPW2!3Gj+k;dGw(GcnK@D8t55jtdphZ z6IQd$*nPSnJfL!@60v-6_L}l=xkG$5gX++{o}B5qg6m%P+4qY+6#MUuBVCQBcN*m~ zs_$B@Ny@w~H9aRm<`LlbDSh=p*oOn9<0+2gW)G5ZDAwXt^Qwsl<$mVh&(d*E_>F#1 zI~3g28aUusC4?06PHlx}gSCx6kEjJXjrd#hY!ptYQ3=Vdj2Gpc|B!pTJlF-_(riDj zZa?l=w!li+=4O2Rc6?c5LdLa`ud6<5gPEfm-2#dluB=*v$Zwq$-%)seFrGqoq#Jyq zgKNRp)J%Ng0$k0q@IpBE57$S8vATAcaqCCl{%4|O7mP9%uIi(}TW6+3T3Cg>D|-=^ zP5vymj#qIwe6r50z;X#dr_S)qJ1(XL^D;t+ zjS?mM7ay~4uc!hrS-evpo12N0MJb9U-juzGkTo9O1!L{8@K`V2i;PdFU%{`SP?ryo5X z4mWHzQCn|(t?{hHpl6ub20B*fVjtG5$&oUm@{6Rc#QksPdAqRkEJaO?+gTR6(??~< zqco+d{t5vz%l(}S2PJ=py)8*NTKf*O2_ikISlbA9h4`6m&V6XOG+;OJwZrm6vXJ1A zf}qv8nB4b1Zl*?vys;AsjCbeV)wF!?$}%HWB;ZL~@YKh>XecKm8eTMWC2(C#vS}Gl z2X`_PeIC^)Wj3HI(N)=n#XWGY4CzEwE@rO|mj}qYhYCvZ_<|cfQHb*nboklP1l!j)r*hlT5Hf-+(PDs4~A^~=cG!9Wl z(V?QpvbD@MwGSR{@JLi<63gl?w@++jG%kQY>}c`3I9feU$jaBKk9su4`3C$lR;F@S z$?DHF9<@roQu1qYxuRrB-nhak)5BSdV~`k*UCN~4jYLIA zKH_OykdAouR|3XK++zjY;6L8ctTNiD?z^iq<<-fVSbL~kr#zE#uoL22Y6MO$7EnBQ z>YYJ?qQ=Kf^`4}MDILf*RMlKD0{K!YcP}s_o{E<^&=NLthSs8Rhf8O#?~w=eMFO=@ zplAML5UgPwX6|B)BSbx0o6?|R?WByy|8(kF4#x|k)(~$K2vF}vIKPZYK%bc{BMlWY zWlw9}>LonwK~nQ6KId4;iwQIg=QLnOH0Gk_PXDR8!=Ig|9_Iv^ z-%S@*t{r3ZAu3nCdI{|E_*?vB_Tpo)m82UB=#F5CJjYoM_ev_)WcOXo3}}uX^Mw&YJI2^m5sm|a?+lFsHBgSmP;MqSz4ns;2c z$I2Y%IsY^jN`U?mnCg9*6SxWnb|je>KJaY72giUHX>&)Eo=ErghYQ5E4{1?C0p zdrME{UFW>A#C?_}^Y>R*CxIlnYCFHtdJs)7>xY47X$%a67yM}S=|GR<42jn#`FwzK zI@tgvmT$p4ap7GvbI^k7ggU%*FmzYrN-6P777@QFMvT8PB%E00Sqh)BE}2U1bJ_nQ z+$aeo+`RzawQDTg^H~LvTi=vJxC$JriA7JKb%o3Jx%;gYFmXf7qh~r`GHm*uQa_f zn7NEY&0MuPf0~Irdv3UtwP}bj{OuWvCWjxp5AaN@-TgaHwen+jdI`KSM-rXyPblUc8Wm{?9-{~Pc4 z8}u;ao;eowT9_>V_!HlgBu(nGQ$UkC>^Wfa=ggBG%jW}{)Q?D zr%7H2=r10iRa~RN?o_`}67mfN6;UnAW55uzn7bb=(vHRLK%1@jh;* z`+&wG>`aLdNq{MS08339&hj8({d^bD_&&u=pCgRnmsQBPV{3>1TxbE9);j>x`s}9U z#6aSS^{-L&L2z1UPIWOO^tubD99o+3`?$h(t!N zGay4VQjd$o5pAym{y*E2=1d}ExB>vCvv1`wl7t-*7QkUQX8Ny_$Z#LPlG?lD z@S+kUsfu;$>*|w4_Y9ui<0o2%i#`?%)UR^bOO}QE-A{ zbGM|PI?{#cMJzL0oshC^kLcvuN2`t_g~w#cn~!HKwEaFhAo4hx6|1`2$9tdlil$2N zWJP?1c~4vGmJL}U8mc3(gsfL|EDC$h>xSzATz>oE^4d1$Yn^eZ8=eYa*sJ?^k2O2Z$_#gB$D#O+F?TI}6*-2!c(VQz6CjU)U{z^sUttCvw{K!}a{`4Rb5B@ZxZX zZ62#u=9RsheuloUVxA6SzkxAWR{8a?LrlB^8r9H{NQe~T^Ogvven5yBA{4j&1W<&rd@$cfU`)P1LZek$nnXT@)-{a&*S6 zeEvSVjZD#a#h74xEX?y94f5Ar_uuQ)(XuHkQ%Fw539&DAmueUkKi8aSnkt@xeX=PG zWoBHAFWSz8viH4dmfV)YmxrQsql&wY@$*D|)NJ{{h3^dCJO5jq({! zO2%50n{BV1AnC|bFNO#BuWhe-jQCVzmaivg$sEehsk5$vt6B*Yv)1^84U3THc)N== zmjgf-A8b3x{#I_rEBq47B7KrE zS7mqK%fMYT_oLow_y_GW2Y}?{s(t@N%V#0s50C+i@0!?e$--R?ACD3Zt3od!>M9~& zQNnnSh>JwdFiK;_w_C9-T@V6>&byCL6oJWXfw1qdv3wXk#X3H&HQ{fi-Q9H*jy{{) zjHo&$ewh~!pC=Hx*Fb^p21|^;RR^wO4S!vyHh;fFk^<_1N_HLjY>WhqD>b_UuLKlF@e@d@@l;wM1u{#8Jo;Xcj=nU~yCT1j$;!z)seS zyx1lqp(Oy;O3*n&lBApI0227+Md;C`l~OZM;5YM}X(v%*Jpv%nWvKqE+FzyHzgGMA tto?SYe?9cy;PFpC_ixDk? Date: Sat, 24 Feb 2018 14:38:22 -0300 Subject: [PATCH 0765/1476] Adding Google Authenticator link in doc --- Docs/Home.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Home.md b/Docs/Home.md index 55c374ae2..6451cc129 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -17,6 +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) * [UserHelper](Documentation/UserHelper.md) * [Events](Documentation/Events.md) * [Extending the Plugin](Documentation/Extending-the-Plugin.md) From 5cfb30e1b6594ba6ba0331e190bbb41903b4075b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 26 Feb 2018 12:43:48 +0000 Subject: [PATCH 0766/1476] fix travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 574d41f68..fda5b479c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ before_script: - sh -c "if [ '$PHPCS' = '1' ]; then composer require 'cakephp/cakephp-codesniffer:@stable'; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev 'satooshi/php-coveralls:@stable'; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev 'satooshi/php-coveralls:^2.0'; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" script: From 1efa4d1c89eb6b930f5848046f3b83fd806d7c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 26 Feb 2018 12:56:34 +0000 Subject: [PATCH 0767/1476] refs #travis fix travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fda5b479c..e57438d54 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,6 @@ before_script: - sh -c "if [ '$PHPCS' = '1' ]; then composer require 'cakephp/cakephp-codesniffer:@stable'; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev 'satooshi/php-coveralls:^2.0'; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" script: From 3bda610739b5e9f561a814713eca4da1f1286ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 26 Feb 2018 13:03:26 +0000 Subject: [PATCH 0768/1476] refs #travis fix travis --- .travis.yml | 1 + composer.json | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e57438d54..ccae8dd02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ before_script: - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi" - sh -c "if [ '$PHPCS' = '1' ]; then composer require 'cakephp/cakephp-codesniffer:@stable'; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev 'satooshi/php-coveralls:^2.0'; fi" - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" diff --git a/composer.json b/composer.json index 528e23e63..0742b0ae6 100644 --- a/composer.json +++ b/composer.json @@ -32,15 +32,13 @@ }, "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", - "satooshi/php-coveralls": "dev-master" + "robthree/twofactorauth": "~1.6.0" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", From 13265a5b92e378dc22f0acc3c9ef8e53e209e70f Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 27 Feb 2018 17:12:34 -0500 Subject: [PATCH 0769/1476] Handling case when beforeRegister even was triggered and an error is found while registering --- src/Controller/Traits/RegisterTrait.php | 4 ++ .../Controller/Traits/BaseTraitTest.php | 8 ++- .../Controller/Traits/RegisterTraitTest.php | 56 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index c36ede2e3..fdac20d86 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -65,6 +65,10 @@ public function register() if ($event->result instanceof EntityInterface) { if ($userSaved = $usersTable->register($user, $event->result->toArray(), $options)) { return $this->_afterRegister($userSaved); + } else { + $this->set(compact('user')); + $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); + return; } } if ($event->isStopped()) { diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 07ed7384d..761cb23c9 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -13,6 +13,7 @@ use Cake\Event\Event; use Cake\Mailer\Email; +use Cake\ORM\Entity; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use PHPUnit_Framework_MockObject_RuntimeException; @@ -200,13 +201,18 @@ protected function _mockAuth() * mock utility * * @param Event $event event + * @param array $result array of data * @return void */ - protected function _mockDispatchEvent(Event $event = null) + protected function _mockDispatchEvent(Event $event = null, $result = []) { if (is_null($event)) { $event = new Event('cool-name-here'); } + + if (!empty($result)) { + $event->result = new Entity($result); + } $this->Trait->expects($this->any()) ->method('dispatchEvent') ->will($this->returnValue($event)); diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 8c19c1c04..419097907 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Cake\Event\Event; use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; use Cake\Core\Configure; use Cake\Core\Plugin; @@ -91,6 +92,61 @@ public function testRegister() $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); } + /** + * Triggering beforeRegister event and not able to register the user + * + * @return void + */ + public function testRegisterWithEventFalseResult() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), ['username' => 'hello']); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The user could not be saved'); + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->Trait->request->expects($this->never()) + ->method('is'); + + $this->Trait->register(); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * Triggering beforeRegister event and registering the user successfully + * + * @return void + */ + public function testRegisterWithEventSuccessResult() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ]); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->never()) + ->method('is'); + + $this->Trait->register(); + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + /** * test * From 2ff0216c52f4b00d8d26b5d896a685e876244bab Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Tue, 27 Feb 2018 17:21:21 -0500 Subject: [PATCH 0770/1476] CS fix --- src/Controller/Traits/RegisterTrait.php | 1 + tests/TestCase/Controller/Traits/RegisterTraitTest.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index fdac20d86..98c6c4995 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -68,6 +68,7 @@ public function register() } else { $this->set(compact('user')); $this->Flash->error(__d('CakeDC/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 419097907..cc050a9df 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\Event\Event; 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; From dd0f98bd30e72011153fdd229240028fc6fda0fb Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 1 Mar 2018 13:47:08 -0500 Subject: [PATCH 0771/1476] Password was being hashed twice when beforeRegister event was being triggered --- src/Controller/Traits/RegisterTrait.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 98c6c4995..82c353130 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -63,10 +63,12 @@ public function register() ]); if ($event->result instanceof EntityInterface) { - if ($userSaved = $usersTable->register($user, $event->result->toArray(), $options)) { + $data = $event->result->toArray(); + $data['password'] = $requestData['password']; //since password is a hidden property + if ($userSaved = $usersTable->register($user, $data, $options)) { return $this->_afterRegister($userSaved); } else { - $this->set(compact('user')); + $this->set(compact('user')); $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); return; From 3b544d98a360a3ca90b2e12921e327cb40ba3ad8 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 1 Mar 2018 13:54:09 -0500 Subject: [PATCH 0772/1476] Fixing unit test --- .../Controller/Traits/RegisterTraitTest.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index cc050a9df..8e35ea735 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -123,17 +123,22 @@ public function testRegisterWithEventFalseResult() */ public function testRegisterWithEventSuccessResult() { - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), [ + $data = [ 'username' => 'testRegistration', 'password' => 'password', 'email' => 'test-registration@example.com', 'password_confirm' => 'password', 'tos' => 1 - ]); + ]; + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), $data); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue($data)); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('Please validate your account before log in'); From 8c40bef13939b2c61b2ec72885518b455201356b Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Thu, 1 Mar 2018 13:55:17 -0500 Subject: [PATCH 0773/1476] CS fix --- 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 82c353130..4b63a22a1 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -68,7 +68,7 @@ public function register() if ($userSaved = $usersTable->register($user, $data, $options)) { return $this->_afterRegister($userSaved); } else { - $this->set(compact('user')); + $this->set(compact('user')); $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); return; From 6bf7a8580337f354edb015c6bf4373cfbe3c7e77 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 6 Mar 2018 17:52:34 +0100 Subject: [PATCH 0774/1476] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b3143e4a4..af4cdedb9 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^3.5 | [master](https://github.com/cakedc/users/tree/master) | 6.0.0 | stable | +| ^3.5 | [master](https://github.com/cakedc/users/tree/master) | 6.0.1 | stable | | ^3.5 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 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 | From 2b609d4aa7c7fc4434fb22200f9c13579efe76f7 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 6 Mar 2018 17:52:52 +0100 Subject: [PATCH 0775/1476] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index f83d94eff..f08998704 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 6 :minor: 0 -:patch: 0 +:patch: 1 :special: '' From 55f0563cf900b39bf580ce2a3e5bb44cfd6d055c Mon Sep 17 00:00:00 2001 From: Lartak Date: Fri, 9 Mar 2018 11:33:36 +0100 Subject: [PATCH 0776/1476] Update source image for Validation code page --- Docs/Documentation/Google-Two-Factor-Authenticator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Google-Two-Factor-Authenticator.md index 21fcebbca..99245ce76 100644 --- a/Docs/Documentation/Google-Two-Factor-Authenticator.md +++ b/Docs/Documentation/Google-Two-Factor-Authenticator.md @@ -28,7 +28,7 @@ the QR code shown (image 1). 1) Validation code page - + 2) Google Authentation app From 603c11193f09ab51163f9daf45b4ef2b14def556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Sun, 1 Apr 2018 21:38:15 +0200 Subject: [PATCH 0777/1476] Replace deprecated methods for 3.6 --- Docs/Documentation/Extending-the-Plugin.md | 2 +- composer.json | 2 +- config/bootstrap.php | 4 +- config/permissions.php | 2 +- src/Auth/SocialAuthenticate.php | 6 +- .../Component/RememberMeComponent.php | 14 +- .../Component/UsersAuthComponent.php | 10 +- src/Controller/SocialAccountsController.php | 2 +- .../Traits/CustomUsersTableTrait.php | 2 +- src/Controller/Traits/LinkSocialTrait.php | 16 +-- src/Controller/Traits/LoginTrait.php | 2 +- .../Traits/PasswordManagementTrait.php | 8 +- src/Controller/Traits/RegisterTrait.php | 4 +- src/Controller/Traits/SimpleCrudTrait.php | 14 +- src/Controller/Traits/SocialTrait.php | 2 +- src/Controller/Traits/UserValidationTrait.php | 2 +- src/Mailer/UsersMailer.php | 13 +- .../TestCase/Auth/SocialAuthenticateTest.php | 6 +- .../GoogleAuthenticatorComponentTest.php | 4 +- .../Component/UsersAuthComponentTest.php | 133 +++++++++--------- .../SocialAccountsControllerTest.php | 14 +- .../Controller/Traits/BaseTraitTest.php | 4 +- .../Traits/CustomUsersTableTraitTest.php | 2 +- .../Controller/Traits/LinkSocialTraitTest.php | 14 +- .../Controller/Traits/RegisterTraitTest.php | 2 +- .../Controller/Traits/SocialTraitTest.php | 10 +- tests/TestCase/Mailer/UsersMailerTest.php | 16 +-- .../Model/Behavior/AuthFinderBehaviorTest.php | 2 +- .../Model/Behavior/LinkSocialBehaviorTest.php | 10 +- .../Model/Behavior/PasswordBehaviorTest.php | 8 +- .../Model/Behavior/RegisterBehaviorTest.php | 2 +- .../Behavior/SocialAccountBehaviorTest.php | 2 +- .../Model/Table/SocialAccountsTableTest.php | 4 +- tests/TestCase/Model/Table/UsersTableTest.php | 4 +- tests/TestCase/Shell/UsersShellTest.php | 2 +- tests/TestCase/View/Helper/UserHelperTest.php | 4 +- 36 files changed, 171 insertions(+), 177 deletions(-) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index 3da0705d6..fec58928a 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -151,7 +151,7 @@ You could use a new Trait. For example, you want to add an 'impersonate' feature namespace App\Controller\Traits; use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\Network\Exception\NotFoundException; +use Cake\Http\Exception\NotFoundException; /** * Impersonate Trait diff --git a/composer.json b/composer.json index 0742b0ae6..bfd71f729 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": "dev-3.next", "cakedc/auth": "^2.0" }, "require-dev": { diff --git a/config/bootstrap.php b/config/bootstrap.php index fb8f7c9d5..42d2bb0c2 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -22,8 +22,8 @@ Configure::load($file); }); -TableRegistry::config('Users', ['className' => Configure::read('Users.table')]); -TableRegistry::config('CakeDC/Users.Users', ['className' => Configure::read('Users.table')]); +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')); diff --git a/config/permissions.php b/config/permissions.php index b73559e05..a437994a1 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -39,7 +39,7 @@ 'action' => ['edit', 'delete'], 'allowed' => function(array $user, $role, Request $request) { $postId = Hash::get($request->params, 'pass.0'); - $post = TableRegistry::get('Posts')->get($postId); + $post = TableRegistry::getTableLocator()->get('Posts')->get($postId); $userId = Hash::get($user, 'id'); if (!empty($post->user_id) && !empty($userId)) { return $post->user_id === $userId; diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php index b3d26cce8..a5602c150 100755 --- a/src/Auth/SocialAuthenticate.php +++ b/src/Auth/SocialAuthenticate.php @@ -268,8 +268,8 @@ protected function _map($data) * application. * * @param \Cake\Http\ServerRequest $request Request object. - * @param \Cake\Network\Response $response Response object. - * @return \Cake\Network\Response|null + * @param \Cake\Http\Response $response Response object. + * @return \Cake\Http\Response|null */ public function unauthenticated(ServerRequest $request, Response $response) { @@ -480,7 +480,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; diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php index eecfa8f34..742d91b63 100644 --- a/src/Controller/Component/RememberMeComponent.php +++ b/src/Controller/Component/RememberMeComponent.php @@ -105,8 +105,8 @@ public function setLoginCookie(Event $event) if (empty($user)) { return; } - $user['user_agent'] = $this->getController()->request->getHeaderLine('User-Agent'); - if (!(bool)$this->getController()->request->getData(Configure::read('Users.Key.Data.rememberMe'))) { + $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); @@ -135,10 +135,10 @@ public function beforeFilter(Event $event) { $user = $this->Auth->user(); if (!empty($user) || - $this->getController()->request->is(['post', 'put']) || - $this->getController()->request->getParam('action') === 'logout' || - $this->getController()->request->getSession()->check(Configure::read('Users.Key.Session.social')) || - $this->getController()->request->getParam('provider')) { + $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; } @@ -152,7 +152,7 @@ public function beforeFilter(Event $event) if (is_array($event->result)) { return $this->getController()->redirect($event->result); } - $url = $this->getController()->request->getRequestTarget(); + $url = $this->getController()->getRequest()->getRequestTarget(); return $this->getController()->redirect($url); } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 9944abfe0..c2d1d7716 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -116,8 +116,8 @@ protected function _initAuth() } list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); - if ($this->getController()->request->getParam('plugin', null) === $plugin && - $this->getController()->request->getParam('controller') === $controller + if ($this->getController()->getRequest()->getParam('plugin', null) === $plugin && + $this->getController()->getRequest()->getParam('controller') === $controller ) { $this->getController()->Auth->allow([ // LoginTrait @@ -150,7 +150,7 @@ protected function _initAuth() */ public function isUrlAuthorized(Event $event) { - $url = Hash::get((array)$event->data, 'url'); + $url = Hash::get((array)$event->getData(), 'url'); if (empty($url)) { return false; } @@ -185,7 +185,7 @@ public function isUrlAuthorized(Event $event) } $request = new ServerRequest($requestUrl); - $request = $request->addParams($requestParams); + $request = $request->withAttribute('params', $requestParams); $isAuthorized = $this->getController()->Auth->isAuthorized(null, $request); @@ -220,7 +220,7 @@ protected function _isActionAllowed($requestParams = []) if (empty($requestParams['action'])) { return false; } - if (!empty($requestParams['controller']) && $requestParams['controller'] !== $this->getController()->name) { + if (!empty($requestParams['controller']) && $requestParams['controller'] !== $this->getController()->getName()) { return false; } $action = strtolower($requestParams['action']); diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index e9d07d978..b22507464 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -15,7 +15,7 @@ use CakeDC\Users\Exception\AccountAlreadyActiveException; use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\Network\Response; +use Cake\Http\Response; /** * SocialAccounts Controller diff --git a/src/Controller/Traits/CustomUsersTableTrait.php b/src/Controller/Traits/CustomUsersTableTrait.php index 76e6037a4..f016f66de 100644 --- a/src/Controller/Traits/CustomUsersTableTrait.php +++ b/src/Controller/Traits/CustomUsersTableTrait.php @@ -33,7 +33,7 @@ public function getUsersTable() if ($this->_usersTable instanceof Table) { return $this->_usersTable; } - $this->_usersTable = TableRegistry::get(Configure::read('Users.table')); + $this->_usersTable = TableRegistry::getTableLocator()->get(Configure::read('Users.table')); return $this->_usersTable; } diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 490c1e127..9b10c960b 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -13,7 +13,7 @@ use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; -use Cake\Network\Exception\NotFoundException; +use Cake\Http\Exception\NotFoundException; use League\OAuth1\Client\Server\Twitter; /** @@ -27,8 +27,8 @@ trait LinkSocialTrait * * @param string $alias of the provider. * - * @throws \Cake\Network\Exception\NotFoundException Quando o provider informado não existe - * @return \Cake\Network\Response Redirects on successful + * @throws \Cake\Http\Exception\NotFoundException Quando o provider informado não existe + * @return \Cake\Http\Response Redirects on successful */ public function linkSocial($alias = null) { @@ -52,8 +52,8 @@ public function linkSocial($alias = null) * * @param string $alias of the provider. * - * @throws \Cake\Network\Exception\NotFoundException Quando o provider informado não existe - * @return \Cake\Network\Response Redirects to profile if okay or error + * @throws \Cake\Http\Exception\NotFoundException Quando o provider informado não existe + * @return \Cake\Http\Response Redirects to profile if okay or error */ public function callbackLinkSocial($alias = null) { @@ -117,7 +117,7 @@ public function callbackLinkSocial($alias = null) $this->getUsersTable()->linkSocialAccount($user, $data); - if ($user->errors()) { + if ($user->getErrors()) { $this->Flash->error($message); } else { $this->Flash->success(__d('CakeDC/Users', 'Social account was associated.')); @@ -161,7 +161,7 @@ protected function _mapSocialUser($alias, $data) * * @param string $alias of the provider. * - * @throws \Cake\Network\Exception\NotFoundException + * @throws \Cake\Http\Exception\NotFoundException * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter */ protected function _getSocialProvider($alias) @@ -184,7 +184,7 @@ protected function _getSocialProvider($alias) * @param array $config for social provider. * @param string $alias provider alias * - * @throws \Cake\Network\Exception\NotFoundException + * @throws \Cake\Http\Exception\NotFoundException * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter */ protected function _createSocialProvider($config, $alias = null) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 6e7c7b509..28c30d588 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -19,7 +19,7 @@ use Cake\Core\Configure; use Cake\Core\Exception\Exception; use Cake\Event\Event; -use Cake\Network\Exception\NotFoundException; +use Cake\Http\Exception\NotFoundException; use Cake\Utility\Hash; use League\OAuth1\Client\Server\Twitter; diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 653498906..5e9f1cd4b 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -47,12 +47,12 @@ public function changePassword() $validatePassword = false; if (!$user->id) { $this->Flash->error(__d('CakeDC/Users', 'User was not found')); - $this->redirect($this->Auth->config('loginAction')); + $this->redirect($this->Auth->getConfig('loginAction')); return; } //@todo add to the documentation: list of routes used - $redirect = $this->Auth->config('loginAction'); + $redirect = $this->Auth->getConfig('loginAction'); } $this->set('validatePassword', $validatePassword); if ($this->request->is('post')) { @@ -66,7 +66,7 @@ public function changePassword() $this->request->getData(), ['validate' => $validator] ); - if ($user->errors()) { + if ($user->getErrors()) { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); } else { $user = $this->getUsersTable()->changePassword($user); @@ -105,7 +105,7 @@ public function resetPassword($token = null) /** * Reset password * - * @return void|\Cake\Network\Response + * @return void|\Cake\Http\Response */ public function requestResetPassword() { diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 4b63a22a1..fc29ef602 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -14,8 +14,8 @@ use CakeDC\Users\Controller\Component\UsersAuthComponent; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; -use Cake\Network\Exception\NotFoundException; -use Cake\Network\Response; +use Cake\Http\Exception\NotFoundException; +use Cake\Http\Response; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index 35973a1e9..4f2480a0a 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Network\Exception\NotFoundException; -use Cake\Network\Response; +use Cake\Http\Exception\NotFoundException; +use Cake\Http\Response; use Cake\Utility\Inflector; /** @@ -30,7 +30,7 @@ trait SimpleCrudTrait public function index() { $table = $this->loadModel(); - $tableAlias = $table->alias(); + $tableAlias = $table->getAlias(); $this->set($tableAlias, $this->paginate($table)); $this->set('tableAlias', $tableAlias); $this->set('_serialize', [$tableAlias, 'tableAlias']); @@ -46,7 +46,7 @@ public function index() public function view($id = null) { $table = $this->loadModel(); - $tableAlias = $table->alias(); + $tableAlias = $table->getAlias(); $entity = $table->get($id, [ 'contain' => [] ]); @@ -63,7 +63,7 @@ public function view($id = null) public function add() { $table = $this->loadModel(); - $tableAlias = $table->alias(); + $tableAlias = $table->getAlias(); $entity = $table->newEntity(); $this->set($tableAlias, $entity); $this->set('tableAlias', $tableAlias); @@ -91,7 +91,7 @@ public function add() public function edit($id = null) { $table = $this->loadModel(); - $tableAlias = $table->alias(); + $tableAlias = $table->getAlias(); $entity = $table->get($id, [ 'contain' => [] ]); @@ -122,7 +122,7 @@ public function delete($id = null) { $this->request->allowMethod(['post', 'delete']); $table = $this->loadModel(); - $tableAlias = $table->alias(); + $tableAlias = $table->getAlias(); $entity = $table->get($id, [ 'contain' => [] ]); diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 7fd6b197e..f019f9e1d 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; -use Cake\Network\Exception\NotFoundException; +use Cake\Http\Exception\NotFoundException; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index d9ba30a73..2229c7abb 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -15,7 +15,7 @@ use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; use Cake\Core\Configure; -use Cake\Network\Response; +use Cake\Http\Response; use Exception; /** diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index fabfbfcb1..2e021884d 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Mailer; use Cake\Datasource\EntityInterface; -use Cake\Mailer\Email; use Cake\Mailer\Mailer; /** @@ -33,10 +32,10 @@ protected function validation(EntityInterface $user) $user->setHidden(['password', 'token_expires', 'api_token']); $subject = __d('CakeDC/Users', 'Your account validation link'); $this - ->to($user['email']) - ->setSubject($firstName . $subject) - ->setViewVars($user->toArray()) - ->setTemplate('CakeDC/Users.validation'); + ->setTo($user['email']) + ->setSubject($firstName . $subject) + ->setViewVars($user->toArray()) + ->setTemplate('CakeDC/Users.validation'); } /** @@ -54,7 +53,7 @@ protected function resetPassword(EntityInterface $user) $user->setHidden(['password', 'token_expires', 'api_token']); $this - ->to($user['email']) + ->setTo($user['email']) ->setSubject($subject) ->setViewVars($user->toArray()) ->setTemplate('CakeDC/Users.resetPassword'); @@ -74,7 +73,7 @@ protected function socialAccountValidation(EntityInterface $user, EntityInterfac // note: we control the space after the username in the previous line $subject = __d('CakeDC/Users', '{0}Your social account validation link', $firstName); $this - ->to($user['email']) + ->setTo($user['email']) ->setSubject($subject) ->setViewVars(compact('user', 'socialAccount')) ->setTemplate('CakeDC/Users.socialAccountValidation'); diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index fb1387438..4eafafef7 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -21,7 +21,7 @@ use Cake\Event\Event; use Cake\Http\ServerRequest; use Cake\Network\Request; -use Cake\Network\Response; +use Cake\Http\Response; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use ReflectionClass; @@ -47,7 +47,7 @@ public function setUp() $request = new ServerRequest(); $response = new Response(); - $this->Table = TableRegistry::get('CakeDC/Users.Users'); + $this->Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Token = $this->getMockBuilder('League\OAuth2\Client\Token\AccessToken') ->setMethods(['getToken', 'getExpires']) @@ -240,7 +240,7 @@ public function testGetUserSessionData() $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', '_getProviderName', '_mapUser', '_touch', '_validateConfig']); - $session = $this->getMockBuilder('Cake\Network\Session') + $session = $this->getMockBuilder('Cake\Http\Session') ->setMethods(['read', 'delete']) ->getMock(); $session->expects($this->once()) diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index 868c449da..659cfbe03 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -20,7 +20,7 @@ use Cake\Database\Exception; use Cake\Event\Event; use Cake\Network\Request; -use Cake\Network\Session; +use Cake\Http\Session; use Cake\ORM\Entity; use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; @@ -64,7 +64,7 @@ public function setUp() ->setMethods(['is', 'method']) ->getMock(); $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); - $this->response = $this->getMockBuilder('Cake\Network\Response') + $this->response = $this->getMockBuilder('Cake\Http\Response') ->setMethods(['stop']) ->getMock(); $this->Controller = new Controller($this->request, $this->response); diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 11ef64357..6f2c7aaef 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -21,7 +21,7 @@ use Cake\Event\Event; use Cake\Http\ServerRequest; use Cake\Network\Request; -use Cake\Network\Session; +use Cake\Http\Session; use Cake\ORM\Entity; use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; @@ -70,11 +70,11 @@ public function setUp() ->setMethods(['is', 'method']) ->getMock(); $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); - $this->response = $this->getMockBuilder('Cake\Network\Response') + $this->response = $this->getMockBuilder('Cake\Http\Response') ->setMethods(['stop']) ->getMock(); $this->Controller = new Controller($this->request, $this->response); - $this->Controller->name = 'Users'; + $this->Controller->setName('Users'); $this->Registry = $this->Controller->components(); $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); } @@ -131,9 +131,9 @@ public function testInitializeNoRequiredRememberMe() public function testIsUrlAuthorizedUserNotLoggedIn() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => '/route', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -153,9 +153,9 @@ public function testIsUrlAuthorizedUserNotLoggedIn() public function testIsUrlAuthorizedUserNotLoggedInActionAllowed() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => '/route', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -176,9 +176,9 @@ public function testIsUrlAuthorizedUserNotLoggedInActionAllowed() public function testIsUrlAuthorizedUserLoggedInNotAllowedActionAllowed() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => '/notAllowed', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -199,9 +199,9 @@ public function testIsUrlAuthorizedUserLoggedInNotAllowedActionAllowed() public function testIsUrlAuthorizedUserLoggedInAllowedActionAllowed() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => '/route', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -237,9 +237,9 @@ public function testIsUrlAuthorizedNoUrl() public function testIsUrlAuthorizedUrlRelativeString() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => '/route', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -250,14 +250,13 @@ public function testIsUrlAuthorizedUrlRelativeString() $this->Controller->Auth->expects($this->once()) ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { - return $subject->params === [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_ext' => null, - 'pass' => [], - '_matchedRoute' => '/route/*', - ]; + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; })) ->will($this->returnValue(true)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); @@ -273,9 +272,9 @@ public function testIsUrlAuthorizedUrlRelativeString() public function testIsUrlAuthorizedMissingRouteString() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => '/missingRoute', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -294,12 +293,12 @@ public function testIsUrlAuthorizedMissingRouteString() public function testIsUrlAuthorizedMissingRouteArray() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => [ 'controller' => 'missing', 'action' => 'missing', ], - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -317,9 +316,9 @@ public function testIsUrlAuthorizedMissingRouteArray() public function testIsUrlAuthorizedUrlAbsoluteForCurrentAppString() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => Router::fullBaseUrl() . '/route', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -330,14 +329,13 @@ public function testIsUrlAuthorizedUrlAbsoluteForCurrentAppString() $this->Controller->Auth->expects($this->once()) ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { - return $subject->params === [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_ext' => null, - 'pass' => [], - '_matchedRoute' => '/route/*', - ]; + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; })) ->will($this->returnValue(true)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); @@ -352,9 +350,9 @@ public function testIsUrlAuthorizedUrlAbsoluteForCurrentAppString() public function testIsUrlAuthorizedUrlRelativeForCurrentAppString() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => 'route', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -365,14 +363,13 @@ public function testIsUrlAuthorizedUrlRelativeForCurrentAppString() $this->Controller->Auth->expects($this->once()) ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { - return $subject->params === [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_ext' => null, - 'pass' => [], - '_matchedRoute' => '/route/*', - ]; + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; })) ->will($this->returnValue(true)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); @@ -387,9 +384,9 @@ public function testIsUrlAuthorizedUrlRelativeForCurrentAppString() public function testIsUrlAuthorizedUrlAbsoluteForOtherAppString() { $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => 'http://example.com', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -408,14 +405,14 @@ public function testIsUrlAuthorizedUrlAbsoluteForOtherAppString() public function testIsUrlAuthorizedUrlArray() { $event = new Event('event'); - $event->data = [ + $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() @@ -426,14 +423,13 @@ public function testIsUrlAuthorizedUrlArray() $this->Controller->Auth->expects($this->once()) ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { - return $subject->params === [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_ext' => null, - 'pass' => ['pass-one'], - '_matchedRoute' => '/route/*', - ]; + 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); @@ -456,13 +452,13 @@ public function testIsUrlAuthorizedBaseUrl() 'url' => '/', ])); $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword', ], - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() @@ -473,14 +469,13 @@ public function testIsUrlAuthorizedBaseUrl() $this->Controller->Auth->expects($this->once()) ->method('isAuthorized') ->with(null, $this->callback(function ($subject) { - return $subject->params === [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_ext' => null, - 'pass' => [], - '_matchedRoute' => '/route/*', - ]; + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; })) ->will($this->returnValue(true)); $result = $this->Controller->UsersAuth->isUrlAuthorized($event); @@ -504,9 +499,9 @@ public function testIsUrlAuthorizedUserLoggedInAllowedActionAllowedAnotherContro 'action' => 'requestResetPassword' ]); $event = new Event('event'); - $event->data = [ + $event->setData([ 'url' => '/route-another-controller', - ]; + ]); $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') ->setMethods(['user', 'isAuthorized']) ->disableOriginalConstructor() diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index ef002f15f..296f15f2f 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -97,7 +97,7 @@ public function testValidateAccountHappy() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-1234'); - $this->assertEquals('Account validated successfully', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Account validated successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } /** @@ -111,7 +111,7 @@ public function testValidateAccountInvalidToken() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-not-found'); - $this->assertEquals('Invalid token and/or social account', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Invalid token and/or social account', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } /** @@ -125,7 +125,7 @@ public function testValidateAccountAlreadyActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('Social Account already active', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } /** @@ -148,7 +148,7 @@ public function testResendValidationHappy() ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->resendValidation('Facebook', 'reference-1-1234'); - $this->assertEquals('Email sent successfully', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Email sent successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } /** @@ -171,7 +171,7 @@ public function testResendValidationEmailError() ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->resendValidation('Facebook', 'reference-1-1234'); - $this->assertEquals('Email could not be sent', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Email could not be sent', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } /** @@ -185,7 +185,7 @@ public function testResendValidationInvalid() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->resendValidation('Facebook', 'reference-invalid'); - $this->assertEquals('Invalid account', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Invalid account', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } /** @@ -199,6 +199,6 @@ public function testResendValidationAlreadyActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('Social Account already active', $this->Controller->request->session()->read('Flash.flash.0.message')); + $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } } diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 761cb23c9..a7ff42461 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -47,7 +47,7 @@ public function setUp() { parent::setUp(); $traitMockMethods = array_unique(array_merge(['getUsersTable'], $this->traitMockMethods)); - $this->table = TableRegistry::get('CakeDC/Users.Users'); + $this->table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); try { $this->Trait = $this->getMockBuilder($this->traitClassName) ->setMethods($traitMockMethods) @@ -96,7 +96,7 @@ public function tearDown() */ protected function _mockSession($attributes) { - $session = new \Cake\Network\Session(); + $session = new \Cake\Http\Session(); foreach ($attributes as $field => $value) { $session->write($field, $value); diff --git a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php index 82db079d5..3511fd9a5 100644 --- a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php +++ b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php @@ -33,7 +33,7 @@ public function tearDown() public function testGetUsersTable() { $table = $this->controller->Trait->getUsersTable(); - $this->assertEquals('CakeDC/Users.Users', $table->registryAlias()); + $this->assertEquals('CakeDC/Users.Users', $table->getRegistryAlias()); $newTable = new Table(); $this->controller->Trait->setUsersTable($newTable); $this->assertSame($newTable, $this->controller->Trait->getUsersTable()); diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 9088c66fc..86a45be55 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -16,7 +16,7 @@ use Cake\Event\Event; use Cake\Http\ServerRequest; use Cake\I18n\Time; -use Cake\Network\Exception\NotFoundException; +use Cake\Http\Exception\NotFoundException; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use League\OAuth2\Client\Provider\Facebook; @@ -250,7 +250,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'); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) @@ -380,7 +380,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') @@ -507,7 +507,7 @@ public function testCallbackLinkSocialFailGettingAccessToken() 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->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) @@ -600,7 +600,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->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) @@ -688,7 +688,7 @@ public function testCallbackLinkSocialWrongState() 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->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) @@ -775,7 +775,7 @@ public function testCallbackLinkSocialMissingCode() 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->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable', 'log']) diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 8e35ea735..ec2a005d9 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -326,7 +326,7 @@ public function testRegisterRecaptchaDisabled() * test * * @return void - * @expectedException Cake\Network\Exception\NotFoundException + * @expectedException Cake\Http\Exception\NotFoundException */ public function testRegisterNotEnabled() { diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 683a23d81..054bc7cb1 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -45,7 +45,7 @@ public function tearDown() */ public function testSocialEmail() { - $session = $this->getMockBuilder('Cake\Network\Session') + $session = $this->getMockBuilder('Cake\Http\Session') ->setMethods(['check', 'delete']) ->getMock(); $session->expects($this->at(0)) @@ -70,11 +70,11 @@ public function testSocialEmail() /** * Test socialEmail * - * @expectedException \Cake\Network\Exception\NotFoundException + * @expectedException \Cake\Http\Exception\NotFoundException */ public function testSocialEmailInvalid() { - $session = $this->getMockBuilder('Cake\Network\Session') + $session = $this->getMockBuilder('Cake\Http\Session') ->setMethods(['check']) ->getMock(); $session->expects($this->once()) @@ -94,7 +94,7 @@ public function testSocialEmailInvalid() public function testSocialEmailPostValidateFalse() { - $session = $this->getMockBuilder('Cake\Network\Session') + $session = $this->getMockBuilder('Cake\Http\Session') ->setMethods(['check', 'delete']) ->getMock(); $session->expects($this->any()) @@ -136,7 +136,7 @@ public function testSocialEmailPostValidateFalse() public function testSocialEmailPostValidateTrue() { - $session = $this->getMockBuilder('Cake\Network\Session') + $session = $this->getMockBuilder('Cake\Http\Session') ->setMethods(['check', 'delete']) ->getMock(); $session->expects($this->any()) diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 4197fdb5b..ae79ca496 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -39,12 +39,12 @@ public function setUp() { parent::setUp(); $this->Email = $this->getMockBuilder('Cake\Mailer\Email') - ->setMethods(['to', 'setSubject', 'setViewVars', 'setTemplate']) + ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) ->getMock(); $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') ->setConstructorArgs([$this->Email]) - ->setMethods(['to', 'setSubject', 'setViewVars', 'setTemplate']) + ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) ->getMock(); } @@ -67,7 +67,7 @@ public function tearDown() */ public function testValidation() { - $table = TableRegistry::get('CakeDC/Users.Users'); + $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $data = [ 'first_name' => 'FirstName', 'email' => 'test@example.com', @@ -75,7 +75,7 @@ public function testValidation() ]; $user = $table->newEntity($data); $this->UsersMailer->expects($this->once()) - ->method('to') + ->method('setTo') ->with($user['email']) ->will($this->returnValue($this->Email)); @@ -99,11 +99,11 @@ public function testValidation() */ public function testSocialAccountValidation() { - $social = TableRegistry::get('CakeDC/Users.SocialAccounts') + $social = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts') ->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); $this->UsersMailer->expects($this->once()) - ->method('to') + ->method('setTo') ->with('user-1@test.com') ->will($this->returnValue($this->Email)); @@ -127,7 +127,7 @@ public function testSocialAccountValidation() */ public function testResetPassword() { - $table = TableRegistry::get('CakeDC/Users.Users'); + $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $data = [ 'first_name' => 'FirstName', 'email' => 'test@example.com', @@ -135,7 +135,7 @@ public function testResetPassword() ]; $user = $table->newEntity($data); $this->UsersMailer->expects($this->once()) - ->method('to') + ->method('setTo') ->with($user['email']) ->will($this->returnValue($this->Email)); diff --git a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php index 59e51de37..2134da7eb 100644 --- a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php @@ -43,7 +43,7 @@ class AuthFinderBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $this->table = TableRegistry::get('CakeDC/Users.Users'); + $this->table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Behavior = new AuthFinderBehavior($this->table); } diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index 9344ac513..0d2710ae0 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -48,7 +48,7 @@ class LinkSocialBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $this->Table = TableRegistry::get('CakeDC/Users.Users'); + $this->Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Behavior = new LinkSocialBehavior($this->Table); } @@ -174,7 +174,7 @@ public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId, $actual = $resultUser->social_accounts[0]; $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); - $actual = $user->errors(); + $actual = $user->getErrors(); $expected = [ 'social_accounts' => [ @@ -187,7 +187,7 @@ public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId, ]; $this->assertEquals($expected, $actual); - $error = $user->errors('social_accounts'); + $error = $user->getErrors('social_accounts'); $error = $error ? reset($error) : $message; } @@ -274,7 +274,7 @@ public function testlinkSocialAccountFacebookProviderAccountExists($data, $userI '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') ] ]; - $actual = $user->errors(); + $actual = $user->getErrors(); $this->assertEquals($expected, $actual); //Se for o usuário que já esta associado então okay @@ -288,7 +288,7 @@ public function testlinkSocialAccountFacebookProviderAccountExists($data, $userI ]); $resultUser = $this->Behavior->linkSocialAccount($userBase, $data); $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); - $this->assertEquals([], $userBase->errors()); + $this->assertEquals([], $userBase->getErrors()); $actual = $resultUser->social_accounts[0]; diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index aa1cf5308..5ba5a7950 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -42,7 +42,7 @@ class PasswordBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $this->table = TableRegistry::get('CakeDC/Users.Users'); + $this->table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\PasswordBehavior') ->setMethods(['sendResetPasswordEmail']) ->setConstructorArgs([$this->table]) @@ -152,7 +152,7 @@ public function testResetTokenNotExistingUser() */ public function testResetTokenUserAlreadyActive() { - $activeUser = TableRegistry::get('CakeDC/Users.Users')->findByUsername('user-4')->first(); + $activeUser = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-4')->first(); $this->assertTrue($activeUser->active); $this->table = $this->getMockForModel('CakeDC/Users.Users', ['save']); $this->table->expects($this->never()) @@ -184,7 +184,7 @@ public function testResetTokenUserNotActive() */ public function testResetTokenUserActive() { - $user = TableRegistry::get('CakeDC/Users.Users')->findByUsername('user-2')->first(); + $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-2')->first(); $result = $this->Behavior->resetToken('user-2', [ 'ensureActive' => true, 'expiration' => 3600 @@ -197,7 +197,7 @@ public function testResetTokenUserActive() */ public function testChangePassword() { - $user = TableRegistry::get('CakeDC/Users.Users')->findByUsername('user-6')->first(); + $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-6')->first(); $user->current_password = '12345'; $user->password = 'new'; $user->password_confirmation = 'new'; diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index f0e4b9707..d1dbcee6e 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -41,7 +41,7 @@ class RegisterBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $table = TableRegistry::get('CakeDC/Users.Users'); + $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $table->addBehavior('CakeDC/Users/Register.Register'); $this->Table = $table; $this->Behavior = $table->behaviors()->Register; diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index 01e9fd2da..b9149c516 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -42,7 +42,7 @@ class SocialAccountBehaviorTest extends TestCase public function setUp() { parent::setUp(); - $this->Table = TableRegistry::get('CakeDC/Users.SocialAccounts'); + $this->Table = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts'); $this->Behavior = $this->Table->behaviors()->SocialAccount; } diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index 6cdbb16e2..f662d7bf2 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -43,7 +43,7 @@ class SocialAccountsTableTest extends TestCase public function setUp() { parent::setUp(); - $this->SocialAccounts = TableRegistry::get('CakeDC/Users.SocialAccounts'); + $this->SocialAccounts = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts'); } /** @@ -69,6 +69,6 @@ public function testValidationHappy() 'data' => 'test-data', ]; $entity = $this->SocialAccounts->newEntity($data); - $this->assertEmpty($entity->errors()); + $this->assertEmpty($entity->getErrors()); } } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index fcf798304..dcad61b07 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -46,7 +46,7 @@ class UsersTableTest extends TestCase public function setUp() { parent::setUp(); - $this->Users = TableRegistry::get('CakeDC/Users.Users'); + $this->Users = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->fullBaseBackup = Router::fullBaseUrl(); Router::fullBaseUrl('http://users.test'); Email::setConfigTransport('test', [ @@ -142,7 +142,7 @@ public function testValidateRegisterTosRequired() ]; $userEntity = $this->Users->newEntity(); $this->Users->register($userEntity, $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); - $this->assertEquals(['tos' => ['_required' => 'This field is required']], $userEntity->errors()); + $this->assertEquals(['tos' => ['_required' => 'This field is required']], $userEntity->getErrors()); } /** diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index bb1e4484f..05bd3e58f 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -39,7 +39,7 @@ public function setUp() parent::setUp(); $this->out = new ConsoleOutput(); $this->io = $this->getMockBuilder('Cake\Console\ConsoleIo')->getMock(); - $this->Users = TableRegistry::get('CakeDC/Users.Users'); + $this->Users = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 55e5d1cbe..e20b30e77 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -131,7 +131,7 @@ public function testLogoutWithOptions() */ public function testWelcome() { - $session = $this->getMockBuilder('Cake\Network\Session') + $session = $this->getMockBuilder('Cake\Http\Session') ->setMethods(['read']) ->getMock(); $session->expects($this->at(0)) @@ -163,7 +163,7 @@ public function testWelcome() */ public function testWelcomeNotLoggedInUser() { - $session = $this->getMockBuilder('Cake\Network\Session') + $session = $this->getMockBuilder('Cake\Http\Session') ->setMethods(['read']) ->getMock(); $session->expects($this->at(0)) From 50264285076018b07e901667720acdfe6878c407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= <613615+jtraulle@users.noreply.github.com> Date: Sun, 1 Apr 2018 21:47:57 +0200 Subject: [PATCH 0778/1476] Aliasing CakePHP requirement --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bfd71f729..4ff66a0fc 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "dev-3.next", + "cakephp/cakephp": "dev-3.next as 3.6.0-RC1", "cakedc/auth": "^2.0" }, "require-dev": { From 19566600758439a8732e2b931bf112aca18e0804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Sun, 1 Apr 2018 22:03:07 +0200 Subject: [PATCH 0779/1476] Put use classes in alphabetic order. --- tests/TestCase/Auth/SocialAuthenticateTest.php | 2 +- .../Controller/Component/GoogleAuthenticatorComponentTest.php | 2 +- tests/TestCase/Controller/Component/UsersAuthComponentTest.php | 2 +- tests/TestCase/Controller/Traits/LinkSocialTraitTest.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php index 4eafafef7..14a5f72bb 100644 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -19,9 +19,9 @@ use Cake\Controller\ComponentRegistry; use Cake\Core\Configure; use Cake\Event\Event; +use Cake\Http\Response; use Cake\Http\ServerRequest; use Cake\Network\Request; -use Cake\Http\Response; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use ReflectionClass; diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index 659cfbe03..f708e7f6f 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -19,8 +19,8 @@ use Cake\Core\Plugin; use Cake\Database\Exception; use Cake\Event\Event; -use Cake\Network\Request; use Cake\Http\Session; +use Cake\Network\Request; use Cake\ORM\Entity; use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 6f2c7aaef..922646bda 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -20,8 +20,8 @@ use Cake\Database\Exception; use Cake\Event\Event; use Cake\Http\ServerRequest; -use Cake\Network\Request; use Cake\Http\Session; +use Cake\Network\Request; use Cake\ORM\Entity; use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 86a45be55..35efd039e 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -14,9 +14,9 @@ use CakeDC\Users\Controller\Traits\LinkSocialTrait; use Cake\Core\Configure; use Cake\Event\Event; +use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; use Cake\I18n\Time; -use Cake\Http\Exception\NotFoundException; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use League\OAuth2\Client\Provider\Facebook; From 815d0c6605ae57be9530bd943e7e4c23fa848b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= <613615+jtraulle@users.noreply.github.com> Date: Mon, 2 Apr 2018 11:21:07 +0200 Subject: [PATCH 0780/1476] Adjusted future version numbers in README file. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index af4cdedb9..3fed7a14b 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,9 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^3.5 | [master](https://github.com/cakedc/users/tree/master) | 6.0.1 | stable | -| ^3.5 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | +| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 7.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 | | 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 | From 228d5469a6e260b9bbf607acb7b17acfaf55269b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 22 Jan 2018 09:39:35 +0000 Subject: [PATCH 0781/1476] Update Extending-the-Plugin.md Improve docs thanks to @llincoln --- Docs/Documentation/Extending-the-Plugin.md | 2 ++ src/Controller/Component/UsersAuthComponent.php | 1 + src/Controller/Traits/PasswordManagementTrait.php | 8 ++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index 01a5b5b99..3da0705d6 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -180,6 +180,8 @@ Updating the Templates Use the standard CakePHP conventions to override Plugin views using your application views http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application +`{project_dir}/src/Template/Plugin/CakeDC/Users/Users/{templates_in_here}` + Updating the Emails ------------------- diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 9944abfe0..f32dff7ee 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -33,6 +33,7 @@ class UsersAuthComponent extends Component const EVENT_BEFORE_LOGOUT = 'Users.Component.UsersAuth.beforeLogout'; 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'; /** * Initialize method, setup Auth if not already done passing the $config provided and diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 653498906..a2f04d480 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; @@ -71,8 +72,12 @@ public function changePassword() } else { $user = $this->getUsersTable()->changePassword($user); if ($user) { - $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $user]); + if (is_array($event->result)) { + return $this->redirect($event->result); + } + $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); return $this->redirect($redirect); } else { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); @@ -130,7 +135,6 @@ public function requestResetPassword() $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); $this->Flash->error($msg); } - return $this->redirect(['action' => 'login']); } catch (UserNotFoundException $exception) { $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); From e0ee947a572303d6b116da7c9db5884ff4af27e2 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 11 Apr 2018 16:47:12 -0500 Subject: [PATCH 0782/1476] Adding after change password event --- src/Controller/Traits/PasswordManagementTrait.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index a2f04d480..96146c71f 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -73,11 +73,12 @@ public function changePassword() $user = $this->getUsersTable()->changePassword($user); if ($user) { $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $user]); - if (is_array($event->result)) { + if (!empty($event) && is_array($event->result)) { + return $this->redirect($event->result); } - $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); + return $this->redirect($redirect); } else { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); From 0f79d15e3623b5e2383f15be75a4496a01969a0e Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 11 Apr 2018 16:47:45 -0500 Subject: [PATCH 0783/1476] Adding unit test for after change password event --- .../Traits/PasswordManagementTraitTest.php | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index a47d91e57..b246980f7 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Cake\Event\Event; use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; use Cake\Auth\PasswordHasherFactory; use Cake\Core\Configure; @@ -27,7 +28,7 @@ class PasswordManagementTraitTest extends BaseTraitTest public function setUp() { $this->traitClassName = 'CakeDC\Users\Controller\Traits\PasswordManagementTrait'; - $this->traitMockMethods = ['set', 'redirect', 'validate', 'log']; + $this->traitMockMethods = ['set', 'redirect', 'validate', 'log', 'dispatchEvent']; $this->mockDefaultEmail = true; parent::setUp(); } @@ -93,6 +94,42 @@ public function testChangePasswordWithError() $this->Trait->changePassword(); } + /** + * test + * + * @return void + */ + public function testChangePasswordWithAfterChangeEvent() + { + $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'new', + ])); + $event = new Event('event'); + $event->result = [ + 'action' => 'newAction', + ]; + $this->Trait->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'newAction']); + $this->Trait->Flash->expects($this->any()) + ->method('success') + ->with('Password has been changed successfully'); + $this->Trait->changePassword(); + $hasher = PasswordHasherFactory::build('Default'); + $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); + + } + /** * test * From 9bdd81d8335ba0fb5b1c5f8eb4f5380f2e0dddef Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 11 Apr 2018 17:02:29 -0500 Subject: [PATCH 0784/1476] Fix cs --- .../TestCase/Controller/Traits/PasswordManagementTraitTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index b246980f7..555c99386 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -12,7 +12,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Event\Event; -use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; use Cake\Auth\PasswordHasherFactory; use Cake\Core\Configure; use Cake\ORM\TableRegistry; @@ -127,7 +126,6 @@ public function testChangePasswordWithAfterChangeEvent() $this->Trait->changePassword(); $hasher = PasswordHasherFactory::build('Default'); $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); - } /** From c6e6458fcb9c96b39febe3a7804aaaeeb42dc909 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Wed, 11 Apr 2018 17:33:26 -0500 Subject: [PATCH 0785/1476] Fix cs --- src/Controller/Traits/PasswordManagementTrait.php | 2 +- .../TestCase/Controller/Traits/PasswordManagementTraitTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 96146c71f..467c0a705 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -74,7 +74,6 @@ public function changePassword() if ($user) { $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $user]); if (!empty($event) && is_array($event->result)) { - return $this->redirect($event->result); } $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); @@ -136,6 +135,7 @@ public function requestResetPassword() $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); $this->Flash->error($msg); } + return $this->redirect(['action' => 'login']); } catch (UserNotFoundException $exception) { $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 555c99386..f4d292765 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -11,9 +11,9 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\Event\Event; use Cake\Auth\PasswordHasherFactory; use Cake\Core\Configure; +use Cake\Event\Event; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; From f286dfbf997e227125bb349c7cfe5969b5b1b4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= <613615+jtraulle@users.noreply.github.com> Date: Mon, 16 Apr 2018 15:54:00 +0200 Subject: [PATCH 0786/1476] Lock CakePHP dependency to ^3.6 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4ff66a0fc..93d1a1dbd 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "dev-3.next as 3.6.0-RC1", + "cakephp/cakephp": "^3.6", "cakedc/auth": "^2.0" }, "require-dev": { From dca16b1d394f6451fc2ee67c2b74b9b7069b0194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 18 Apr 2018 17:31:19 -0500 Subject: [PATCH 0787/1476] Update LinkSocialTraitTest.php Fix typo, in previous code but detected just now :P --- tests/TestCase/Controller/Traits/LinkSocialTraitTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 35efd039e..00ce7b11b 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -380,7 +380,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') From dcca49767b7bff64a2d4871d7badaada2d7d1187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 20 Apr 2018 08:01:06 +0100 Subject: [PATCH 0788/1476] doc fixes --- .semver | 4 ++-- .travis.yml | 5 +++-- CHANGELOG.md | 4 ++++ Docs/Documentation/Installation.md | 5 ++++- Docs/Documentation/Migration/6.x-7.0.md | 18 ++++++++++++++++++ Docs/Home.md | 1 + LICENSE.txt | 2 +- README.md | 2 +- config/permissions.php | 3 +-- 9 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 Docs/Documentation/Migration/6.x-7.0.md diff --git a/.semver b/.semver index f08998704..d42bf6c44 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- -:major: 6 +:major: 7 :minor: 0 -:patch: 1 +:patch: 0 :special: '' diff --git a/.travis.yml b/.travis.yml index ccae8dd02..e71ec741f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ php: - 5.6 - 7.0 - 7.1 + - 7.2 sudo: false @@ -20,10 +21,10 @@ matrix: fast_finish: true include: - - php: 7.0 + - php: 7.1 env: PHPCS=1 DEFAULT=0 - - php: 7.0 + - php: 7.1 env: CODECOVERAGE=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' before_script: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5949db7bc..1cf5f6f8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Changelog Releases for CakePHP 3 ------------- +* 7.0.0 + * Removed deprecations for CakePHP 3.6 + * Updated docs + * 6.0.0 * Removed deprecations and orWhere usage * Amazon login implemented diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 7d043f5c1..18b244230 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -106,7 +106,10 @@ Load the Component in your src/Controller/AppController.php, and use the passed public function initialize() { parent::initialize(); - $this->loadComponent('Flash'); + + // Important: add the 'enableBeforeRedirect' config or or disable deprecation warnings + $this->loadComponent('RequestHandler', ['enableBeforeRedirect' => false]); + $this->loadComponent('Flash'); $this->loadComponent('CakeDC/Users.UsersAuth'); } ``` diff --git a/Docs/Documentation/Migration/6.x-7.0.md b/Docs/Documentation/Migration/6.x-7.0.md new file mode 100644 index 000000000..3258e398f --- /dev/null +++ b/Docs/Documentation/Migration/6.x-7.0.md @@ -0,0 +1,18 @@ +Migration 6.x to 7.0 +====================== + +7.0 is compatible with CakePHP ^3.6 and the plugin code was updated to remove all deprecations. + +* Add 'enableBeforeRedirect' configuration option to RequestHandler component load in your `src/Controller/AppController.php` file + +``` + public function initialize() + { + parent::initialize(); + + // Important: add the 'enableBeforeRedirect' config or or disable deprecation warnings + $this->loadComponent('RequestHandler', ['enableBeforeRedirect' => false]); + $this->loadComponent('Flash'); + $this->loadComponent('CakeDC/Users.UsersAuth'); + } +``` diff --git a/Docs/Home.md b/Docs/Home.md index 6451cc129..378d61db9 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -27,5 +27,6 @@ Migration guides ---------------- * [4.x to 5.0](Documentation/Migration/4.x-5.0.md) +* [6.x to 7.0](Documentation/Migration/6.x-7.0.md) diff --git a/LICENSE.txt b/LICENSE.txt index 270499663..5448b2520 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License -Copyright 2009-2017 +Copyright 2009-2018 Cake Development Corporation 1785 E. Sahara Avenue, Suite 490-423 Las Vegas, Nevada 89104 diff --git a/README.md b/README.md index 3fed7a14b..1c213f6a7 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.4.0+ +* CakePHP 3.6.0+ * PHP 5.6+ Documentation diff --git a/config/permissions.php b/config/permissions.php index a437994a1..79a4ae957 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -50,7 +50,7 @@ */ return [ - 'Users.SimpleRbac.permissions' => [ + 'CakeDC/Auth.permissions' => [ //admin role allowed to all the things [ 'role' => 'admin', @@ -84,7 +84,6 @@ //all roles allowed to Pages/display [ 'role' => '*', - //'plugin' => null, 'controller' => 'Pages', 'action' => 'display', ], From a2cf90d9bc073dacde3488ec808ef8118721866a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 20 Apr 2018 08:21:19 +0100 Subject: [PATCH 0789/1476] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cf5f6f8a..0ce6ea612 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Releases for CakePHP 3 * 7.0.0 * Removed deprecations for CakePHP 3.6 + * Added a new `UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD` * Updated docs * 6.0.0 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 0790/1476] 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 0791/1476] 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 544caced7966fc90859a4c56f7b60a076e23214f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 26 Apr 2018 13:03:35 +0100 Subject: [PATCH 0792/1476] fix docs fixes #570 thanks to @makamo for reporting --- 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 db4f2887f..e4db903d1 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -140,10 +140,10 @@ Using the UsersAuthComponent default initialization, the component will load the * '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 - * 'CakeDC/Auth.ApiKey' check [ApiKeyAuthenticate](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/ApiKeyAuthenticate.md) for configuration options ## Using the user's email to login From 30ea0afb6697ff6f27b48a060222ff91be5b31b1 Mon Sep 17 00:00:00 2001 From: Andrej Griniuk Date: Mon, 30 Apr 2018 21:26:11 +1000 Subject: [PATCH 0793/1476] CakeDC/Users.RememberMe -> CakeDC/Auth.RememberMe --- 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 e4db903d1..f52015acb 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -120,7 +120,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'all' => [ 'finder' => 'active', ], - 'CakeDC/Users.RememberMe', + 'CakeDC/Auth.RememberMe', 'Form', ], 'authorize' => [ From 2e2219b499a4e01af96eaa3b5909e68531a0203b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 1 May 2018 13:05:36 +0200 Subject: [PATCH 0794/1476] 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 0795/1476] 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 0796/1476] 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 0797/1476] 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 0798/1476] 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 0799/1476] 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 0800/1476] 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 0801/1476] 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 0802/1476] 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 0803/1476] 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 0804/1476] 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 0805/1476] 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 0806/1476] 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 0807/1476] 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 0808/1476] 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 0809/1476] 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 0810/1476] 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 0811/1476] 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 0812/1476] 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 0813/1476] 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 0814/1476] 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 0815/1476] 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 0816/1476] 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 0817/1476] 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 0818/1476] 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 0819/1476] 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 0820/1476] 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 0821/1476] 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 0822/1476] 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 0823/1476] 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 0824/1476] 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 0825/1476] 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 0826/1476] 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 0827/1476] 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 0828/1476] 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 0829/1476] 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 0830/1476] 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 0831/1476] 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 0832/1476] 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 0833/1476] 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 0834/1476] 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 0835/1476] 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 0836/1476] 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 0837/1476] 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 0838/1476] 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 0839/1476] 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 0840/1476] 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 0841/1476] 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 0842/1476] 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 0843/1476] 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 0844/1476] 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 0845/1476] 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 0846/1476] 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 0847/1476] 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 0848/1476] 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 0849/1476] 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 0850/1476] 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 0851/1476] 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 0852/1476] 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 0853/1476] 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 0854/1476] 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 0855/1476] 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 0856/1476] 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 0857/1476] 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 0858/1476] 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 0859/1476] 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 0860/1476] 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 0861/1476] 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 0862/1476] 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 0863/1476] 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 0864/1476] 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 0865/1476] 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 0866/1476] 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 0867/1476] 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 0868/1476] 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 0869/1476] 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 0870/1476] 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 0871/1476] 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 0872/1476] 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 0873/1476] 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 0874/1476] 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 0875/1476] 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 0876/1476] 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 0877/1476] 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 0878/1476] 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 0879/1476] 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 0880/1476] 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 0881/1476] 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 0882/1476] 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 0883/1476] 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 0884/1476] 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 0885/1476] 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 0886/1476] 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 0887/1476] 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 0888/1476] 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 0889/1476] 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 0890/1476] 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 0891/1476] 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 0892/1476] 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 0893/1476] 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 0894/1476] 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 0895/1476] 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 0896/1476] 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 0897/1476] 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 0898/1476] 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 0899/1476] 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 0900/1476] 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 0901/1476] 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 0902/1476] 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 0903/1476] 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 0904/1476] 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 0905/1476] 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 0906/1476] 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 0907/1476] 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 0908/1476] 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 0909/1476] 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 0910/1476] 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 0911/1476] 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 0912/1476] 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 0913/1476] 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 0914/1476] 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 0915/1476] 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 0916/1476] 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 0917/1476] 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 0918/1476] 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 0919/1476] 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 0920/1476] 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 0921/1476] 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 0922/1476] 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 0923/1476] 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 0924/1476] 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 0925/1476] 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 0926/1476] 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 0927/1476] 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 0928/1476] 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 0929/1476] 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 0930/1476] 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 0931/1476] 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 0932/1476] 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 0933/1476] 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 0934/1476] 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 0935/1476] 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 0936/1476] 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 0937/1476] 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 0938/1476] 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 0939/1476] 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 0940/1476] 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 0941/1476] 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 0942/1476] 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 0943/1476] 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 0944/1476] 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 0945/1476] 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 0946/1476] 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 0947/1476] 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 0948/1476] 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 0949/1476] 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 0950/1476] 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 0951/1476] 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 0952/1476] 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 0953/1476] 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 0954/1476] 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 0955/1476] 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 0956/1476] 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 0957/1476] 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 0958/1476] 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 0959/1476] 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 0960/1476] 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 0961/1476] 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 0962/1476] 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 0963/1476] 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 0964/1476] 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 0965/1476] 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 0966/1476] 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 0967/1476] 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 0968/1476] 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 0969/1476] 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 0970/1476] 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 0971/1476] 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 0972/1476] 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 0973/1476] 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 0974/1476] 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 0975/1476] 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 0976/1476] 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 0977/1476] 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 0978/1476] 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 0979/1476] 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 0980/1476] 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 0981/1476] 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 0982/1476] 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 0983/1476] 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 0984/1476] 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 0985/1476] 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 0986/1476] 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 0987/1476] 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 0988/1476] 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 0989/1476] 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 0990/1476] 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 0991/1476] 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 0992/1476] 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 0993/1476] 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 0994/1476] 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 0995/1476] 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 0996/1476] 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 0997/1476] 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 0998/1476] =?UTF-8?q?doc=20how=20we=20handle=20login=C2=A0?= =?UTF-8?q?result?= 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 0999/1476] 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 1000/1476] 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 1001/1476] 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 1002/1476] 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 1003/1476] 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 1004/1476] 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 1005/1476] 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 1006/1476] 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 1007/1476] 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 1008/1476] 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 1009/1476] 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 1010/1476] 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 1182/1476] 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 1183/1476] 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 1184/1476] 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 1185/1476] 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 1186/1476] 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 1187/1476] 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 1188/1476] 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 1189/1476] 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 1190/1476] 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 1191/1476] 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 1192/1476] 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 1193/1476] 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 1194/1476] 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 1195/1476] 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 1196/1476] 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 1197/1476] 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 1198/1476] 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 1199/1476] 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 1200/1476] 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 1201/1476] 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 1202/1476] #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 1203/1476] #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 1204/1476] #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 1205/1476] 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 1206/1476] 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 1207/1476] 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 1208/1476] 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 1209/1476] 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 1210/1476] 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 1211/1476] 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 1212/1476] 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 1213/1476] 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 1214/1476] 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 1215/1476] 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 1216/1476] 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 1217/1476] 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 1218/1476] 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 1219/1476] 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 1220/1476] 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 1221/1476] 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 1222/1476] 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 1223/1476] 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 1224/1476] 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 1225/1476] 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 1226/1476] 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 1227/1476] 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 1228/1476] 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 1229/1476] 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 1230/1476] 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 1231/1476] 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 1232/1476] 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 1233/1476] 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 1234/1476] 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 1235/1476] 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 1236/1476] 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 1237/1476] 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 1238/1476] 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 1239/1476] 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 1240/1476] 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 1241/1476] 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 1242/1476] 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 1243/1476] 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 1244/1476] 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 1245/1476] 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 1246/1476] 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 1247/1476] 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 1248/1476] 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 1249/1476] 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 1250/1476] 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 1251/1476] 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 1252/1476] 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 1253/1476] 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 1254/1476] 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 1255/1476] 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 1256/1476] 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 1257/1476] 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 1258/1476] 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 1259/1476] 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 1260/1476] 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 1261/1476] 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 1262/1476] 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 1263/1476] 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 1264/1476] 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 1265/1476] 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 1266/1476] 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 1267/1476] 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 1268/1476] 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 1269/1476] 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 1270/1476] 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 1271/1476] 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 1272/1476] 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 1273/1476] 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 1274/1476] 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 1275/1476] 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 1276/1476] 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 1277/1476] 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 1278/1476] 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 1279/1476] 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 1280/1476] 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 1281/1476] 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 1282/1476] 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 1283/1476] 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 1284/1476] 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 1285/1476] 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 1286/1476] 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 1287/1476] 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 1288/1476] 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 1289/1476] 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 1290/1476] 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 1291/1476] 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 1292/1476] 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 1293/1476] 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 1294/1476] 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 1295/1476] 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 1296/1476] 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 1297/1476] 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 1298/1476] 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 1299/1476] 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 1300/1476] 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 1301/1476] 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 1302/1476] 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 1303/1476] 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 1304/1476] 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 1305/1476] 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 1306/1476] 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 1307/1476] 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 1308/1476] 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 1309/1476] 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 1310/1476] 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 1311/1476] 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 1312/1476] 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 1313/1476] 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 1314/1476] 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 1315/1476] 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 1316/1476] 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 1317/1476] 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 1318/1476] 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 1319/1476] 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 1320/1476] 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 1321/1476] 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 1322/1476] 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 1323/1476] 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 1324/1476] 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 1325/1476] 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 1326/1476] 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 1327/1476] 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 1328/1476] 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 1329/1476] 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 1330/1476] 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 1331/1476] 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 1332/1476] 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 1333/1476] 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 1334/1476] 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 1335/1476] 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 1336/1476] 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 1337/1476] 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 1338/1476] 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 1339/1476] 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 1340/1476] 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 1341/1476] 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 1342/1476] 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 1343/1476] 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 1344/1476] 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 1345/1476] 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 1346/1476] 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 1347/1476] 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 1348/1476] 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 1349/1476] 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 1350/1476] 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 1351/1476] 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 1352/1476] #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 1353/1476] 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 1354/1476] #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 1355/1476] #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 1356/1476] #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 1357/1476] #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 1358/1476] #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 1359/1476] #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 1360/1476] 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 1361/1476] 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 1362/1476] 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 1363/1476] 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 1364/1476] 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 1365/1476] 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 1366/1476] 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 1367/1476] 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 1368/1476] 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 1369/1476] 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 1370/1476] test From 4bf939d6af6d5db218aff2931e8feafb87ec79d8 Mon Sep 17 00:00:00 2001 From: Eugene Ritter Date: Wed, 11 Nov 2020 20:15:50 -0600 Subject: [PATCH 1371/1476] 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 1372/1476] 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 1373/1476] 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 1374/1476] 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 1375/1476] 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 1376/1476] 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 1377/1476] 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 1378/1476] 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 1379/1476] 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 1380/1476] 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 1381/1476] #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 1382/1476] #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 1383/1476] #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 1384/1476] #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 1385/1476] #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 1386/1476] #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 1387/1476] 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 1388/1476] 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 1389/1476] 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 1390/1476] 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 1391/1476] 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 1392/1476] 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 1393/1476] 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 1394/1476] 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 1395/1476] #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 1396/1476] 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 1397/1476] 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 1398/1476] 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 1399/1476] 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 1400/1476] 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 1401/1476] 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 1402/1476] 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 1403/1476] 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 1404/1476] 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 1405/1476] #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 1406/1476] 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 1407/1476] #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 1408/1476] 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 1409/1476] 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 1410/1476] 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 1411/1476] 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 1412/1476] 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 1413/1476] 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 1414/1476] 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 1415/1476] 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 1416/1476] 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 1417/1476] 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 1418/1476] 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 1419/1476] 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 1420/1476] 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 1421/1476] 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 1422/1476] 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 1423/1476] 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 1424/1476] 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 1425/1476] 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 1426/1476] 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 1427/1476] 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 1428/1476] 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 1429/1476] 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 1430/1476] 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 1431/1476] 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 1432/1476] 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 1433/1476] 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 1434/1476] 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 1435/1476] 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 1436/1476] 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 1437/1476] 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 1438/1476] 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 1439/1476] 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 1440/1476] 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 1441/1476] 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 1442/1476] 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 1443/1476] 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 1444/1476] 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 1445/1476] 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 1446/1476] 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 1447/1476] 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 1448/1476] 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 1449/1476] 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 1450/1476] 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 1451/1476] 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 1452/1476] 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 1453/1476] 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 1454/1476] 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 1455/1476] 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 1456/1476] 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 1457/1476] 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 1458/1476] 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 1459/1476] 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 1460/1476] 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 1461/1476] 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 1462/1476] 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 1463/1476] 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 1464/1476] 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 1465/1476] 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 1466/1476] 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 1467/1476] 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 1468/1476] 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 1469/1476] 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 1470/1476] 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 1471/1476] 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 1472/1476] 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 1473/1476] 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 1474/1476] 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 1475/1476] 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 1476/1476] 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