From: Vincent Zanotti Date: Sun, 15 Jun 2008 14:37:42 +0000 (+0200) Subject: Creates a User class to handle user identification. X-Git-Tag: xorg/0.10.0~86^2~90 X-Git-Url: http://git.polytechnique.org/?a=commitdiff_plain;h=9f8ebb9fefbe781c11d663382e805273178447e8;p=platal.git Creates a User class to handle user identification. Signed-off-by: Vincent Zanotti --- diff --git a/classes/coreuser.php b/classes/coreuser.php new file mode 100644 index 0000000..742b3a1 --- /dev/null +++ b/classes/coreuser.php @@ -0,0 +1,269 @@ +results = $results; + parent::__construct(); + } +} + +// Represents an user of the system, with a special focus on its identification +// (hruid, forlife, and bestalias). +// Note: each implementation of platal-core MUST create a subclass 'User' of +// this abstract CoreUser class. +abstract class CoreUser +{ + // User's data storage. By convention, null means the information hasn't + // been fetched yet, and false means the information is not available. + + // Main (unique) identifiers. + private $user_id = null; + private $hruid = null; + + // User's emails (bestalias should be preferred when sending emails). + private $forlife = null; + private $bestalias = null; + + + // Constructs the object from an identifier (hruid/uid/email alias/email + // redirection) and an optionnal array of known user properties. + public function __construct($login, $values = array()) + { + list($this->user_id, $this->hruid) = $this->getLogin($login); + $this->fillFromArray($values); + } + + + // Properties accessors. + public function id() + { + return $this->user_id; + } + + public function login() + { + return $this->hruid; + } + + public function bestEmail() + { + if (!isset($this->bestalias)) { + global $globals; + $res = XDB::query("SELECT CONCAT(alias, '@{$globals->mail->domain}') + FROM aliases + WHERE FIND_IN_SET('bestalias', flags) + AND id = {?}", $this->user_id); + $this->bestalias = $res->numRows() ? $res->fetchOneCell() : false; + } + return $this->bestalias; + } + + public function forlifeEmail() + { + if (!isset($this->forlife)) { + global $globals; + $res = XDB::query("SELECT CONCAT(alias, '@{$globals->mail->domain}') + FROM aliases + WHERE type = 'a_vie' AND id = {?}", $this->user_id); + $this->forlife = $res->numRows() ? $res->fetchOneCell() : false; + } + return $this->forlife; + } + + + // Determines if the @p id is a valid identifier; if so, returns the user_id + // and the hruid. Otherwise raises UserNotFoundException. + private function getLogin($login) + { + global $globals; + + // If $data is an integer, fetches directly the result. + if (is_numeric($login)) { + $res = XDB::query("SELECT user_id, hruid FROM auth_user_md5 WHERE user_id = {?}", $login); + if ($res->numRows()) { + return $res->fetchOneRow(); + } + + throw new UserNotFoundException(); + } + + // Checks whether $login is a valid hruid or not. + $res = XDB::query("SELECT user_id, hruid FROM auth_user_md5 WHERE hruid = {?}", $login); + if ($res->numRows()) { + return $res->fetchOneRow(); + } + + // From now, $login can only by an email alias, or an email redirection. + // If it doesn't look like a valid address, appends the plat/al's main domain. + $login = trim(strtolower($login)); + if (strstr($login, '@') === false) { + $login = $login . '@' . $globals->mail->domain; + } + + // Checks if $login is a valid alias on the main domains. + list($mbox, $fqdn) = explode('@', $login); + if ($fqdn == $globals->mail->domain || $fqdn == $globals->mail->domain2) { + $res = XDB::query("SELECT u.user_id, u.hruid + FROM auth_user_md5 AS u + INNER JOIN aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie')) + WHERE a.alias = {?}", $mbox); + if ($res->numRows()) { + return $res->fetchOneRow(); + } + + if (preg_match('/^(.*)\.([0-9]{4})$/u', $mbox, $matches)) { + $res = XDB::query("SELECT u.user_id, u.hruid + FROM auth_user_md5 AS u + INNER JOIN aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie')) + WHERE a.alias = {?} AND u.promo = {?}", $matches[1], $matches[2]); + if ($res->numRows() == 1) { + return $res->fetchOneRow(); + } + } + + throw new UserNotFoundException(); + } + + // Looks for $login as an email alias from the dedicated alias domain. + if ($fqdn == $globals->mail->alias_dom || $fqdn == $globals->mail->alias_dom2) { + $res = XDB::query("SELECT redirect + FROM virtual_redirect + INNER JOIN virtual USING(vid) + WHERE alias = {?}", $mbox . '@' . $globals->mail->alias_dom); + if ($redir = $res->fetchOneCell()) { + // We now have a valid alias, which has to be translated to an hruid. + list($alias, $alias_fqdn) = explode('@', $redir); + $res = XDB::query("SELECT u.user_id, u.hruid + FROM auth_user_md5 AS u + LEFT JOIN aliases AS a ON (a.id = u.user_id AND a.type IN ('alias', 'a_vie')) + WHERE a.alias = {?}", $alias); + if ($res->numRows()) { + return $res->fetchOneRow(); + } + } + + throw new UserNotFoundException(); + } + + // Otherwise, we do suppose $login is an email redirection. + $res = XDB::query("SELECT u.user_id, u.hruid + FROM auth_user_md5 AS u + LEFT JOIN emails AS e ON (e.uid = u.user_id) + WHERE e.email = {?}", $login); + if ($res->numRows() == 1) { + return $res->fetchOneRow(); + } + + throw new UserNotFoundException($res->fetchColumn(1)); + } + + // Fills the object from associative arrays containing our data. + // The use case is for arrays got directly from anoter SQL request. + private function fillFromArray(array $values) + { + foreach ($values as $key => $value) { + if (property_exists($this, $key) && !isset($this->$key)) { + $this->$key = $value; + } + } + } + + + // Returns a valid User object built from the @p id and optionnal @p values, + // or returns false and calls the callback if the @p id is not valid. + public static function get($login, $callback = false) + { + return User::getWithValues($login, array(), $callback); + } + + public static function getWithValues($login, $values, $callback = false) + { + if (!$callback) { + $callback = array(__CLASS__, '_default_user_callback'); + } + + try { + return new User($login, $values); + } catch (UserNotFoundException $e) { + return call_user_func($callback, $login, $e->results); + } + } + + // Alias on get() with the silent callback. + public static function getSilent($login) + { + return User::getWithValues($login, array(), array(__CLASS__, '_silent_user_callback')); + } + + // Returns the forlife emails for @p members. If @p strict mode is enabled, + // it returns the list of validated forlife emails. If strict mode is not, + // it also returns unvalidated values (but still call the callback for them). + public static function getBulkForlifeEmails($logins, $strict = true, $callback = false) + { + if (!is_array($logins)) { + if (strlen(trim($logins)) == 0) { + return null; + } + $logins = explode(' ', $logins); + } + + if ($logins) { + $list = array(); + foreach ($logins as $i => $login) { + if (($user = User::get($login, $callback))) { + $list[$i] = $user->forlifeEmail(); + } else if(!$strict) { + $list[$i] = $login; + } + } + return $list; + } + return null; + } + + // Silent callback for the user lookup -- does nothing. + public static function _silent_user_callback($login, $results) + { + return; + } + + // Default callback for user lookup -- displays an error message w.r.t. the + // number of matching users found. + public static function _default_user_callback($login, $results) + { + global $page; + + $result_count = count($results); + if ($result_count == 0 || !S::has_perms()) { + $page->trigError("Il n'y a pas d'utilisateur avec l'identifiant : $login"); + } else { + $page->trigError("Il y a $result_count utilisateurs avec cet identifiant : " . join(', ', $results)); + } + } +} + +// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: +?> diff --git a/classes/user.php b/classes/user.php new file mode 100644 index 0000000..512eeca --- /dev/null +++ b/classes/user.php @@ -0,0 +1,27 @@ +