SimpleModelSite/class_user.php

426 lines
14 KiB
PHP

<?php
class User {
private $id = 0;
private $username = "";
private $password = "";
private $firstname = "";
private $lastname = "";
// createtime will be stored in the class using the native SQL datetime format
private $createtime = "";
// lastlogin will be stored in the class using the native SQL datetime format
private $lastlogin = "";
// lastbadlogin will be stored in the class using the native SQL datetime format
private $lastbadlogin = "";
private $badlogincount = 0;
// lastupdate will be stored in the class using the native SQL datetime format
private $lastupdate = "";
const COOKIENAME = SESSNAME . "_rememberme";
const ROLE_ADMIN = "admin";
const ROLE_USER = "user";
const ROLE_GUEST = "guest";
const ROLE_VALIDROLES = array(User::ROLE_GUEST, User::ROLE_ADMIN, User::ROLE_USER);
const GUEST = 1000601;
const USER = 1000602;
const ADMIN = 1000603;
const LOGININVALID = 1000604;
const LOGINLOCKED = 1000605;
public function getID() {
return intval($this->id);
}
public function getUsername($flag = 0) {
switch ($flag) {
case HTMLSAFE:
return htmlspecialchars($this->lastname);
break;
case HTMLFORMSAFE:
return htmlspecialchars($this->lastname, ENT_QUOTES);
break;
case CSVSAFE:
return str_replace('"', '""', $this->lastname);
break;
default:
return $this->username;
break;
}
}
public function getFirstName($flag = 0) {
switch ($flag) {
case HTMLSAFE:
return htmlspecialchars($this->firstname);
break;
case HTMLFORMSAFE:
return htmlspecialchars($this->firstname, ENT_QUOTES);
break;
case CSVSAFE:
return str_replace('"', '""', $this->firstname);
break;
default:
return $this->firstname;
break;
}
}
public function getLastName($flag = 0) {
switch ($flag) {
case HTMLSAFE:
return htmlspecialchars($this->lastname);
break;
case HTMLFORMSAFE:
return htmlspecialchars($this->lastname, ENT_QUOTES);
break;
case CSVSAFE:
return str_replace('"', '""', $this->lastname);
break;
default:
return $this->lastname;
break;
}
}
public function getFullName($flag = 0) {
$fullname = $this->firstname . " " . $this->lastname;
switch ($flag) {
case HTMLSAFE:
return htmlspecialchars($fullname);
break;
case HTMLFORMSAFE:
return htmlspecialchars($fullname, ENT_QUOTES);
break;
case CSVSAFE:
return str_replace('"', '""', $fullname);
break;
default:
return $fullname;
break;
}
}
public function getCreateTime($flag = 0) {
switch ($flag) {
case TIMESTAMP:
return strtotime($this->createtime);
break;
case PRETTY:
return date("F j Y H:i:s", strtotime($this->createtime));
break;
default:
return $this->createtime;
break;
}
}
public function getLastLogin($flag = 0) {
switch ($flag) {
case TIMESTAMP:
return strtotime($this->lastlogin);
break;
case PRETTY:
return (($this->lastlogin == "0000-00-00 00:00:00") || ($this->lastlogin == "")) ? "Never" : date("F j Y H:i:s", strtotime($this->lastlogin));
break;
default:
return $this->lastlogin;
break;
}
}
public function getLastBadLogin($flag = 0) {
switch ($flag) {
case TIMESTAMP:
return strtotime($this->lastbadlogin);
break;
case PRETTY:
return (($this->lastbadlogin == "0000-00-00 00:00:00") || ($this->lastbadlogin == "")) ? "Never" : date("F j Y H:i:s", strtotime($this->lastbadlogin));
break;
default:
return $this->lastbadlogin;
break;
}
}
public function getBadLoginCount() {
return intval($this->badlogincount);
}
public function getLastUpdate($flag = 0) {
switch ($flag) {
case TIMESTAMP:
return strtotime($this->lastupdate);
break;
case PRETTY:
return date("F j Y H:i:s", strtotime($this->lastupdate));
break;
default:
return $this->lastupdate;
break;
}
}
public function setID($id = null) {
if (is_null($id)) return false;
$id = abs(intval($id));
if ($id == 0) return false;
$this->id = $id;
return true;
}
public function setUsername($username = null) {
if (is_null($username) || ($username == "")) return false;
settype($username, "string");
$this->username = $username;
return true;
}
public function setPassword($password = null) {
if (is_null($password)) return false;
$this->password = password_hash($password, PASSWORD_DEFAULT);
return true;
}
public function setPasswordHash($hash = null) {
if (is_null($hash)) return false;
$this->password = $hash;
return true;
}
public function setFirstName($firstname = null) {
if (is_null($firstname) || ($firstname == "")) return false;
settype($firstname, "string");
$this->firstname = $firstname;
return true;
}
public function setLastName($lastname = null) {
if (is_null($lastname) || ($lastname == "")) return false;
settype($lastname, "string");
$this->lastname = $lastname;
return true;
}
public function setBadLoginCount($count = null) {
if (is_null($count)) return false;
$this->badlogincount = intval($count);
}
public function saveLastLogin() {
global $globaldbh;
$query = "UPDATE " . AppDB::TABLE_USERS . " SET lastlogin=:lastlogin WHERE id=:id";
$fields = array();
$fields[':id'] = $this->getID();
$fields[':lastlogin'] = (new DateTime("now", new DateTimeZone("UTC")))->format('Y-m-d H:i:s');
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
}
public static function getUserByUsername($username = null) {
global $globaldbh;
if (is_null($username)) return false;
$query = "SELECT id FROM " . AppDB::TABLE_USERS . " WHERE username=:username";
$fields = array();
$fields[':username'] = $username;
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
if ($row = $sth->fetch()) {
return new User($row['id']);
} else {
return false;
}
}
public function setCookie() {
global $globaldbh;
$query = "DELETE FROM " . AppDB::TABLE_COOKIES . " WHERE user_id=:user_id AND ipaddress=:ipaddress";
$fields = array();
$fields[':user_id'] = $this->getID();
$fields[':ipaddress'] = $_SERVER['REMOTE_ADDR'];
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
$hash = uniqid("", true) . uniqid("", true);
$query = "INSERT INTO " . AppDB::TABLE_COOKIES . " ";
if (DBTYPE == 'mysql') {
$query .= "VALUES(:hash, :user_id, :ipaddress, UTC_TIMESTAMP() + INTERVAL 30 DAY)";
} elseif (DBTYPE == 'sqlite') {
$query .= "VALUES(:hash, :user_id, :ipaddress, DATETIME('NOW','+30 DAY'))";
}
$fields[':hash'] = $hash;
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
setcookie(User::COOKIENAME, $hash, array('expires' => time() + (60 * 60 * 24 * 30), 'path' => "/", 'domain' => $_SERVER['SERVER_NAME'], 'samesite' => 'Lax'));
}
public function saveLastUpdate() {
global $globaldbh;
$query = "UPDATE " . AppDB::TABLE_USERS . " ";
if (DBTYPE == 'mysql') {
$query .= "SET lastupdate=UTC_TIMESTAMP() WHERE id=:id";
} elseif (DBTYPE == 'sqlite') {
$query .= "SET lastupdate=DATETIME('NOW') WHERE id=:id";
}
$fields = array(':id' => $this->getID());
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
}
public function incrementBadLogins() {
global $globaldbh;
$this->badlogincount++;
$query = "UPDATE " . AppDB::TABLE_USERS . " ";
if (DBTYPE == 'mysql') {
$query .= "SET badlogincount=:badlogincount, lastbadlogin=UTC_TIMESTAMP() WHERE id=:id";
} elseif (DBTYPE == 'sqlite') {
$query .= "SET badlogincount=:badlogincount, lastbadlogin=DATETIME('NOW') WHERE id=:id";
}
$fields = array();
$fields[':id'] = $this->getID();
$fields[':badlogincount'] = $this->getBadLoginCount();
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
}
public static function getUserFromLogin($username = null, $password = null) {
global $globaldbh;
$user = User::getUserByUsername($username);
if ($user === false) {
return User::LOGININVALID;
}
if (($user->getBadLoginCount() >= MAXBADLOGINS) && ((strtotime($user->getLastBadLogin()) + (BADLOGINEXPIRATION * 60)) > time())) {
return User::LOGINLOCKED;
}
$query = "SELECT id, password FROM " . AppDB::TABLE_USERS . " WHERE username=:username";
$fields = array(':username' => $username);
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
if ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
if (password_verify($password, $row['password'])) {
$user = new User($row['id']);
$user->setBadLoginCount(0);
$saved = $user->save();
return $user;
}
}
$user->incrementBadLogins();
return User::LOGININVALID;
}
public static function validateUserCookie($hash = null) {
global $globaldbh;
$query = "SELECT user_id FROM " . AppDB::TABLE_COOKIES . " WHERE hash=:hash AND ipaddress=:ipaddress ";
if (DBTYPE == 'mysql') {
$query .= "AND expiration >= UTC_TIMESTAMP()";
} elseif (DBTYPE == 'sqlite') {
$query .= "AND DATETIME(expiration) >= DATETIME('NOW')";
}
$fields = array();
$fields[':hash'] = $hash;
$fields[':ipaddress'] = $_SERVER['REMOTE_ADDR'];
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
if ($row = $sth->fetch()) {
$user = new User($row['user_id']);
return $user->getID();
} else {
return 0;
}
}
public function removeCookie() {
global $globaldbh;
if (!isset($_COOKIE[User::COOKIENAME])) return;
setcookie(User::COOKIENAME, "", time() - 3600, "/", $_SERVER['SERVER_NAME']);
$query = "DELETE FROM " . AppDB::TABLE_COOKIES . " WHERE user_id=:user_id AND ipaddress=:ipaddress";
$fields = array();
$fields[':user_id'] = $this->getID();
$fields[':ipaddress'] = $_SERVER['REMOTE_ADDR'];
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
}
public static function getList($search = null) {
global $globaldbh;
$fields = array();
if (is_null($search)) {
$query = "SELECT id FROM " . AppDB::TABLE_USERS . " ORDER BY firstname, lastname";
} else {
$query = "SELECT id FROM " . AppDB::TABLE_USERS . " WHERE (firstname LIKE :search) OR (lastname LIKE :search) OR (username LIKE :search) ORDER BY firstname, lastname";
$fields[':search'] = "%" . $search . "%";
}
$sth = $globaldbh->prepare($query);
$thelist = array();
if ($sth->execute($fields)) {
while ($row = $sth->fetch()) {
$thelist[] = new User($row['id']);
}
}
return $thelist;
}
public function isLoggedIn() {
if ( $this->getID() != 0 ) { return true; } else { return false; }
}
public function save() {
global $globaldbh;
if ($this->getFirstName() == "") return false;
if ($this->getLastName() == "") return false;
$fields = array();
if ($this->getID() == 0) {
$query = "INSERT INTO " . AppDB::TABLE_USERS . " ";
$query .= "(username, password, firstname, lastname, createtime, lastupdate) ";
$query .= "VALUES(:username, :password, :firstname, :lastname, :createtime, :lastupdate)";
$fields[':password'] = $this->password; // There is no "getter" for password since it should never read outside the class
$fields[':createtime'] = (new DateTime("now", new DateTimeZone("UTC")))->format('Y-m-d H:i:s');
} else {
$query = "UPDATE " . AppDB::TABLE_USERS . " SET username=:username, ";
if ($this->password != "") {
$query .= "password=:password, ";
$fields[':password'] = $this->password; // There is no "getter" for password since it should never read outside the class
}
$query .= "firstname=:firstname, lastname=:lastname, ";
$query .= "lastupdate=:lastupdate, badlogincount=:badlogincount WHERE id=:id";
$fields[':id'] = $this->getID();
$fields[':badlogincount'] = $this->getBadLoginCount();
}
$fields[':username'] = $this->getUsername();
$fields[':firstname'] = $this->getFirstName();
$fields[':lastname'] = $this->getLastName();
$fields[':lastupdate'] = (new DateTime("now", new DateTimeZone("UTC")))->format('Y-m-d H:i:s');
$sth = $globaldbh->prepare($query);
$saved = $sth->execute($fields);
return $saved;
}
function __construct($reqid = 0) {
global $globaldbh;
$reqid = intval($reqid);
$query = "SELECT id, username, firstname, lastname, createtime, lastlogin, " .
"lastbadlogin, badlogincount, lastupdate FROM " . AppDB::TABLE_USERS . " WHERE id=:id";
$fields = array();
$fields[':id'] = $reqid;
$sth = $globaldbh->prepare($query);
if ($sth->execute($fields)) {
if ($row = $sth->fetch()) {
$this->setID($row['id']);
$this->setUsername($row['username']);
$this->setFirstName($row['firstname']);
$this->setLastName($row['lastname']);
$this->createtime = $row['createtime'];
$this->lastlogin = $row['lastlogin'];
$this->lastbadlogin = $row['lastbadlogin'];
$this->setBadLoginCount($row['badlogincount']);
$this->lastupdate = $row['lastupdate'];
}
}
}
}
// vim: set ts=3:sw=3