diff --git a/Config/Migration/001_initialize_users_schema.php b/Config/Migration/001_initialize_users_schema.php index 643d44a9d..db36cd21c 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/Component/RememberMeComponent.php b/Controller/Component/RememberMeComponent.php new file mode 100644 index 000000000..41d84fb73 --- /dev/null +++ b/Controller/Component/RememberMeComponent.php @@ -0,0 +1,197 @@ + true, + 'userModel' => 'User', + 'cookieKey' => 'rememberMe', + 'cookie' => array( + 'name' => 'User'), + '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->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; + } + +/** + * 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; + } + + extract($this->settings); + $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]; + } + } + + $result = $this->Auth->login(); + + if (!$result) { + $this->request->data = $request; + } + + return $result; + } + } + +/** + * 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]; + } + } + + return $this->Cookie->write($cookieKey, $cookieData, true, '+99 years'); + } + +/** + * 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(__('users', 'Invalid options %s', $key)); + } + } + } +} \ No newline at end of file diff --git a/Controller/UserDetailsController.php b/Controller/UserDetailsController.php index 9dee9c783..fdc36edf3 100644 --- a/Controller/UserDetailsController.php +++ b/Controller/UserDetailsController.php @@ -1,11 +1,11 @@ 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/UsersAppController.php b/Controller/UsersAppController.php index 2c90c3a38..4d2dc1691 100644 --- a/Controller/UsersAppController.php +++ b/Controller/UsersAppController.php @@ -1,11 +1,11 @@ _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; + } + } + +/** + * 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; } /** @@ -87,7 +124,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'; @@ -98,7 +135,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'; @@ -140,14 +177,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'); } /** @@ -159,7 +196,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)); } @@ -170,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); } @@ -182,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('/'); @@ -197,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]; } } @@ -218,8 +255,8 @@ public function edit() { */ public function admin_index() { $this->Prg->commonProcess(); - $this->User->validator()->remove('username'); - $this->User->validator()->remove('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); @@ -244,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)); } /** @@ -254,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')); } @@ -273,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')); @@ -286,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')); } @@ -298,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')); @@ -328,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 { @@ -349,8 +386,11 @@ public function add() { public function login() { if ($this->request->is('post')) { if ($this->Auth->login()) { - $this->User->id = $this->Auth->user('id'); - $this->User->saveField('last_login', date('Y-m-d H:i:s')); + $this->getEventManager()->dispatch(new CakeEvent('Users.afterLogin', $this, array( + 'isFirstLogin' => !$this->Auth->user('last_login')))); + + $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 = '/'; @@ -358,7 +398,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'])) { @@ -382,6 +426,7 @@ public function login() { /** * Search - Requires the CakeDC Search plugin to work * + * @throws MissingPluginException * @return void * @link https://github.com/CakeDC/search */ @@ -431,6 +476,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()); } @@ -449,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) { @@ -462,6 +508,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) { @@ -469,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')); @@ -479,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')); @@ -498,15 +545,15 @@ 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')) - ->template('new_password') + ->template($this->_pluginDot() . 'new_password') ->viewVars(array( 'model' => $this->modelClass, 'userData' => $userData)) - ->send($content); + ->send(); } /** @@ -517,8 +564,10 @@ 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.')); + // we don't want to keep the cookie with the old password around + $this->RememberMe->destroyCookie(); $this->redirect('/'); } } @@ -551,7 +600,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 */ @@ -578,8 +628,8 @@ protected function _sendVerificationEmail($userData, $options = array()) { $defaults = array( 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Account verification'), - 'template' => 'Users.account_verification', - 'layout'=> 'default'); + 'template' => $this->_pluginDot() . 'account_verification', + 'layout' => 'default'); $options = array_merge($defaults, $options); @@ -606,13 +656,13 @@ protected function _sendPasswordReset($admin = null, $options = array()) { $defaults = array( 'from' => Configure::read('App.defaultEmail'), 'subject' => __d('users', 'Password Reset'), - 'template' => 'Users.password_reset_request', - 'layout'=> 'default'); + 'template' => $this->_pluginDot() . 'password_reset_request', + 'layout' => 'default'); $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)) { @@ -623,8 +673,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) { @@ -647,32 +697,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 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 = 'User') { - 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'); - - $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']); + protected function _setCookie($options = array(), $cookieKey = 'rememberMe') { + $this->RememberMe->settings['cookieKey'] = $cookieKey; + $this->RememberMe->configureCookie($options); + $this->RememberMe->setCookie(); } /** @@ -682,13 +716,13 @@ protected function _setCookie($options = array(), $cookieKey = 'User') { * @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); } diff --git a/Model/User.php b/Model/User.php index 197e90b54..62f5453d9 100644 --- a/Model/User.php +++ b/Model/User.php @@ -1,11 +1,11 @@ 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 */ @@ -708,10 +713,9 @@ protected function _findSearch($state, $query, $results = array()) { $query['search'] = ''; } - $db =& ConnectionManager::getDataSource($this->useDbConfig); + $db = ConnectionManager::getDataSource($this->useDbConfig); $by = $query['by']; $search = $query['search']; - $byQuoted = $db->value($search); $like = '%' . $query['search'] . '%'; switch ($by) { @@ -767,7 +771,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 +792,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 9ae7c9353..9e485f162 100644 --- a/Model/UserDetail.php +++ b/Model/UserDetail.php @@ -1,11 +1,11 @@ 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( @@ -257,4 +257,3 @@ public function saveSection($userId = null, $data = null, $section = null) { return true; } } -; \ No newline at end of file diff --git a/Model/UsersAppModel.php b/Model/UsersAppModel.php index ca07f0267..bd062bada 100644 --- a/Model/UsersAppModel.php +++ b/Model/UsersAppModel.php @@ -1,11 +1,11 @@ addTestFile($basePath . 'Controller' . DS . 'UserDetailsControllerTest.php'); $suite->addTestFile($basePath . 'Controller' . DS . 'UsersControllerTest.php'); diff --git a/Test/Case/Controller/Component/RememberMeComponentTest.php b/Test/Case/Controller/Component/RememberMeComponentTest.php new file mode 100644 index 000000000..d45d003f5 --- /dev/null +++ b/Test/Case/Controller/Component/RememberMeComponentTest.php @@ -0,0 +1,163 @@ + array( + 'email' => 'test@cakedc.com', + 'password' => 'test'), + 'admin' => array( + 'email' => 'admin@cakedc.com', + 'password' => 'admin')); + +/** + * start + * + * @return void + */ + public function setUp() { + $_COOKIE = array(); + $this->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($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 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' => $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'); + $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/UserDetailsControllerTest.php b/Test/Case/Controller/UserDetailsControllerTest.php index aacd167e0..ae87ff009 100644 --- a/Test/Case/Controller/UserDetailsControllerTest.php +++ b/Test/Case/Controller/UserDetailsControllerTest.php @@ -1,11 +1,11 @@ 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 +244,36 @@ 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('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('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')); + ->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))); + $this->assertEqual(Router::normalize($this->Users->redirectUrl), Router::normalize(Router::url($this->Users->Auth->loginRedirect))); } /** @@ -277,10 +286,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 +301,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 +330,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 +346,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 +362,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 +387,25 @@ 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->RememberMe = $this->getMock('RememberMeComponent', array(), array($this->Collection)); + $this->Users->RememberMe->expects($this->any()) + ->method('destroyCookie'); + + $this->Users->logout(); $this->assertEqual($this->Users->redirectUrl, '/'); } @@ -437,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, '/'); } @@ -537,23 +554,27 @@ 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->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->Cookie->name = 'userTestCookie'; - $result = $this->Users->Cookie->read('User'); - $this->assertEqual($result, array( - 'password' => 'testtest', - 'email' => 'testuser@cakedc.com', - )); + + $this->assertEqual($this->Users->RememberMe->settings['cookieKey'], 'rememberMe'); } - + /** * Test getting default and setted email instance config * @@ -570,7 +591,6 @@ public function testGetMailInstance() { $this->setExpectedException('ConfigureException'); Configure::write('Users.emailConfig', 'doesnotexist'); $anotherConfig = $this->Users->getMailInstance()->config(); - } /** @@ -597,7 +617,7 @@ private function __setGet() { * * @return void */ - public function endTest() { + public function endTest($method) { $this->Users->Session->destroy(); unset($this->Users); ClassRegistry::flush(); diff --git a/Test/Case/Model/UserDetailTest.php b/Test/Case/Model/UserDetailTest.php index ea0127f83..3953fde90 100755 --- a/Test/Case/Model/UserDetailTest.php +++ b/Test/Case/Model/UserDetailTest.php @@ -1,11 +1,11 @@ User); ClassRegistry::flush(); } + /** * * diff --git a/Test/Fixture/UserDetailFixture.php b/Test/Fixture/UserDetailFixture.php index 909e60208..1a72385dc 100644 --- a/Test/Fixture/UserDetailFixture.php +++ b/Test/Fixture/UserDetailFixture.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..f87c8922c 100644 --- a/View/Users/add.ctp +++ b/View/Users/add.ctp @@ -1,11 +1,11 @@ @@ -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'); ?> 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..73dbb4ab0 100644 --- a/View/Users/admin_index.ctp +++ b/View/Users/admin_index.ctp @@ -1,11 +1,11 @@ @@ -21,6 +21,7 @@ ?> element('paging'); ?> + element('pagination'); ?> @@ -62,5 +63,6 @@
Paginator->sort('username'); ?>
+ element('pagination'); ?> element('Users/admin_sidebar'); ?> 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..e803fe2b9 100644 --- a/View/Users/login.ctp +++ b/View/Users/login.ctp @@ -1,11 +1,11 @@ @@ -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( 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 diff --git a/readme.md b/readme.md index a2f700b7e..be4021668 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. @@ -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->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); - } + 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 + + $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 ## @@ -69,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. @@ -76,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 @@ -93,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.