fields['users'] = array( "guid", "auth", "salt", "alias", "email", "emailVer", "admin", "reg", "emailConf", ); parent::__construct($guid); $this->expectType("user"); } /* * Get the GUID of a user object from a given username, or NULL if * the username is not in use. Therefore, this function can be * used to test the existence of a user with the given username. */ public static function getGuidByUname(string $uname) : ?string { $uname = database::esc($uname); $query = "SELECT guid FROM objects WHERE objtype = 'user' AND name = '" . $uname . "'"; $res = database::query($query); if (count($res) == 0) return NULL; return $res[0]['guid']; } /* * Get a user object from a given username, or NULL if the username * is not in use. This function can be used to test the existence * of a user with the given username. */ public static function getByUname(string $uname) : ?user { if (($guid = self::getGuidByUname($uname))) return new user($guid); return NULL; } /* * Get an array of all users, sorted by username */ public static function getAll_ordByUname() : array { $query = "SELECT guid FROM objects WHERE objtype = 'user' ORDER BY name"; $res = database::query($query); $users = array(); foreach ($res as $u) $users[] = new user($u['guid']); return $users; } /* * Get an array of all users, sorted by admin (descending, admins * first), then by username. */ public static function getAll_ordByAdminByUname() : array { $query = "SELECT o.guid FROM objects o JOIN users u ON o.guid = u.guid " . "WHERE o.objtype = 'user' ORDER BY u.admin DESC, o.name"; $res = database::query($query); $users = array(); foreach ($res as $u) $users[] = new user($u['guid']); return $users; } /* * Get an array of all admins, sorted by username */ public static function getAllAdmin_ordByUname() : array { $query = "SELECT o.guid FROM objects o JOIN users u ON o.guid = u.guid " . "WHERE o.objtype = 'user' AND u.admin = 1 ORDER BY o.name"; $res = database::query($query); $users = array(); foreach ($res as $u) $users[] = new user($u['guid']); return $users; } /* * Get the currently logged in user, or NULL if logged out. This * function will throw if unable to aquire a PHP session. This * function will also forcibly log the current user out if it * detects any changes in the user-agent or remote IP address. */ public static function getCurrent() : ?user { if ((session_status() != PHP_SESSION_ACTIVE) && !session_start()) throw new Exception("Unable to aquire a PHP session"); if (!isset($_SESSION['userguid'])) return NULL; /* detect session hijacking */ if (($_SESSION['useragent'] != $_SERVER['HTTP_USER_AGENT']) || ($_SESSION['userip'] != $_SERVER['REMOTE_ADDR'])) { self::setCurrent(); location("/"); return NULL; } try { return new user($_SESSION['userguid']); } catch (Exception $e) { /* invalid user */ self::setCurrent(); location("/"); return NULL; } } /* * Set the currently logged in user. Using NULL will logout any * current user. This function will throw if unable to aquire a * PHP session. This function will also cache the user-agent and * remote IP address of the current request to help validate future * requests made under the same session. */ public static function setCurrent(?user $user = NULL) : void { if ((session_status() != PHP_SESSION_ACTIVE) && !session_start()) throw new Exception("Unable to aquire a PHP session"); unset($_SESSION['userguid']); unset($_SESSION['useragent']); unset($_SESSION['userip']); if ($user) { $_SESSION['userguid'] = $user->guid; $_SESSION['useragent'] = $_SERVER['HTTP_USER_AGENT']; $_SESSION['userip'] = $_SERVER['REMOTE_ADDR']; } } /* * Initialize a new user object with the given username and plain * text password. This function returns NULL if $uname is already * being used. */ public static function initNew(string $uname, string $passwd) : ?user { if (self::getByUname($uname)) return NULL; $user = new user(); /* if there exist no users already, make this new one an admin */ if (count(self::getAll_ordByUname()) == 0) $user->admin = 1; $user->name = $uname; $user->objtype = "user"; $user->setPasswd($passwd); $user->setEmail(""); $user->reg = 1; $user->saveObj(); return $user; } /* * Get the salted and hashed form of a password */ private static function getAuth(string $passwd, string $salt) : string { return hash("sha256", $passwd . $salt); } /* * Validate the given plain-text password for this user. Returns true if * correct, false otherwise. */ public function validatePasswd(string $passwd) : bool { $auth = self::getAuth($passwd, $this->salt); return $auth == $this->auth; } /* * Update the auth and salt for this user, given a new plain-text * password. */ public function setPasswd(string $passwd) : void { $this->salt = self::getBlob(); $this->auth = self::getAuth($passwd, $this->salt); $this->saveObj(); } /* * Validate the email confirmation code for this user. Returns true if * correct, false otherwise. On success, $this->emailConf is also set * to 1 */ public function verifyEmail(string $ver) : bool { if ($ver != $this->emailVer) return false; $this->emailConf = 1; $this->saveObj(); return true; } /* * Update the email address for this user. This function will automatically * reset the emailConf flag and confirmation code for this user as well. */ public function setEmail(string $email) : void { $this->email = $email; $this->emailVer = substr(self::getBlob(), 0, 8); $this->emailConf = 0; $this->saveObj(); } /* * Get all groups this user owns or is a member of. This isn't necessarily * all groups this user has access permissions for. Results are sorted by * ownership, then by name. */ public function getGroups_ordByOwnByName() : array { $groups = array(); /* owner */ $query = "SELECT guid FROM objects WHERE objtype = 'group' AND owner = '" . database::esc($this->guid) . "' " . "ORDER BY name"; $res = database::query($query); foreach ($res as $g) $groups[] = new group($g['guid']); /* member */ $query = "SELECT o.guid FROM objects o JOIN members m ON o.guid = m.guid WHERE o.objtype = 'group' AND " . "m.member = '" . database::esc($this->guid) . "' ORDER BY o.name"; $res = database::query($query); foreach ($res as $g) $groups[] = new group($g['guid']); return $groups; } /* * Send an email message to this user using stored configuration * parameters. If config is not established, delivery is not * attempted. Return status. */ public function sendEmail(string $subj, string $mesg, ?string $attachPath = NULL, ?string $attachName = NULL, bool $ignoreEmailConf = false) : bool { if (settings::smtpServer() == "") return false; if (!$ignoreEmailConf && !$this->emailConf) return true; if ($this->email == "") return true; $mail = new PHPMailer(); $mail->isSMTP(); $mail->SMTPAuth = true; $mail->Host = settings::smtpServer(); $mail->Port = settings::smtpPort(); $mail->Username = settings::smtpUname(); $mail->Password = settings::smtpPasswd(); $mail->SMTPSecure = settings::smtpSecurity(); $mail->setFrom(settings::smtpEmailAddress(), settings::smtpFrom()); $mail->addAddress($this->email, $this->getDisplayName()); $mail->Subject = $subj; $mail->Body = $mesg; if ($attachPath && $attachName) $mail->addAttachment($attachPath, $attachName); return $mail->send(); } } ?>