295 lines
10 KiB
PHP
295 lines
10 KiB
PHP
<?php
|
|
|
|
/** DomFramework
|
|
* @package domframework
|
|
* @author Dominique Fournier <dominique@fournier38.fr>
|
|
* @license BSD
|
|
*/
|
|
|
|
namespace Domframework;
|
|
|
|
/** User authentication against SQL database */
|
|
class Authsql extends Auth
|
|
{
|
|
/** The DSN to use to connect to SQL database */
|
|
public $dsn = null;
|
|
/** The username to connect to the database */
|
|
public $username = null;
|
|
/** The password to use to connecto to the database */
|
|
public $password = null;
|
|
/** The driver options for the PDO driver */
|
|
public $driver_options = null;
|
|
/** The table name to use */
|
|
public $table = null;
|
|
/** The tableprefix text to prepend to table name (Should finish by _)
|
|
Just allow chars ! */
|
|
public $tableprefix = "";
|
|
/** The password field name */
|
|
public $fieldPassword = "password";
|
|
/** The identifier field name (maybe email) */
|
|
public $fieldIdentifier = "email";
|
|
/** The field name containing the lastname of the user */
|
|
public $fieldLastname = null;
|
|
/** The field name containing the Firstname of the user */
|
|
public $fieldFirstname = null;
|
|
/** The information fields (in an array) */
|
|
public $fieldsInfo = array();
|
|
|
|
/** The DBLayer pointer */
|
|
private $db = null;
|
|
/** The details of the authenticated user */
|
|
private $details = null;
|
|
|
|
/** Establish a connection to a SQL server */
|
|
public function connect()
|
|
{
|
|
if (! function_exists("openssl_random_pseudo_bytes")) {
|
|
throw new \Exception(
|
|
dgettext(
|
|
"domframework",
|
|
"No PHP support for openssl_random_pseudo_bytes"
|
|
),
|
|
500
|
|
);
|
|
}
|
|
$this->db = new Dblayer(
|
|
$this->dsn,
|
|
$this->username,
|
|
$this->password,
|
|
$this->driver_options
|
|
);
|
|
if ($this->table === null) {
|
|
throw new \Exception(
|
|
dgettext("domframework", "No SQL table defined"),
|
|
500
|
|
);
|
|
}
|
|
if ($this->fieldIdentifier === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"No fieldIdentifier defined"
|
|
), 500);
|
|
}
|
|
if ($this->fieldPassword === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"No fieldPassword defined"
|
|
), 500);
|
|
}
|
|
if ($this->fieldLastname === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"No fieldLastname defined"
|
|
), 500);
|
|
}
|
|
if ($this->fieldFirstname === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"No fieldFirstname defined"
|
|
), 500);
|
|
}
|
|
$fields = array_merge(
|
|
array($this->fieldIdentifier, $this->fieldPassword,
|
|
$this->fieldLastname, $this->fieldFirstname),
|
|
$this->fieldsInfo
|
|
);
|
|
$fields = array_flip($fields);
|
|
foreach ($fields as $key => $val) {
|
|
$fields[$key] = array("varchar", "255");
|
|
}
|
|
$this->db->table = $this->table;
|
|
$this->db->fields = $fields;
|
|
$this->db->primary = $this->fieldIdentifier;
|
|
}
|
|
|
|
/** Try to authenticate the email/password of the user
|
|
@param string $email Email to authenticate
|
|
@param string $password Password to authenticate */
|
|
public function authentication($email, $password)
|
|
{
|
|
if ($this->db === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"The SQL database is not connected"
|
|
), 500);
|
|
}
|
|
$data = $this->db->read(
|
|
array(array($this->fieldIdentifier, $email)),
|
|
array_merge(
|
|
array($this->fieldIdentifier,
|
|
$this->fieldFirstname,
|
|
$this->fieldLastname,
|
|
$this->fieldPassword),
|
|
$this->fieldsInfo
|
|
)
|
|
);
|
|
if (count($data) === 0) {
|
|
throw new \Exception(sprintf(
|
|
dgettext(
|
|
"domframework",
|
|
"Unable to find the user : '%s'"
|
|
),
|
|
$email
|
|
), 401);
|
|
}
|
|
if (! isset($data[0][$this->fieldPassword])) {
|
|
throw new \Exception(
|
|
dgettext(
|
|
"domframework",
|
|
"Unable to get the user password from database"
|
|
),
|
|
500
|
|
);
|
|
}
|
|
$cryptedPassword = $data[0][$this->fieldPassword];
|
|
if (crypt($password, $cryptedPassword) !== $cryptedPassword) {
|
|
throw new \Exception(
|
|
sprintf(dgettext(
|
|
"domframework",
|
|
"Bad password for '%s'"
|
|
), $email),
|
|
401
|
|
);
|
|
}
|
|
// The password should never be stored by this function
|
|
unset($data[0][$this->fieldPassword]);
|
|
$content = $data[0];
|
|
$content["email"] = $data[0][$this->fieldIdentifier];
|
|
$content["lastname"] = $data[0][$this->fieldLastname];
|
|
$content["firstname"] = $data[0][$this->fieldFirstname];
|
|
$this->details = $content;
|
|
}
|
|
|
|
/** Return all the parameters recorded for the authenticate user */
|
|
public function getdetails()
|
|
{
|
|
return $this->details;
|
|
}
|
|
|
|
/** Method to change the password
|
|
@param string $oldpassword The old password (to check if the user have the
|
|
rights to change the password)
|
|
@param string $newpassword The new password to be recorded */
|
|
public function changepassword($oldpassword, $newpassword)
|
|
{
|
|
if ($this->db === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"The SQL database is not connected"
|
|
), 500);
|
|
}
|
|
if (
|
|
$this->details === null ||
|
|
! isset($this->details[$this->fieldIdentifier])
|
|
) {
|
|
throw new \Exception(
|
|
dgettext(
|
|
"domframework",
|
|
"Can't change the password if the user is not authenticated"
|
|
),
|
|
500
|
|
);
|
|
}
|
|
$data = $this->db->read(
|
|
array(array($this->fieldIdentifier,
|
|
$this->details[$this->fieldIdentifier])),
|
|
array($this->fieldIdentifier,
|
|
$this->fieldPassword)
|
|
);
|
|
$cryptedPassword = $data[0][$this->fieldPassword];
|
|
if (crypt($oldpassword, $cryptedPassword) !== $cryptedPassword) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"Bad old password provided"
|
|
), 401);
|
|
}
|
|
$cost = 11;
|
|
$salt = substr(base64_encode(openssl_random_pseudo_bytes(17)), 0, 22);
|
|
$salt = str_replace("+", ".", $salt);
|
|
$param = '$' . implode('$', array(
|
|
"2y", //select the most secure version of blowfish (>=PHP 5.3.7)
|
|
str_pad($cost, 2, "0", STR_PAD_LEFT), //add the cost in two digits
|
|
$salt //add the salt
|
|
));
|
|
//now do the actual hashing
|
|
$cryptpassword = crypt($newpassword, $param);
|
|
$rc = $this->db->update(
|
|
$this->details[$this->fieldIdentifier],
|
|
array($this->fieldPassword => $cryptpassword)
|
|
);
|
|
if ($rc !== 1) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"Can't change the password"
|
|
), 500);
|
|
}
|
|
}
|
|
|
|
/** Method to overwrite the password (without oldpassword check)
|
|
Must be reserved to the administrators. For the users, use changepassword
|
|
method
|
|
@param string $email the user identifier to select
|
|
@param string $newpassword The new password to be recorded */
|
|
public function overwritepassword($email, $newpassword)
|
|
{
|
|
if ($this->db === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"The SQL database is not connected"
|
|
), 500);
|
|
}
|
|
$data = $this->db->read(
|
|
array(array($this->fieldIdentifier, $email)),
|
|
array($this->fieldIdentifier,
|
|
$this->fieldPassword)
|
|
);
|
|
if (count($data) === 0) {
|
|
throw new \Exception(sprintf(
|
|
dgettext(
|
|
"domframework",
|
|
"Unable to find the user : '%s'"
|
|
),
|
|
$email
|
|
), 401);
|
|
}
|
|
$cost = 11;
|
|
$salt = substr(base64_encode(openssl_random_pseudo_bytes(17)), 0, 22);
|
|
$salt = str_replace("+", ".", $salt);
|
|
$param = '$' . implode('$', array(
|
|
"2y", //select the most secure version of blowfish (>=PHP 5.3.7)
|
|
str_pad($cost, 2, "0", STR_PAD_LEFT), //add the cost in two digits
|
|
$salt //add the salt
|
|
));
|
|
//now do the actual hashing
|
|
$cryptpassword = crypt($newpassword, $param);
|
|
$rc = $this->db->update(
|
|
$email,
|
|
array($this->fieldPassword => $cryptpassword)
|
|
);
|
|
if ($rc !== 1) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"Can't change the password"
|
|
), 500);
|
|
}
|
|
}
|
|
/** List all the users available in the database
|
|
Return firstname, lastname, mail, with mail is an array */
|
|
public function listusers()
|
|
{
|
|
if ($this->db === null) {
|
|
throw new \Exception(dgettext(
|
|
"domframework",
|
|
"The SQL database is not connected"
|
|
), 500);
|
|
}
|
|
$data = $this->db->read(null, array_merge(
|
|
array($this->fieldIdentifier,
|
|
$this->fieldFirstname,
|
|
$this->fieldLastname),
|
|
$this->fieldsInfo
|
|
));
|
|
return $data;
|
|
}
|
|
}
|