php-censor/src/PHPCensor/Controller/SessionController.php

235 lines
7 KiB
PHP
Raw Normal View History

2013-05-10 17:25:51 +02:00
<?php
2016-07-19 20:28:11 +02:00
namespace PHPCensor\Controller;
2013-05-10 17:25:51 +02:00
use b8;
2016-07-19 20:28:11 +02:00
use PHPCensor\Helper\Email;
use PHPCensor\Helper\Lang;
use PHPCensor\Controller;
2016-12-29 06:43:02 +01:00
use PHPCensor\Security\Authentication\Service;
use PHPCensor\Store\UserStore;
2013-05-10 17:25:51 +02:00
/**
2017-03-04 16:39:56 +01:00
* Session Controller - Handles user login / logout.
*
2017-03-04 16:39:56 +01:00
* @author Dan Cryer <dan@block8.co.uk>
*/
2016-05-09 08:20:26 +02:00
class SessionController extends Controller
2013-05-10 17:25:51 +02:00
{
/**
2016-12-29 06:43:02 +01:00
* @var UserStore
*/
protected $userStore;
/**
2016-12-29 06:43:02 +01:00
* @var Service
*/
protected $authentication;
/**
* Initialise the controller, set up stores and services.
*/
public function init()
{
2013-07-30 19:45:27 +02:00
$this->response->disableLayout();
$this->userStore = b8\Store\Factory::getStore('User');
$this->authentication = Service::getInstance();
}
2013-05-10 17:25:51 +02:00
/**
* Handles user login (form and processing)
*/
public function login()
2013-07-30 19:45:27 +02:00
{
2013-10-08 08:50:42 +02:00
$isLoginFailure = false;
if ($this->request->getMethod() == 'POST') {
$token = $this->getParam('token');
if (!isset($token, $_SESSION['login_token']) || $token !== $_SESSION['login_token']) {
2013-10-08 08:50:42 +02:00
$isLoginFailure = true;
} else {
unset($_SESSION['login_token']);
$email = $this->getParam('email');
$password = $this->getParam('password', '');
$isLoginFailure = true;
$user = $this->userStore->getByEmailOrName($email);
$providers = $this->authentication->getLoginPasswordProviders();
if (null !== $user) {
// Delegate password verification to the user provider, if found
$key = $user->getProviderKey();
$isLoginFailure = !isset($providers[$key]) || !$providers[$key]->verifyPassword($user, $password);
} else {
// Ask each providers to provision the user
foreach ($providers as $provider) {
$user = $provider->provisionUser($email);
if ($user !== null && $provider->verifyPassword($user, $password)) {
$this->userStore->save($user);
$isLoginFailure = false;
break;
}
}
}
if (!$isLoginFailure) {
$_SESSION['php-censor-user-id'] = $user->getId();
$response = new b8\Http\Response\RedirectResponse();
$response->setHeader('Location', $this->getLoginRedirect());
return $response;
}
}
}
2013-05-10 17:25:51 +02:00
$form = new b8\Form();
$form->setMethod('POST');
$form->setAction(APP_URL . 'session/login');
2013-05-10 17:25:51 +02:00
2017-01-04 19:39:23 +01:00
$email = new b8\Form\Element\Text('email');
2017-01-05 11:36:13 +01:00
$email->setLabel(Lang::get('login'));
$email->setRequired(true);
$email->setContainerClass('form-group');
$email->setClass('form-control');
$form->addField($email);
2013-05-10 17:25:51 +02:00
$pwd = new b8\Form\Element\Password('password');
$pwd->setLabel(Lang::get('password'));
$pwd->setRequired(true);
$pwd->setContainerClass('form-group');
$pwd->setClass('form-control');
$form->addField($pwd);
2013-05-10 17:25:51 +02:00
$pwd = new b8\Form\Element\Submit();
$pwd->setValue(Lang::get('log_in'));
$pwd->setClass('btn-success');
$form->addField($pwd);
2013-05-10 17:25:51 +02:00
$tokenValue = $this->generateToken();
$_SESSION['login_token'] = $tokenValue;
$token = new b8\Form\Element\Hidden('token');
$token->setValue($tokenValue);
$form->addField($token);
$this->view->form = $form->render();
2013-10-08 08:50:42 +02:00
$this->view->failed = $isLoginFailure;
return $this->view->render();
}
2013-05-10 17:25:51 +02:00
/**
* Handles user logout.
*/
public function logout()
{
2016-07-21 19:02:11 +02:00
unset($_SESSION['php-censor-user']);
unset($_SESSION['php-censor-user-id']);
session_destroy();
$response = new b8\Http\Response\RedirectResponse();
2016-07-21 17:20:34 +02:00
$response->setHeader('Location', APP_URL);
return $response;
}
2014-05-08 22:38:32 +02:00
/**
* Allows the user to request a password reset email.
* @return string
*/
2014-05-08 22:38:32 +02:00
public function forgotPassword()
{
if ($this->request->getMethod() == 'POST') {
$email = $this->getParam('email', null);
$user = $this->userStore->getByEmail($email);
if (empty($user)) {
$this->view->error = Lang::get('reset_no_user_exists');
2014-05-08 22:38:32 +02:00
return $this->view->render();
}
$key = md5(date('Y-m-d') . $user->getHash());
2016-07-21 17:20:34 +02:00
$url = APP_URL;
2014-05-08 22:38:32 +02:00
$message = Lang::get('reset_email_body', $user->getName(), $url, $user->getId(), $key);
2014-05-08 22:38:32 +02:00
$email = new Email();
2014-05-08 22:43:06 +02:00
$email->setEmailTo($user->getEmail(), $user->getName());
$email->setSubject(Lang::get('reset_email_title', $user->getName()));
2014-05-08 22:38:32 +02:00
$email->setBody($message);
$email->send();
$this->view->emailed = true;
}
return $this->view->render();
}
/**
* Allows the user to change their password after a password reset email.
* @param $userId
* @param $key
* @return string
*/
2014-05-08 22:43:06 +02:00
public function resetPassword($userId, $key)
2014-05-08 22:38:32 +02:00
{
2014-05-08 22:43:06 +02:00
$user = $this->userStore->getById($userId);
2014-05-08 22:38:32 +02:00
$userKey = md5(date('Y-m-d') . $user->getHash());
if (empty($user) || $key != $userKey) {
$this->view->error = Lang::get('reset_invalid');
2014-05-08 22:38:32 +02:00
return $this->view->render();
}
if ($this->request->getMethod() == 'POST') {
$hash = password_hash($this->getParam('password'), PASSWORD_DEFAULT);
$user->setHash($hash);
2016-07-21 19:02:11 +02:00
$_SESSION['php-censor-user'] = $this->userStore->save($user);
$_SESSION['php-censor-user-id'] = $user->getId();
2014-05-08 22:38:32 +02:00
$response = new b8\Http\Response\RedirectResponse();
2016-07-21 17:20:34 +02:00
$response->setHeader('Location', APP_URL);
return $response;
2014-05-08 22:38:32 +02:00
}
2014-05-08 22:43:06 +02:00
$this->view->id = $userId;
2014-05-08 22:38:32 +02:00
$this->view->key = $key;
return $this->view->render();
}
/**
* Get the URL the user was trying to go to prior to being asked to log in.
* @return string
*/
protected function getLoginRedirect()
{
2016-07-21 17:20:34 +02:00
$rtn = APP_URL;
2016-07-21 19:02:11 +02:00
if (!empty($_SESSION['php-censor-login-redirect'])) {
$rtn .= $_SESSION['php-censor-login-redirect'];
$_SESSION['php-censor-login-redirect'] = null;
}
return $rtn;
}
/** Generate a random token.
*
* @return string
*/
protected function generateToken()
{
2015-03-10 21:29:10 +01:00
if (function_exists('openssl_random_pseudo_bytes')) {
return bin2hex(openssl_random_pseudo_bytes(16));
}
return sprintf("%04x", mt_rand(0, 0xFFFF))
. sprintf("%04x", mt_rand(0, 0xFFFF))
. sprintf("%04x", mt_rand(0, 0xFFFF))
. sprintf("%04x", mt_rand(0, 0xFFFF));
}
}