public function indexAction() { $this->tag->setTitle('Users'); $this->pageName = 'users'; $users = Users::find(); $this->view->setVar('users', $users); }
/** * LOGIN BRUTE FORCE PROTECTION * This will slow down failed login attempts by throttling the request time. * If the requests continue to fail a Recaptcha will be shown (if enabled) * and finally the login form will be disabled for a while. * * @param $userName * @param bool $clear * @return array */ public function loginAttempts($userName, $option = FALSE) { $blockTime = \Phalcon\DI::getDefault()->getShared('config')->brute->block_time * 60; $user = Users::findFirst(array('username=:username:'******'bind' => array(':username' => $userName))); if ($user) { $userId = $user->id; } else { // user didn't even get the user name right $userId = NULL; } $footprint = md5(\Phalcon\DI::getDefault()->getShared('request')->getClientAddress() . \Phalcon\DI::getDefault()->getShared('request')->getUserAgent()); // if clearing attempts after successful login if ($option == 'clear') { $toDelete = FailedLogins::find(array('conditions' => 'user_id=:user_id: OR time <' . (time() - 60 * 60 * 24 * 365), 'bind' => array(':user_id' => $userId))); if (count($toDelete) > 0) { $toDelete->delete(); return TRUE; } } $captcha = FALSE; $block = FALSE; // get attempts so far if (is_numeric($userId)) { // if username was correct $attemptsDb = FailedLogins::find(array('conditions' => '(user_id=:user_id: OR footprint=:footprint:) AND time >' . (time() - $blockTime), 'bind' => array(':user_id' => $userId, ':footprint' => $footprint))); $attempts = count($attemptsDb); } else { // if username was not correct - we search on footprint only $attemptsDb = FailedLogins::find(array('conditions' => 'footprint=:footprint: AND time >' . (time() - $blockTime), 'bind' => array(':footprint' => $footprint))); $attempts = count($attemptsDb); } if ($option != 'state') { // increment the number of attempts $attempts++; // generate record in DB $fail = new FailedLogins(); $fail->user_id = $userId; $fail->time = time(); $fail->ip = \Phalcon\DI::getDefault()->getShared('request')->getClientAddress(); $fail->useragent = \Phalcon\DI::getDefault()->getShared('request')->getUserAgent(); $fail->footprint = $footprint; $fail->save(); } // carry out blocks if ($attempts >= 1 && $attempts <= 3) { if ($option != 'state') { sleep($attempts * 2); // throttle speed to slow them down } } else { if ($attempts > 3 && $attempts < 10) { if ($option != 'state') { sleep($attempts); // throttle attempts for longer and longer } $captcha = TRUE; // now we start using captcha } else { if ($attempts >= 10) { if ($option != 'state') { sleep($attempts); // throttle attempts for longer and longer } $captcha = TRUE; // now we start using captcha $block = TRUE; // block the login form } } } return array('attempts' => $attempts, 'attempts_left' => 10 - $attempts, 'captcha' => $captcha, 'block' => $block); }
/** * USER RESET PASSWORD * This is the process for a user to reset their password if they have forgotten it. * It works in the usual way - user enters email address and if the email address is * recognised, the system sends a reset link to their email. The reset link is * encrypted and contains a JSON encoded object which has the user id, username, * time (link was generated) and a hash key for further verification. */ public function password_resetAction() { // user clicks link via email so we check them then show change password form if ($this->request->getQuery('c')) { // decrypt user $dec = rawurldecode($this->request->getQuery('c')); $decr = $this->getDI()->getShared('crypt')->decrypt($dec); $decar = json_decode($decr); // get the decrypted user info from url $user_id = $decar->user_id; $user_name = $decar->username; $time = $decar->time; $key = $decar->key; // check the link has not expired if ($time > time() - 7200) { // link expires after 2 hours // Show the set form $user = Users::findFirst(array('id=:user_id: AND username=:username:'******'bind' => array('user_id' => $user_id, 'username' => $user_name))); if ($user == TRUE) { $hash = md5($user->id . $user->email . $user->password . $this->config->auth->hash_key); if ($key == $hash) { $this->view->setVar('c', rawurlencode($dec)); $this->view->setVar('user', $user->id); $this->view->setVar('username', $user_name); } else { $this->flashSession->error('<i class="close icon"></i>' . '<div class="ui header">' . __('Error') . '!</div> ' . '<div class="content">Invalid key. You may have used an out of date link.</div>'); } } else { $this->flashSession->error('<i class="close icon"></i>' . '<div class="ui header">' . __('Error') . '!</div> ' . '<div class="content">Invalid user.</div>'); } } else { $this->flashSession->error('<i class="close icon"></i>' . '<div class="ui header">' . __('Error') . '!</div> ' . '<div class="content">The password reset link is invalid or has expired.</div>'); } // send the reset email } else { if ($this->request->isPost() == TRUE) { // request reset email submission if ($this->request->getPost('action') == 'request_reset') { if ($this->security->checkToken()) { $validation = new \Baseapp\Extension\Validation(); $validation->add('email', new \Phalcon\Validation\Validator\PresenceOf()); $validation->add('email', new \Phalcon\Validation\Validator\Email()); $validation->setLabels(array('email' => 'Email')); $messages = $validation->validate($_POST); if (count($messages)) { $this->view->setVar('errors', $validation->getMessages()); } else { $email = $this->request->getPost('email', 'email'); $email_conf = Users::findFirst(array('email=:email:', 'bind' => array('email' => $email))); if ($email_conf == TRUE) { $send = $email_conf->sendReset($email); if ($send) { $this->flashSession->notice('<i class="close icon"></i>' . '<div class="ui header">' . __('Check your inbox!') . '!</div> ' . '<div class="content">An email has been sent to you containing a link to reset your password.</div>'); } } else { $this->flashSession->error('<i class="close icon"></i>' . '<div class="ui header">' . __('Error') . '!</div> ' . '<div class="content">We do not have a record of that email address.</div>'); } } } // process and validate the reset form } else { if ($this->request->getPost('action') == 'change_pass') { if ($this->security->checkToken()) { // Reset the password if ($this->request->getPost('c')) { $dec = rawurldecode($this->request->getPost('c')); $decr = $this->getDI()->getShared('crypt')->decrypt($dec); $decar = json_decode($decr); // get the decrypted user info from form $user_id = $decar->user_id; $user_name = $decar->username; $time = $decar->time; $key = $decar->key; if ($time > time() - 7200) { // link expires after 2 hours // validate $user = Users::findFirst(array('id=:user_id: AND username=:username:'******'bind' => array('user_id' => $user_id, 'username' => $user_name))); if ($user == TRUE) { $hash = md5($user->id . $user->email . $user->password . $this->config->auth->hash_key); if ($key == $hash) { $this->view->setVar('username', $user->username); $this->view->setVar('c', $this->request->getPost('c')); $validation = new \Baseapp\Extension\Validation(); $validation->add('pass', new \Baseapp\Extension\Password()); $validation->add('pass_conf', new \Phalcon\Validation\Validator\Confirmation(array('with' => 'pass'))); $validation->setLabels(array('pass' => 'Password', 'pass_conf' => 'Confirm password')); $messages = $validation->validate($_POST); if (count($messages)) { $this->view->setVar('errors', $validation->getMessages()); } else { // update user's password $new_pass = $this->auth->hashPass($this->request->getPost('pass')); $user->password = $new_pass; if ($user->update() == TRUE) { $this->flashSession->success('<i class="close icon"></i>' . '<div class="ui header">' . __('Password updated') . '!</div> ' . '<div class="content">Your password has been successfully updated. Please login.</div>'); $this->view->setVar('completed', '1'); $this->response->redirect('user/signin'); } else { echo 'Update failed'; exit; } } } else { $this->flashSession->error('<i class="close icon"></i>' . '<div class="ui header">' . __('Error') . '!</div> ' . '<div class="content">Invalid key.</div>'); } } else { $this->flashSession->error('<i class="close icon"></i>' . '<div class="ui header">' . __('Error') . '!</div> ' . '<div class="content">Invalid user.</div>'); } } else { $this->flashSession->error('<i class="close icon"></i>' . '<div class="ui header">' . __('Error') . '!</div> ' . '<div class="content">The password reset link is invalid or has expired.</div>'); } } } else { // CSRF check failed $this->flashSession->warning('<i class="close icon"></i>' . '<div class="ui header">Form expired!</div> ' . '<div class="content">The form has expired. Please try again.</div>'); } } } } else { // show the initial form where user enters email } } }
/** * Activation Action * * @package base-app * @version 2.0 */ public function activationAction() { $this->view->pick('msg'); $this->tag->setTitle(__('Activation')); $this->view->setVar('title', __('Activation')); $params = $this->router->getParams(); $user = Users::findFirst(array('username=:user:'******'bind' => array('user' => $params[0]))); if ($user && md5($user->id . $user->email . $user->password . $this->config->auth->hash_key) == $params[1]) { $activation = $user->activation(); if ($activation === NULL) { $this->flashSession->notice($this->tag->linkTo(array('#', 'class' => 'close', 'title' => __("Close"), '×')) . '<strong>' . __('Notice') . '!</strong> ' . __("Activation has already been completed.")); } elseif ($activation === TRUE) { $this->flashSession->success($this->tag->linkTo(array('#', 'class' => 'close', 'title' => __("Close"), '×')) . '<strong>' . __('Success') . '!</strong> ' . __("Activation completed. Please log in.")); // Redirect to sign in $this->view->setVar('redirect', 'user/signin'); } } else { $this->flashSession->error($this->tag->linkTo(array('#', 'class' => 'close', 'title' => __("Close"), '×')) . '<strong>' . __('Error') . '!</strong> ' . __("Activation cannot be completed. Invalid username or hash.")); } }
/** * Refresh user data stored in the session from the database. * Returns null if no user is currently logged in. * * @package base-app * @version 2.0 * * @return mixed */ public function refresh_user() { $user = $this->_session->get($this->_config['session_key']); if (!$user) { return null; } else { // Get user's data from db $user = Users::findFirst($user->id); $roles = $this->get_roles($user); // Regenerate session_id session_regenerate_id(); // Store user in session $this->_session->set($this->_config['session_key'], $user); // Store user's roles in session if ($this->_config['session_roles']) { $this->_session->set($this->_config['session_roles'], $roles); } return $user; } }