* @license BSD */ namespace Domframework; /** Store the users in SQL database. Manage the creation of the users, * modification, delete, password management */ class Userssql extends Users { /** The database connector */ private $dsn; /** The user needed to connect to database */ private $username; /** The password needed to connect to database */ private $password; /** The optional drivers need by the database */ private $driver_options; /** The db connector */ private $db; /** The table to store the information */ public $table = "authusers"; /** The tableprefix text to prepend to table name (Should finish by _) Just allow chars ! */ public $tableprefix = ""; /** The email field in the database */ public $fieldEmail = "email"; /** The firstname field in the database */ public $fieldFirstname = "firstname"; /** The lastname field in the database */ public $fieldLastname = "lastname"; /** The password field in the database */ public $fieldPassword = "password"; /** The lastchange field in the database */ public $fieldLastchange = "lastchange"; /** The constructor. Save the parameters to connect to the database * @param string $dsn The DSN to connect * @param string|null $username The username to connect * @param string|null $password The password to connect * @param array|null $driver_options The optional drivers parameters */ public function __construct( $dsn, $username = null, $password = null, $driver_options = null ) { $this->dsn = $dsn; $this->username = $username; $this->password = $password; $this->driver_options = $driver_options; } /** Connect to the storage */ public function connect() { if ($this->table === null) { throw new \Exception( dgettext("domframework", "No SQL table defined"), 500 ); } if ($this->fieldEmail === 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); } if ($this->fieldLastchange === null) { throw new \Exception(dgettext( "domframework", "No fieldLastchange defined" ), 500); } $this->db = new Dblayer( $this->dsn, $this->username, $this->password, $this->driver_options ); $this->db->table = $this->table; $this->db->fields = array( $this->fieldEmail => array("varchar", "255", "not null"), $this->fieldFirstname => array("varchar", "255", "not null"), $this->fieldLastname => array("varchar", "255"), $this->fieldPassword => array("varchar", "255"), $this->fieldLastchange => array("datetime")); $this->db->primary = $this->fieldEmail; $this->db->unique = array($this->fieldEmail); $this->db->tableprefix = $this->tableprefix; } /** Initialise the storage Create the structure of data needed to the class */ public function initStorage() { if ($this->db === null) { $this->connect(); } return $this->db->createTable(); } /** Create a new user * If the password is not provided, create a default passwd (can be disable * password) * @param string $email The email to add * @param string $firstname The firstname to add * @param string $lastname The lastname to add * @param string|null $password The password of the user */ public function adduser($email, $firstname, $lastname, $password = null) { if ($this->db === null) { $this->connect(); } $this->checkEmail($email); $this->checkFirstname($firstname); $this->checkLastname($lastname); if ($password !== null) { $this->checkPassword($password); $password = $this->cryptPasswd($password); } return $this->db->insert(array($this->fieldEmail => $email, $this->fieldFirstname => $firstname, $this->fieldLastname => $lastname, $this->fieldPassword => $password)); } /** Delete a user * @param string $email The email to remove */ public function deluser($email) { if ($this->db === null) { $this->connect(); } $this->checkEmail($email); return $this->db->delete($email); } /** Update a user * @param string $oldemail The old email to modify * @param string $newemail The new email to save * @param string $firstname The firstname of the user * @param string $lastname The lastname of the user */ public function updateuser($oldemail, $newemail, $firstname, $lastname) { if ($this->db === null) { $this->connect(); } $this->checkEmail($oldemail); $this->checkEmail($newemail); $this->checkFirstname($firstname); $this->checkLastname($lastname); return $this->db->update( $oldemail, array($this->fieldEmail => $newemail, $this->fieldFirstname => $firstname, $this->fieldLastname => $lastname) ); } /** List the users */ public function listusers() { if ($this->db === null) { $this->connect(); } return $this->db->read(null, array($this->fieldEmail, $this->fieldFirstname, $this->fieldLastname)); } /** Change password @param string $email the user email 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($email, $oldpassword, $newpassword) { if ($this->db === null) { $this->connect(); } $this->checkEmail($email); $this->checkPassword($oldpassword); $this->checkPassword($newpassword); if ($this->checkValidPassword($email, $oldpassword) !== true) { throw new \Exception(dgettext( "domframework", "Bad old password provided" ), 401); } $cryptedPassword = $this->cryptPasswd($newpassword); return $this->db->update( $email, array($this->fieldPassword => $cryptedPassword, $this->fieldLastchange => date("Y-m-d H:i:s", time())) ); } /** Overwrite password (without oldpassword check) Must be reserved to the administrators. For the users, use changepassword method @param string $email the user email to change the password @param string $newpassword The new password to be recorded */ public function overwritepassword($email, $newpassword) { if ($this->db === null) { $this->connect(); } $this->checkEmail($email); $this->checkPassword($newpassword); $data = $this->db->read( array(array($this->fieldEmail, $email)), array($this->fieldPassword) ); if (count($data) === 0) { throw new \Exception(dgettext( "domframework", "No information found for this email" ), 404); } $cryptedPassword = $this->cryptPasswd($newpassword); return $this->db->update( $email, array($this->fieldPassword => $cryptedPassword, $this->fieldLastchange => date("Y-m-d H:i:s", time())) ); } /** Check if the provided password is correctely associated to the email user * @param string $email The email to authenticate * @param string $password The user password (not crypted !) */ public function checkValidPassword($email, $password) { if ($this->db === null) { $this->connect(); } $this->checkEmail($email); $this->checkPassword($password); $data = $this->db->read( array(array($this->fieldEmail, $email)), array($this->fieldPassword) ); if (count($data) === 0) { throw new \Exception(dgettext( "domframework", "No information found for this email" ), 404); } if (! isset($data[0][$this->fieldPassword])) { throw new \Exception(dgettext( "domframework", "No password available for this email" ), 404); } $cryptedPassword = $data[0][$this->fieldPassword]; if (crypt($password, $cryptedPassword) !== $cryptedPassword) { return false; } return true; } }