pics/models/Authentication.php

167 lines
3.8 KiB
PHP

<?php
/*****************************************************************************
* Authentication.php
* Contains key class Authentication.
*
* Kabuki CMS (C) 2013-2015, Aaron van Geffen
*****************************************************************************/
/**
* Authentication class, containing various static functions used for account verification
* and session management.
*/
class Authentication
{
const DEFAULT_RESET_TIMEOUT = 30;
/**
* Checks a password for a given username against the database.
*/
public static function checkPassword($emailaddress, $password)
{
// Retrieve password hash for user matching the provided emailaddress.
$password_hash = Registry::get('db')->queryValue('
SELECT password_hash
FROM users
WHERE emailaddress = {string:emailaddress}',
[
'emailaddress' => $emailaddress,
]);
// If there's no hash, the user likely does not exist.
if (!$password_hash)
return false;
return password_verify($password, $password_hash);
}
public static function checkResetKey($id_user, $reset_key)
{
$key = Registry::get('db')->queryValue('
SELECT reset_key
FROM users
WHERE id_user = {int:id}',
[
'id' => $id_user,
]);
return $key == $reset_key;
}
/**
* Computes a password hash.
*/
public static function computeHash($password)
{
$hash = password_hash($password, PASSWORD_DEFAULT);
if (!$hash)
throw new Exception('Hash creation failed!');
return $hash;
}
public static function consumeResetKey($id_user)
{
return Registry::get('db')->query('
UPDATE users
SET reset_key = NULL,
reset_blocked_until = NULL
WHERE id_user = {int:id_user}',
['id_user' => $id_user]);
}
public static function getResetTimeOut($id_user)
{
$resetTime = Registry::get('db')->queryValue('
SELECT reset_blocked_until
FROM users
WHERE id_user = {int:id_user}',
['id_user' => $id_user]);
return max(0, $resetTime - time());
}
/**
* Verifies whether the user is currently logged in.
*/
public static function isLoggedIn()
{
if (!isset($_SESSION['user_id']))
return false;
try
{
$exists = Member::fromId($_SESSION['user_id']);
return true;
}
catch (NotFoundException $e)
{
return false;
}
}
/**
* Generates a new activation key.
*/
public static function newActivationKey()
{
$alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$string = '';
for ($i = 0; $i < 16; $i++)
$string .= $alpha[mt_rand(0, strlen($alpha) - 1)];
return $string;
}
public static function setResetKey($id_user)
{
return Registry::get('db')->query('
UPDATE users
SET reset_key = {string:key},
reset_blocked_until = UNIX_TIMESTAMP() + ' . static::DEFAULT_RESET_TIMEOUT . '
WHERE id_user = {int:id}',
[
'id' => $id_user,
'key' => self::newActivationKey(),
]);
}
/**
* Resets a password for a certain user.
*/
public static function updatePassword($id_user, $hash)
{
return Registry::get('db')->query('
UPDATE users
SET
password_hash = {string:hash},
reset_key = {string:blank}
WHERE id_user = {int:id_user}',
[
'id_user' => $id_user,
'hash' => $hash,
'blank' => '',
]);
}
public static function updateResetTimeOut($id_user)
{
$currentResetTimeOut = static::getResetTimeOut($id_user);
// New timeout: between 30 seconds, double the current timeout, and a full day
$newResetTimeOut = min(max(static::DEFAULT_RESET_TIMEOUT, $currentResetTimeOut * 2), 60 * 60 * 24);
$success = Registry::get('db')->query('
UPDATE users
SET reset_blocked_until = {int:new_time_out}
WHERE id_user = {int:id_user}',
[
'id_user' => $id_user,
'new_time_out' => time() + $newResetTimeOut,
]);
if (!$success)
throw new UnexpectedValueException('Could not set password reset timeout!');
return $newResetTimeOut;
}
}