Commit f8de498e authored by Nigel McNie's avatar Nigel McNie Committed by Nigel McNie

Broke $SESSION and $USER into distinct roles. $SESSION is now a waffer thin

wrapper around $_SESSION, and $USER deals with system users and their
preferences.
parent 26deabdf
......@@ -60,7 +60,7 @@ $type = param_alpha('type', 'all');
$limit = param_integer('limit', 10);
$offset = param_integer('offset', 0);
$userid = $SESSION->get('id');
$userid = $USER->get('id');
if ($type == 'all') {
$count = count_records('notification_internal_activity', 'usr', $userid);
......
......@@ -37,7 +37,7 @@ $notifications = plugins_installed('notification');
$elements = array();
foreach ($activitytypes as $type) {
if (!$dv = $SESSION->get_activity_preference($type->name)) {
if (!$dv = $USER->get_activity_preference($type->name)) {
$dv = 'internal';
}
$elements[$type->name] = array(
......@@ -76,11 +76,11 @@ $smarty->assign('form', pieform($prefsform));
$smarty->display('account/activity/preferences/index.tpl');
function activityprefs_submit($values) {
global $activitytypes, $SESSION;
global $activitytypes, $USER;
$userid = $SESSION->get('id');
$userid = $USER->get('id');
foreach ($activitytypes as $type) {
$SESSION->set_activity_preference($type->name, $values[$type->name]);
$USER->set_activity_preference($type->name, $values[$type->name]);
}
json_reply(false, get_string('prefssaved', 'account'));
exit;
......
......@@ -32,9 +32,9 @@ require(dirname(dirname(__FILE__)) . '/init.php');
require_once('pieforms/pieform.php');
// load up user preferences
$prefs = (object)($SESSION->get('accountprefs'));
$prefs = (object)($USER->get('accountprefs'));
$authtype = auth_get_authtype_for_institution($USER->institution);
$authtype = auth_get_authtype_for_institution($USER->get('institution'));
$authclass = 'Auth' . ucfirst($authtype);
safe_require('auth', $authtype);
......@@ -149,15 +149,12 @@ $smarty->display('account/index.tpl');
function accountprefs_validate(Pieform $form, $values) {
if ($values['oldpassword'] !== '') {
global $SESSION, $authtype, $authclass;
if (!call_static_method($authclass, 'authenticate_user_account', $SESSION->get('username'), $values['oldpassword'], $SESSION->get('institution'))) {
global $USER, $authtype, $authclass;
if (!call_static_method($authclass, 'authenticate_user_account', $USER->get('username'), $values['oldpassword'], $USER->get('institution'))) {
$form->set_error('oldpassword', get_string('oldpasswordincorrect', 'account'));
return;
}
$user = new StdClass;
$user->username = $SESSION->get('username');
$user->institution = $SESSION->get('institution');
password_validate($form, $values, $user);
password_validate($form, $values, $USER);
}
else if ($values['password1'] !== '' || $values['password2'] !== '') {
$form->set_error('oldpassword', get_string('mustspecifyoldpassword'));
......@@ -165,26 +162,26 @@ function accountprefs_validate(Pieform $form, $values) {
}
function accountprefs_submit($values) {
global $SESSION;
global $USER;
db_begin();
if ($values['password1'] !== '') {
global $authclass;
$password = call_static_method($authclass, 'change_password', $SESSION->get('username'), $values['password1']);
$password = call_static_method($authclass, 'change_password', $USER->get('username'), $values['password1']);
$user = new StdClass;
$user->password = $password;
$user->passwordchange = 0;
$where = new StdClass;
$where->username = $SESSION->get('username');
$where->username = $USER->get('username');
update_record('usr', $user, $where);
$SESSION->set('password', $password);
$SESSION->set('passwordchange', 0);
$USER->set('password', $password);
$USER->set('passwordchange', 0);
}
// use this as looping through values is not safe.
$expectedprefs = expected_account_preferences();
foreach (array_keys($expectedprefs) as $pref) {
$SESSION->set_account_preference($pref, $values[$pref]);
$USER->set_account_preference($pref, $values[$pref]);
}
db_commit();
......
......@@ -34,7 +34,7 @@ $stopmonitoring = param_integer('stopmonitoring', 0);
$getartefacts = param_integer('getartefacts', 0);
if ($stopmonitoring) {
$userid = $SESSION->get('id');
$userid = $USER->get('id');
$count = 0;
db_begin();
try {
......@@ -71,7 +71,7 @@ $type = param_alpha('type', 'views');
$limit = param_integer('limit', 10);
$offset = param_integer('offset', 0);
$userid = $SESSION->get('id');
$userid = $USER->get('id');
$prefix = get_config('dbprefix');
if ($type == 'views') {
......
......@@ -37,7 +37,7 @@ $upgrades = check_upgrades();
if (isset($upgrades['core']) && !empty($upgrades['core']->install)) {
$smarty->assign('installing', true);
$smarty->assign('releaseargs', array($upgrades['core']->torelease,$upgrades['core']->to));
$smarty->assign('releaseargs', array($upgrades['core']->torelease, $upgrades['core']->to));
$smarty->display('admin/installgpl.tpl');
exit;
}
......
......@@ -132,6 +132,9 @@ EOJS;
$smarty->assign('INLINEJAVASCRIPT', $js);
$smarty->assign_by_ref('upgrades', $upgrades);
if (isset($upgrades['core'])) {
$smarty->assign('releaseargs', array($upgrades['core']->torelease, $upgrades['core']->to));
}
$smarty->display('admin/upgrade.tpl');
?>
......@@ -36,7 +36,7 @@ $element_required = call_static_method('ArtefactTypeProfile', 'get_mandatory_fie
// load existing profile information
$profilefields = array();
$profile_data = get_records_select('artefact', "owner=? AND artefacttype IN (" . join(",",array_map(create_function('$a','return db_quote($a);'),array_keys($element_list))) . ")", array($USER->id));
$profile_data = get_records_select('artefact', "owner=? AND artefacttype IN (" . join(",",array_map(create_function('$a','return db_quote($a);'),array_keys($element_list))) . ")", array($USER->get('id')));
if ($profile_data) {
foreach ($profile_data as $field) {
......@@ -45,7 +45,7 @@ if ($profile_data) {
}
$profilefields['email'] = array();
$profilefields['email']['all'] = get_rows('artefact_internal_profile_email', 'owner', $USER->id);
$profilefields['email']['all'] = get_rows('artefact_internal_profile_email', 'owner', $USER->get('id'));
$profilefields['email']['validated'] = array();
$profilefields['email']['unvalidated'] = array();
if ($profilefields['email']['all']) {
......@@ -148,20 +148,20 @@ function profileform_submit($values) {
email_user(
(object)array(
'firstname' => $USER->firstname,
'lastname' => $USER->lastname,
'preferredname' => $USER->preferredname,
'firstname' => $USER->get('firstname'),
'lastname' => $USER->get('lastname'),
'preferredname' => $USER->get('preferredname'),
'email' => $email,
),
null,
get_string('emailvalidation_subject', 'artefact.internal'),
get_string('emailvalidation_body', 'artefact.internal', $USER->firstname, $email, $key_url)
get_string('emailvalidation_body', 'artefact.internal', $USER->get('firstname'), $email, $key_url)
);
insert_record(
'artefact_internal_profile_email',
(object) array(
'owner' => $USER->id,
'owner' => $USER->get('id'),
'email' => $email,
'verified' => 0,
'key' => $key,
......@@ -179,9 +179,9 @@ function profileform_submit($values) {
continue;
}
$artefact_id = get_field('artefact_internal_profile_email', 'artefact', 'email', $email, 'owner', $USER->id);
$artefact_id = get_field('artefact_internal_profile_email', 'artefact', 'email', $email, 'owner', $USER->get('id'));
delete_records('artefact_internal_profile_email', 'email', $email, 'owner', $USER->id);
delete_records('artefact_internal_profile_email', 'email', $email, 'owner', $USER->get('id'));
if ($artefact_id) {
global $db;
......@@ -205,7 +205,7 @@ function profileform_submit($values) {
continue;
}
delete_records('artefact_internal_profile_email', 'email', $email, 'owner', $USER->id);
delete_records('artefact_internal_profile_email', 'email', $email, 'owner', $USER->get('id'));
}
if ($profilefields['email']['default'] != $values['email']['default']) {
......@@ -215,7 +215,7 @@ function profileform_submit($values) {
'principal' => 0,
),
(object)array(
'owner' => $USER->id,
'owner' => $USER->get('id'),
'email' => $profilefields['email']['default'],
)
);
......@@ -225,7 +225,7 @@ function profileform_submit($values) {
'principal' => 1,
),
(object) array(
'owner' => $USER->id,
'owner' => $USER->get('id'),
'email' => $values['email']['default'],
)
);
......@@ -235,14 +235,14 @@ function profileform_submit($values) {
'email' => $values['email']['default'],
),
(object) array(
'id' => $USER->id,
'id' => $USER->get('id'),
)
);
}
}
else {
$classname = generate_artefact_class_name($element);
$profile = new $classname(0, array('owner' => $USER->id));
$profile = new $classname(0, array('owner' => $USER->get('id')));
$profile->set('title', $values[$element]);
$profile->commit();
}
......
......@@ -27,6 +27,7 @@
defined('INTERNAL') || die();
require('session.php');
require(get_config('docroot') . 'auth/user.php');
/**
* Unknown user exception
......@@ -90,35 +91,6 @@ abstract class Auth {
return true;
}
/**
* If a validation form is to be used, the result of
* {@link get_configuration_form} should be passed through this method
* before being returned. This method builds the rest of the form.
*
* @param string $method The name of the authentication method (for
* example 'internal'). Lowercase please.
* @param array $elements The elements in the form.
* @return array The form definition. <kbd>false</kbd> if there
* is no form for the authentication method.
*/
protected static final function build_form($method, $elements) {
if (count($elements)) {
$elements['submit'] = array(
'type' => 'submit',
'value' => 'Update'
);
$elements['method'] = array(
'type' => 'hidden',
'value' => $method
);
return array(
'name' => 'auth',
'elements' => $elements
);
}
return false;
}
}
......@@ -139,58 +111,64 @@ abstract class Auth {
* testing is done to make sure the user has the required permissions to see
* the page.
*
* @return object The $USER object, if the user is logged in and continuing
* their session.
*/
function auth_setup () {
global $SESSION, $USER;
// If the system is not installed, let the user through in the hope that
// they can fix this little problem :)
log_debug('auth_setup()');
if (!get_config('installed')) {
$SESSION->logout();
log_debug('system not installed, letting user through');
$USER->logout();
return;
}
// Check the time that the session is set to log out. If the user does
// not have a session, this time will be 0.
$sessionlogouttime = $SESSION->get('logout_time');
$sessionlogouttime = $USER->get('logout_time');
log_debug("logout time: $sessionlogouttime");
if ($sessionlogouttime && isset($_GET['logout'])) {
if (isset($_GET['logout'])) {
$SESSION->logout();
$SESSION->add_ok_msg(get_string('loggedoutok'));
redirect(get_config('wwwroot'));
}
log_debug("logging user out");
$USER->logout();
$SESSION->add_ok_msg(get_string('loggedoutok'));
redirect(get_config('wwwroot'));
}
if ($sessionlogouttime > time()) {
log_debug("session still active");
// The session is still active, so continue it.
// Make sure that if a user's admin status has changed, they're kicked
// out of the admin section
if (defined('ADMIN')) {
$userreallyadmin = get_field('usr', 'admin', 'id', $SESSION->get('id'));
if (!$SESSION->get('admin') && $userreallyadmin) {
$userreallyadmin = get_field('usr', 'admin', 'id', $USER->get('id'));
if (!$USER->get('admin') && $userreallyadmin) {
// The user has been made into an admin
$SESSION->set('admin', 1);
log_debug("user has been made an admin");
$USER->set('admin', 1);
}
else if ($SESSION->get('admin') && !$userreallyadmin) {
else if ($USER->get('admin') && !$userreallyadmin) {
// The user's admin rights have been taken away
$SESSION->set('admin', 0);
log_debug("users admin rights have been revoked!");
$USER->set('admin', 0);
$SESSION->add_err_msg(get_string('accessforbiddentoadminsection'));
redirect(get_config('wwwroot'));
}
elseif (!$SESSION->get('admin')) {
elseif (!$USER->get('admin')) {
// The user never was an admin
log_debug("denying user access to administration");
$SESSION->add_err_msg(get_string('accessforbiddentoadminsection'));
redirect(get_config('wwwroot'));
}
}
$USER = $SESSION->renew();
log_debug("renewing user's session");
$USER->renew();
auth_check_password_change();
return $USER;
//return $USER;
}
else if ($sessionlogouttime > 0) {
// The session timed out
$SESSION->logout();
log_debug('session timed out');
$USER->logout();
// If the page the user is viewing is public, inform them that they can
// log in again
......@@ -198,6 +176,7 @@ function auth_setup () {
// @todo this links to ?login - later it should do magic to make
// sure that whatever GET string is made it includes the old data
// correctly
log_debug('timed out on public page');
$SESSION->add_info_msg(get_string('sessiontimedoutpublic'), false);
return;
}
......@@ -206,23 +185,23 @@ function auth_setup () {
// The auth_draw_login_page function may authenticate a user if a login
// request was sent at the same time that the "timed out" message is to
// be displayed.
return $USER;
//return $USER;
}
else {
// There is no session, so we check to see if one needs to be started.
log_debug('no session');
// Build login form. If the form is submitted it will be handled here,
// and set $USER for us (this will happen when users hit a page and
// specify login data immediately
//require_once('form.php');
require_once('pieforms/pieform.php');
$form = new Pieform(auth_get_login_form());
if ($USER) {
return $USER;
if ($USER->is_logged_in()) {
return;
}
// Check if the page is public or the site is configured to be public.
if (defined('PUBLIC') && !isset($_GET['login'])) {
log_debug('user viewing public page');
return;
}
......@@ -254,11 +233,11 @@ function auth_get_authtype_for_institution($institution) {
*/
function auth_check_password_change() {
global $USER;
if (!$USER->passwordchange) {
if (!$USER->get('passwordchange')) {
return;
}
$authtype = auth_get_authtype_for_institution($USER->institution);
$authtype = auth_get_authtype_for_institution($USER->get('institution'));
$authclass = 'Auth' . ucfirst($authtype);
$url = '';
safe_require('auth', $authtype);
......@@ -328,7 +307,7 @@ function change_password_validate(Pieform $form, $values) {
// Get the authentication type for the user (based on the institution), and
// use the information to validate the password
$authtype = auth_get_authtype_for_institution($USER->institution);
$authtype = auth_get_authtype_for_institution($USER->get('institution'));
$authclass = 'Auth' . ucfirst($authtype);
$authlang = 'auth.' . $authtype;
safe_require('auth', $authtype);
......@@ -338,7 +317,7 @@ function change_password_validate(Pieform $form, $values) {
// The password cannot be the same as the old one
if (!$form->get_error('password1')
&& call_static_method($authclass, 'authenticate_user_account', $USER->username, $values['password1'], $USER->institution)) {
&& call_static_method($authclass, 'authenticate_user_account', $USER->get('username'), $values['password1'], $USER->get('institution'))) {
$form->set_error('password1', get_string('passwordnotchanged'));
}
}
......@@ -349,28 +328,28 @@ function change_password_validate(Pieform $form, $values) {
* @param array $values The submitted form values
*/
function change_password_submit($values) {
global $SESSION;
$authtype = auth_get_authtype_for_institution($SESSION->get('institution'));
global $USER, $SESSION;
$authtype = auth_get_authtype_for_institution($USER->get('institution'));
$authclass = 'Auth' . ucfirst($authtype);
// This method should exists, because if it did not then the change
// password form would not have been shown.
if ($password = call_static_method($authclass, 'change_password', $SESSION->get('username'), $values['password1'])) {
if ($password = call_static_method($authclass, 'change_password', $USER->get('username'), $values['password1'])) {
$user = new StdClass;
$user->password = $password;
$user->passwordchange = 0;
$where = new StdClass;
$where->username = $SESSION->get('username');
$where->username = $USER->get('username');
update_record('usr', $user, $where);
$SESSION->set('password', $password);
$SESSION->set('passwordchange', 0);
$USER->set('password', $password);
$USER->set('passwordchange', 0);
$SESSION->add_ok_msg(get_string('passwordsaved'));
redirect(get_config('wwwroot'));
exit;
}
throw new Exception('Attempt by "' . $SESSION->get('username') . '@'
. $SESSION->get('institution') . 'to change their password failed');
throw new Exception('Attempt by "' . $USER->get('username') . '@'
. $USER->get('institution') . 'to change their password failed');
}
/**
......@@ -401,7 +380,7 @@ function auth_draw_login_page($message=null, Pieform $form=null) {
* This happens when a user's session times out and they resend post
* data. The request should just continue if so.
*/
if ($USER) {
if ($USER->is_logged_in()) {
return;
}
......@@ -550,6 +529,7 @@ EOF;
*/
function login_submit($values) {
global $SESSION, $USER;
log_debug('login_submit()');
$username = $values['login_username'];
$password = $values['login_password'];
......@@ -563,18 +543,19 @@ function login_submit($values) {
if (call_static_method($authclass, 'authenticate_user_account', $username, $password, $institution)) {
// User logged in! Set a cookie to remember their institution
set_cookie('institution', $institution);
log_debug('user authenticated successfully');
if (!record_exists('usr', 'username', $username)) {
// We don't know about this user. But if the authentication
// method says they're fine, then we must insert data for them
// into the usr table.
// @todo document what needs to be returned by get_user_info
$USER = call_static_method($authclass, 'get_user_info', $username);
insert_record('usr', $USER);
$userdata = call_static_method($authclass, 'get_user_info', $username);
insert_record('usr', $userdata);
}
// @todo config form option for this for each external plugin. NOT for internal
else if (get_config_plugin('auth', $authtype, 'updateuserinfoonlogin')) {
$USER = call_static_method($authclass, 'get_user_info', $username);
$userdata = call_static_method($authclass, 'get_user_info', $username);
$where = new StdClass;
$where->username = $username;
$where->institution = $institution;
......@@ -582,23 +563,22 @@ function login_submit($values) {
// that needs to be validated somewhere. Because here we do an insert into the
// usr table, that needs to work. and provide enough information for future
// authentication attempts
update_record('usr', $USER, $where);
update_record('usr', $userdata, $where);
}
else {
$USER = get_record('usr', 'username', $username, null, null, null, null, '*, ' . db_format_tsfield('expiry'));
$userdata = get_record('usr', 'username', $username, null, null, null, null, '*, ' . db_format_tsfield('expiry'));
}
// Only admins in the admin section!
if (defined('ADMIN') && !$USER->admin) {
if (defined('ADMIN') && !$userdata->admin) {
log_debug('user not allowed in admin section');
$SESSION->add_err_msg(get_string('accessforbiddentoadminsection'));
redirect(get_config('wwwroot'));
}
// Check if the user's account has expired
if ($USER->expiry > 0 && time() > $USER->expiry) {
// Trash the $USER object, used for checking if the user is logged in.
// Smarty uses it and puts login-only stuff in the output otherwise...
$USER = null;
// @todo TEST THIS
if ($userdata->expiry > 0 && time() > $userdata->expiry) {
die_info(get_string('accountexpired'));
}
......@@ -606,14 +586,13 @@ function login_submit($values) {
// Note: only the internal authentication method can say if a user is suspended for now.
// There are problems with how searching excluding suspended users will work that would
// need to be resolved before this could be implemented for all methods
if ($suspend = get_record('usr_suspension', 'usr', $USER->id)) {
$USER = null;
// @todo TEST THIS
if ($suspend = get_record('usr_suspension', 'usr', $userdata->id)) {
die_info(get_string('accountsuspended', 'mahara', $suspend->ctime, $suspend->reason));
}
// User is allowed to log in
$SESSION->login($USER);
$USER->logout_time = $SESSION->get('logout_time');
$USER->login($userdata);
auth_check_password_change();
}
else {
......
......@@ -26,12 +26,13 @@
defined('INTERNAL') || die();
/**
* The session class handles user sessions and session messages.
* The session class handles session data and messages.
*
* This class stores information about the user across page loads,
* so it only needs to be requested once when a user logs in.
* This class stores information across page loads, using only a cookie to
* remember the info. User information is stored in the session so it does
* not have to be requested each time the page is loaded, however any other
* information can also be stored using this class.
*
* This class also is smart about giving out sessions - if a visitor
* has not logged in (e.g. they are a guest, searchbot or a simple
......@@ -43,39 +44,9 @@ defined('INTERNAL') || die();
class Session {
/**
* Defaults for user information.
*
* @var array
*/
private $defaults;
/**
* Sets defaults for the session object (only because PHP5 does not appear
* to support private static const arrays), and resumes a session only if
* a session already exists.
* Resumes an existing session, only if there is one
*/
public function __construct() {
$this->defaults = array(
'logout_time' => 0,
'id' => 0,
'username' => '',
'password' => '',
'salt' => '',
'institution' => 'mahara',
'passwordchange' => false,
'deleted' => false,
'expiry' => 0,
'lastlogin' => 0,
'staff' => false,
'admin' => false,
'firstname' => '',
'lastname' => '',
'preferredname' => '',
'email' => '',
'accountprefs' => array(),
'activityprefs' => array(),