Ask the current password before changing a user password

This commit is contained in:
Frédéric Guillot 2014-03-25 21:25:54 -04:00
parent 0d55f5aa35
commit 34711f5846
10 changed files with 231 additions and 36 deletions

View File

@ -156,9 +156,6 @@ textarea {
font-size: 99%;
}
select {
}
::-webkit-input-placeholder {
color: #bbb;
padding-top: 2px;
@ -183,6 +180,12 @@ textarea.form-error {
border: 2px solid #b94a48;
}
.form-required {
color: red;
padding-left: 5px;
font-weight: bold;
}
.form-errors {
color: #b94a48;
list-style-type: none;

View File

@ -4,9 +4,19 @@ namespace Controller;
require_once __DIR__.'/base.php';
/**
* User controller
*
* @package controller
* @author Frederic Guillot
*/
class User extends Base
{
// Display access forbidden page
/**
* Display access forbidden page
*
* @access public
*/
public function forbidden()
{
$this->response->html($this->template->layout('user_forbidden', array(
@ -15,14 +25,22 @@ class User extends Base
)));
}
// Logout and destroy session
/**
* Logout and destroy session
*
* @access public
*/
public function logout()
{
$this->session->close();
$this->response->redirect('?controller=user&action=login');
}
// Display the form login
/**
* Display the form login
*
* @access public
*/
public function login()
{
if (isset($_SESSION['user'])) $this->response->redirect('?controller=app');
@ -35,7 +53,11 @@ class User extends Base
)));
}
// Check credentials
/**
* Check credentials
*
* @access public
*/
public function check()
{
$values = $this->request->getValues();
@ -51,7 +73,11 @@ class User extends Base
)));
}
// List all users
/**
* List all users
*
* @access public
*/
public function index()
{
$users = $this->user->getAll();
@ -67,7 +93,11 @@ class User extends Base
)));
}
// Display a form to create a new user
/**
* Display a form to create a new user
*
* @access public
*/
public function create()
{
$this->response->html($this->template->layout('user_new', array(
@ -79,7 +109,11 @@ class User extends Base
)));
}
// Validate and save a new user
/**
* Validate and save a new user
*
* @access public
*/
public function save()
{
$values = $this->request->getValues();
@ -105,14 +139,18 @@ class User extends Base
)));
}
// Display a form to edit a user
/**
* Display a form to edit a user
*
* @access public
*/
public function edit()
{
$user = $this->user->getById($this->request->getIntegerParam('user_id'));
if (! $user) $this->notfound();
if (! $_SESSION['user']['is_admin'] && $_SESSION['user']['id'] != $user['id']) {
if ($this->acl->isRegularUser() && $this->acl->getUserId() != $user['id']) {
$this->forbidden();
}
@ -127,17 +165,21 @@ class User extends Base
)));
}
// Validate and update a user
/**
* Validate and update a user
*
* @access public
*/
public function update()
{
$values = $this->request->getValues();
if ($_SESSION['user']['is_admin'] == 1) {
if ($this->acl->isAdminUser()) {
$values += array('is_admin' => 0);
}
else {
if ($_SESSION['user']['id'] != $values['id']) {
if ($this->acl->getUserId() != $values['id']) {
$this->forbidden();
}
@ -168,7 +210,11 @@ class User extends Base
)));
}
// Confirmation dialog before to remove a user
/**
* Confirmation dialog before to remove a user
*
* @access public
*/
public function confirm()
{
$user = $this->user->getById($this->request->getIntegerParam('user_id'));
@ -182,7 +228,11 @@ class User extends Base
)));
}
// Remove a user
/**
* Remove a user
*
* @access public
*/
public function remove()
{
$user_id = $this->request->getIntegerParam('user_id');

View File

@ -18,6 +18,11 @@ function is_admin()
return $_SESSION['user']['is_admin'] == 1;
}
function get_username()
{
return $_SESSION['user']['username'];
}
function markdown($text)
{
require_once __DIR__.'/../vendor/Michelf/MarkdownExtra.inc.php';
@ -206,6 +211,7 @@ function form_textarea($name, $values = array(), array $errors = array(), array
$html .= implode(' ', $attributes).'>';
$html .= isset($values->$name) ? escape($values->$name) : isset($values[$name]) ? $values[$name] : '';
$html .= '</textarea>';
if (in_array('required', $attributes)) $html .= '<span class="form-required">*</span>';
$html .= error_list($errors, $name);
return $html;
@ -217,6 +223,7 @@ function form_input($type, $name, $values = array(), array $errors = array(), ar
$html = '<input type="'.$type.'" name="'.$name.'" id="form-'.$name.'" '.form_value($values, $name).' class="'.$class.'" ';
$html .= implode(' ', $attributes).'/>';
if (in_array('required', $attributes)) $html .= '<span class="form-required">*</span>';
$html .= error_list($errors, $name);
return $html;

View File

@ -264,4 +264,7 @@ return array(
'Do you really want to remove this comment?' => 'Voulez-vous vraiment supprimer ce commentaire ?',
'Only administrators or the creator of the comment can access to this page.' => 'Uniquement les administrateurs ou le créateur du commentaire peuvent accéder à cette page.',
'Details' => 'Détails',
'Current password for the user "%s"' => 'Mot de passe actuel pour l\'utilisateur « %s »',
'The current password is required' => 'Le mot de passe actuel est obligatoire',
'Wrong password' => 'Mauvais mot de passe',
);

View File

@ -267,4 +267,7 @@ return array(
// 'Do you really want to remove this comment?' => '',
// 'Only administrators or the creator of the comment can access to this page.' => '',
// 'Details' => '',
// 'Current password for the user "%s"' => '',
// 'The current password is required' => '',
// 'Wrong password' => '',
);

View File

@ -7,20 +7,51 @@ require_once __DIR__.'/base.php';
use \SimpleValidator\Validator;
use \SimpleValidator\Validators;
/**
* User model
*
* @package model
* @author Frederic Guillot
*/
class User extends Base
{
/**
* SQL table name
*
* @var string
*/
const TABLE = 'users';
/**
* Get a specific user by id
*
* @access public
* @param integer $user_id User id
* @return array
*/
public function getById($user_id)
{
return $this->db->table(self::TABLE)->eq('id', $user_id)->findOne();
}
/**
* Get a specific user by the username
*
* @access public
* @param string $username Username
* @return array
*/
public function getByUsername($username)
{
return $this->db->table(self::TABLE)->eq('username', $username)->findOne();
}
/**
* Get all users
*
* @access public
* @return array
*/
public function getAll()
{
return $this->db
@ -30,11 +61,24 @@ class User extends Base
->findAll();
}
/**
* List all users (key-value pairs with id/username)
*
* @access public
* @return array
*/
public function getList()
{
return $this->db->table(self::TABLE)->asc('username')->listing('id', 'username');
}
/**
* Add a new user in the database
*
* @access public
* @param array $values Form values
* @return boolean
*/
public function create(array $values)
{
if (isset($values['confirmation'])) unset($values['confirmation']);
@ -43,6 +87,13 @@ class User extends Base
return $this->db->table(self::TABLE)->save($values);
}
/**
* Modify a new user
*
* @access public
* @param array $values Form values
* @return array
*/
public function update(array $values)
{
if (! empty($values['password'])) {
@ -52,17 +103,25 @@ class User extends Base
unset($values['password']);
}
unset($values['confirmation']);
if (isset($values['confirmation'])) unset($values['confirmation']);
if (isset($values['current_password'])) unset($values['current_password']);
$this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->update($values);
if ($_SESSION['user']['id'] == $values['id']) {
$this->updateSession();
}
return true;
return $result;
}
/**
* Remove a specific user
*
* @access public
* @param integer $user_id User id
* @return boolean
*/
public function remove($user_id)
{
$this->db->startTransaction();
@ -76,17 +135,32 @@ class User extends Base
return true;
}
/**
* Update user session information
*
* @access public
* @param array $user User data
*/
public function updateSession(array $user = array())
{
if (empty($user)) {
$user = $this->getById($_SESSION['user']['id']);
}
if (isset($user['password'])) unset($user['password']);
if (isset($user['password'])) {
unset($user['password']);
}
$_SESSION['user'] = $user;
}
/**
* Validate user creation
*
* @access public
* @param array $values Form values
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
*/
public function validateCreation(array $values)
{
$v = new Validator($values, array(
@ -108,23 +182,28 @@ class User extends Base
);
}
/**
* Validate user modification
*
* @access public
* @param array $values Form values
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
*/
public function validateModification(array $values)
{
if (! empty($values['password'])) {
return $this->validateCreation($values);
return $this->validatePasswordModification($values);
}
else {
$v = new Validator($values, array(
new Validators\Required('id', t('The user id is required')),
new Validators\Required('username', t('The username is required')),
new Validators\MaxLength('username', t('The maximum length is %d characters', 50), 50),
new Validators\AlphaNumeric('username', t('The username must be alphanumeric')),
new Validators\Unique('username', t('The username must be unique'), $this->db->getConnection(), self::TABLE, 'id'),
new Validators\Integer('default_project_id', t('This value must be an integer')),
new Validators\Integer('is_admin', t('This value must be an integer')),
));
}
$v = new Validator($values, array(
new Validators\Required('id', t('The user id is required')),
new Validators\Required('username', t('The username is required')),
new Validators\MaxLength('username', t('The maximum length is %d characters', 50), 50),
new Validators\AlphaNumeric('username', t('The username must be alphanumeric')),
new Validators\Unique('username', t('The username must be unique'), $this->db->getConnection(), self::TABLE, 'id'),
new Validators\Integer('default_project_id', t('This value must be an integer')),
new Validators\Integer('is_admin', t('This value must be an integer')),
));
return array(
$v->execute(),
@ -132,6 +211,53 @@ class User extends Base
);
}
/**
* Validate password modification
*
* @access public
* @param array $values Form values
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
*/
public function validatePasswordModification(array $values)
{
$v = new Validator($values, array(
new Validators\Required('id', t('The user id is required')),
new Validators\Required('username', t('The username is required')),
new Validators\MaxLength('username', t('The maximum length is %d characters', 50), 50),
new Validators\AlphaNumeric('username', t('The username must be alphanumeric')),
new Validators\Unique('username', t('The username must be unique'), $this->db->getConnection(), self::TABLE, 'id'),
new Validators\Required('current_password', t('The current password is required')),
new Validators\Required('password', t('The password is required')),
new Validators\MinLength('password', t('The minimum length is %d characters', 6), 6),
new Validators\Required('confirmation', t('The confirmation is required')),
new Validators\Equals('password', 'confirmation', t('Passwords doesn\'t matches')),
new Validators\Integer('default_project_id', t('This value must be an integer')),
new Validators\Integer('is_admin', t('This value must be an integer')),
));
if ($v->execute()) {
// Check password
$user = $this->getById($_SESSION['user']['id']);
if ($user !== false && \password_verify($values['current_password'], $user['password'])) {
return array(true, array());
}
else {
return array(false, array('current_password' => array(t('Wrong password'))));
}
}
return array(false, $v->getErrors());
}
/**
* Validate user login
*
* @access public
* @param array $values Form values
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
*/
public function validateLogin(array $values)
{
$v = new Validator($values, array(

View File

@ -9,7 +9,7 @@
<form method="post" action="?controller=project&amp;action=save" autocomplete="off">
<?= Helper\form_label(t('Name'), 'name') ?>
<?= Helper\form_text('name', $values, $errors, array('autofocus required')) ?>
<?= Helper\form_text('name', $values, $errors, array('autofocus', 'required')) ?>
<div class="form-actions">
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>

View File

@ -6,7 +6,7 @@
<form method="post" action="?controller=task&amp;action=save" autocomplete="off">
<?= Helper\form_label(t('Title'), 'title') ?>
<?= Helper\form_text('title', $values, $errors, array('autofocus required')) ?><br/>
<?= Helper\form_text('title', $values, $errors, array('autofocus', 'required')) ?><br/>
<?= Helper\form_hidden('project_id', $values) ?>

View File

@ -13,6 +13,9 @@
<?= Helper\form_label(t('Username'), 'username') ?>
<?= Helper\form_text('username', $values, $errors, array('required')) ?><br/>
<?= Helper\form_label(t('Current password for the user "%s"', Helper\get_username()), 'current_password') ?>
<?= Helper\form_password('current_password', $values, $errors) ?><br/>
<?= Helper\form_label(t('Password'), 'password') ?>
<?= Helper\form_password('password', $values, $errors) ?><br/>

View File

@ -9,7 +9,7 @@
<form method="post" action="?controller=user&amp;action=save" autocomplete="off">
<?= Helper\form_label(t('Username'), 'username') ?>
<?= Helper\form_text('username', $values, $errors, array('autofocus required')) ?><br/>
<?= Helper\form_text('username', $values, $errors, array('autofocus', 'required')) ?><br/>
<?= Helper\form_label(t('Password'), 'password') ?>
<?= Helper\form_password('password', $values, $errors, array('required')) ?><br/>