<?php
class User
{
private static $user = false;
private static $organization = NULL;
private static $isShib = false;
private static $isInDb = false;
private static $isAnonymous = false;
public static function isLoggedIn()
{
return self::$user !== false;
}
public static function isShibbolethAuth()
{
return self::$isShib;
}
public static function isInDatabase()
{
return self::$isInDb;
}
public static function isLocalOnly()
{
return self::$user !== false && self::$isShib === false;
}
public static function isAnonymous()
{
return self::$isAnonymous;
}
public static function getData()
{
return self::$user;
}
public static function getId()
{
if (!isset(self::$user['userid']))
return false;
return (int)self::$user['userid'];
}
public static function getMail()
{
if (!isset(self::$user['email']))
return false;
return self::$user['email'];
}
public static function getName()
{
if (!self::isLoggedIn())
return false;
return self::$user['firstname'] . ' ' . self::$user['lastname'];
}
public static function getLastName()
{
if (!self::isLoggedIn())
return false;
return self::$user['lastname'];
}
public static function hasFullName()
{
return self::$user !== false && !empty(self::$user['firstname']) && !empty(self::$user['lastname']);
}
public static function isTutor()
{
return isset(self::$user['role']) && self::$user['role'] === 'tutor';
}
public static function getOrganizationId()
{
$org = self::getOrganization();
if (!isset($org['organizationid']))
return false;
return $org['organizationid'];
}
public static function getOrganizationName()
{
$org = self::getOrganization();
if (!isset($org['name']))
return false;
return $org['name'];
}
public static function getRemoteOrganizationId()
{
if (empty(self::$user['organization']))
return false;
return self::$user['organization'];
}
public static function getOrganization()
{
if (!self::isLoggedIn())
return false;
if (is_null(self::$organization)) {
self::$organization = Database::queryFirst('SELECT organizationid, name FROM satellite_suffix '
. ' INNER JOIN satellite USING (organizationid) '
. ' WHERE suffix = :org LIMIT 1',
array('org' => self::$user['organization']));
}
return self::$organization;
}
public static function load()
{
if (self::isLoggedIn())
return true;
$hasSession = Session::load();
if (empty($_SERVER['persistent-id'])) {
if (Session::getUid() === false)
return false;
// Try user from local DB
self::$user = Database::queryFirst('SELECT userid, shibid, login, organizationid AS organization, firstname, lastname, email FROM user WHERE userid = :uid LIMIT 1', array('uid' => Session::getUid()));
self::$isInDb = self::$user !== false;
return self::$isInDb;
}
// Try bwIDM etc.
if (!$hasSession) {
Session::create();
Session::set('token', md5(mt_rand() . $_SERVER['REMOTE_ADDR'] . microtime(true) . $_SERVER['persistent-id'] . mt_rand()));
Session::save();
}
self::$isShib = true;
if (!isset($_SERVER['sn'])) $_SERVER['sn'] = '';
if (!isset($_SERVER['givenName'])) $_SERVER['givenName'] = '';
if (!isset($_SERVER['mail'])) $_SERVER['mail'] = '';
$shibId = md5($_SERVER['persistent-id']);
self::$user = array(
'userid' => 0,
'shibid' => $shibId,
'login' => NULL,
'firstname' => $_SERVER['givenName'],
'lastname' => $_SERVER['sn'],
'email' => $_SERVER['mail'],
);
// Figure out whether the user should be considered a tutor
if (isset($_SERVER['affiliation']) && preg_match('/(^|;)employee@/', $_SERVER['affiliation']))
self::$user['role'] = 'tutor';
elseif (isset($_SERVER['entitlement']) && strpos(";{$_SERVER['entitlement']};", ';http://bwidm.de/entitlement/bwLehrpool;') !== false)
self::$user['role'] = 'tutor';
// Try to figure out organization
if (isset($_SERVER['affiliation']) && preg_match('/@([a-zA-Z\-\._]+)(;|$)/', $_SERVER['affiliation'], $out))
self::$user['organization'] = $out[1];
// Get matching db entry if any
$user = Database::queryFirst('SELECT userid, login, firstname, lastname, email, fixedname FROM user WHERE shibid = :shibid LIMIT 1', array('shibid' => $shibId));
if ($user === false) {
// No match in database, user is not signed up
return true;
}
if (Session::getUid() === false) {
Session::setUid($user['userid']);
Session::save();
}
// Already signed up, see if we can fetch missing fields from DB
self::$user['login'] = $user['login'];
self::$isInDb = true;
self::$isAnonymous = (empty($user['firstname']) && empty($user['lastname']));
foreach (array('firstname', 'lastname', 'email') as $key) {
if (empty(self::$user[$key]))
self::$user[$key] = $user[$key];
}
return true;
}
public static function deploy($anonymous)
{
if (empty(self::$user['shibid']))
Util::traceError('NO SHIBID');
if ($anonymous) {
Database::exec("INSERT INTO user (shibid, login, organizationid, firstname, lastname, email) "
. " VALUES (:shibid, :shibid, :org, '', '', '') "
. " ON DUPLICATE KEY UPDATE firstname = '', lastname = '', email = ''", array(
'shibid' => self::$user['shibid'],
'org' => self::getOrganizationId()
));
} else {
Database::exec("INSERT INTO user (shibid, login, organizationid, firstname, lastname, email) "
. " VALUES (:shibid, :shibid, :org, :firstname, :lastname, :email) "
. " ON DUPLICATE KEY UPDATE firstname = VALUES(firstname), lastname = VALUES(lastname), email = VALUES(email)", array(
'shibid' => self::$user['shibid'],
'firstname' => self::$user['firstname'],
'lastname' => self::$user['lastname'],
'email' => self::$user['email'],
'org' => self::getOrganizationId()
));
}
}
public static function updatePassword($pass)
{
if (!self::isLoggedIn() || self::$isShib || !self::$isInDb)
return false;
$pw = Crypto::hash6($pass);
$ret = Database::exec('UPDATE user SET password = :pass WHERE userid = :user LIMIT 1', array(
'pass' => $pw,
'user' => self::getId()
));
return $ret == 1;
}
public static function updateMail($mail)
{
if (!self::isLoggedIn() || self::$isShib || !self::$isInDb)
return false;
$ret = Database::exec('UPDATE user SET email = :mail WHERE userid = :user LIMIT 1', array(
'mail' => $mail,
'user' => self::getId()
));
return $ret == 1 || $mail === self::get('email');
}
public static function login($user, $pass)
{
$ret = Database::queryFirst('SELECT userid, password FROM user WHERE login = :user LIMIT 1', array(':user' => $user));
if ($ret === false)
return false;
if (!Crypto::verify($pass, $ret['password']))
return false;
Session::create();
Session::setUid($ret['userid']);
Session::set('token', md5(rand() . time() . mt_rand() . $_SERVER['REMOTE_ADDR'] . rand() . $_SERVER['REMOTE_PORT'] . rand() . $_SERVER['HTTP_USER_AGENT'] . microtime(true)));
Session::save();
return true;
}
public static function logout()
{
foreach ($_COOKIE as $name => $value) {
if (substr($name, 0, 5) !== '_shib')
continue;
@setcookie($name, '', time() - 8640000, null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true);
}
Session::delete();
if (self::$isShib) {
Header('Location: ?do=Logout&noredirect=yes');
} else {
Header('Location: ?do=Main');
}
exit(0);
}
}