Location: PHPKode > scripts > Research Project Calculator > research-proj-calc-0.10.2-20111121/rpc/account/index.php
<?php
/**
 * Copyright 2010 by the Regents of the University of Minnesota,
 * University Libraries - Minitex
 *
 * This file is part of The Research Project Calculator (RPC).
 *
 * RPC is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * RPC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with The RPC.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Process logins from the native authentication plugin
 */
define('BASE_DIR', dirname(__FILE__) . '/../');
require_once(BASE_DIR . '/inc/rpc.inc.php');
require_once(BASE_DIR . '/inc/rpc_config.inc.php');
require_once(BASE_DIR . '/inc/rpc_db.inc.php');
require_once(BASE_DIR . '/inc/rpc_smarty.inc.php');
require_once(BASE_DIR . '/plugins/auth/native/native_user.inc.php');

$config = RPC_Config::get_instance();
$db = RPC_DB::get_connection($config);
// Guests can perform some account actions.
RPC::init(RPC_User::RPC_AUTHLEVEL_GUEST, $config, $db);

$smarty = new RPC_Smarty($config);

// Default action is modify account settings
$account_action = isset($_GET['acct']) ? $_GET['acct'] : 'modify';
switch ($account_action)
{
	/************************ RESET PASSWORD ******************************/
	case 'resetpw':
		// Native authentication only
		if ($config->auth_plugin == 'native')
		{
			$smarty->assign('acct_action', 'resetpw');
			$smarty->assign('acct_handler', $config->app_fixed_web_path . "account/?acct=resetpw");
			if (isset($_POST['username']) && isset($_POST['transid']))
			{
				// Verify form isn't being resubmitted.  $_SESSION['transid'] won't be set if resubmitted
				if (isset($_SESSION['transid']) && $_SESSION['transid'] == $_POST['transid'])
				{
					$reset_user = new Native_User($_POST['username'], $config, $db);
					if ($reset_user->error == Native_User::ERR_NO_SUCH_USER)
					{
						$smarty->assign('acct_error', "No account could be located for " . htmlspecialchars($_POST['username']));
						$smarty->assign('transid', $_SESSION['transid']);
					}
					else if (!empty($reset_user->error))
					{
						// This shouldn't happen -- database error
						$err = "A database error occurred.";
						error_log($err . ' (' . $db->errno . ') ' . $db->error);
						$smarty->assign('acct_error', $err);
					}
					// Go ahead and process the reset
					else
					{
						$reset_user->recover_password();
						unset($_SESSION['transid']);
						$smarty->assign('acct_success', 'A new password has been emailed to ' . htmlspecialchars($_POST['username']) . " (<a href='{$config->app_relative_web_path}?acct=login'>Login</a>)");
					}
				}
			}
			// Otherwise, show the form
			else
			{
				$_SESSION['transid'] = md5(time() . rand());
				$smarty->assign('transid', $_SESSION['transid']);
			}
		}
		// No caching for form displays.
		header('Cache-control: private');
		header('Pragma: no-cache');
		$smarty->skin_display('forms/native_resetpw.tpl');
		exit();
		break;

	/************************  NEW ACCOUNT CREATION *****************************/
	case 'newacct':
		// Native authentication only
		if ($config->auth_plugin == 'native')
		{
			$smarty->assign('acct_action', 'newacct');
			$smarty->assign('acct_handler', $config->app_fixed_web_path . "account/?acct=newacct");
			// Check if this was a form submission
			if (isset($_POST['username']) && isset($_POST['transid']))
			{
				// Verify form isn't being resubmitted.  $_SESSION['transid'] won't be set if resubmitted
				if (isset($_SESSION['transid']) && $_SESSION['transid'] == $_POST['transid'])
				{
					// Validate required email, password, usertype
					$arr_resubmit = array();
					// Username is valid email address
					if (!RPC_User::validate_email($_POST['username'])) $arr_resubmit['username'] = TRUE;
					// username OK, pass back into smarty
					else $smarty->assign('createacct_username', $_POST['username']);
					// Password meets minimum complexity, and confirmation must match...
					if (!Native_User::password_meets_complexity($_POST['password']) || ($_POST['password'] !== $_POST['password-confirm']))
					{
						$arr_resubmit['password'] = TRUE;
					}
					// Password never gets passed back into smarty!
					// Usertype required as STUDENT or TEACHER
					if (!isset($_POST['usertype']) || (isset($_POST['usertype']) && $_POST['usertype'] !== 'TEACHER' && $_POST['usertype'] !== 'STUDENT'))
					{
						$arr_resubmit['usertype'] = TRUE;
					}
					else $smarty->assign('createacct_usertype', $_POST['usertype']);

					// Name isn't required, so just pass back to smarty
					if (!empty($_POST['name']))
					{
						$smarty->assign('createacct_name', $_POST['name']);
					}

					// Any invalid fields, go back to the form, hilighting invalid fields
					if (sizeof($arr_resubmit) > 0)
					{
						$smarty->assign('acct_error', 'Some required fields were omitted or invalid.');
						$smarty->assign('resubmit', $arr_resubmit);
						$smarty->assign('transid', $_SESSION['transid']);
					}
					// Nothing invalid, so go ahead and create the user
					else
					{
						// Does the requested user account already exist?
						$create_user_exists = RPC_User::username_exists($_POST['username'], $db);
						switch ($create_user_exists)
						{
							// User already exists, show form to create a different account
							case RPC_User::RPC_EXISTS:
								$smarty->assign('acct_error', "User " . htmlspecialchars($_POST['username']) . " already exists!");
								$smarty->assign('transid', $_SESSION['transid']);
								break;
							// Some error, probably database error
							case RPC_User::RPC_EXISTS_ERROR:
								$err = 'Error: User could not be created. A database error occurred.';
								error_log($err . ' (' . $db->errno . ') '. $db->error);
								$smarty->assign('acct_error', $err);
								$smarty->assign('transid', $_SESSION['transid']);
								break;
							// User doesn't already exist. Create it.
							case RPC_User::RPC_NOT_EXISTS:
								$create_username = trim($_POST['username']);
								$create_name = isset($_POST['name']) && trim($_POST['name']) != '' ? trim($_POST['name']) : "";
								// Always create as regular user
								$create_perms = RPC_User::RPC_AUTHLEVEL_USER;
								$create_type = $_POST['usertype'];
								$create_user_success = RPC_User::create_user($create_username, $create_name, $create_username, $create_type, $create_perms, $db);
								if ($create_user_success)
								{
									// Build user object and set password
									$created_user = new Native_User($create_username, $config, $db);
									if (empty($user->error))
									{
										// Old password is empty string, since none has yet been set
										$created_user->set_password("", $_POST['password']);

										// Login the new user
										$created_user->set_authenticated();
										// And load into smarty
										$smarty->set_user($created_user);
									}
									$db->commit();
									unset($_SESSION['transid']);
									$smarty->assign('acct_success', "User " . htmlspecialchars($create_username) . " was successfully created. <a href='{$config->app_relative_web_path}'>Go to the home page</a>");
								}
								else
								{
									$err = 'Error: User could not be created. A database error occurred.';
									error_log($err . ' (' . $db->errno . ') '. $db->error);
									$smarty->assign('acct_error', $err);
									$smarty->assign('transid', $_SESSION['transid']);
								}
								break;
						}
					}
				}
			}
			else
			{
				// Wasn't a form submission, so display the form.
				$_SESSION['transid'] = md5(time() . rand());
				$smarty->assign('transid', $_SESSION['transid']);
				$smarty->assign('acct_handler', $config->app_fixed_web_path . "account/?acct=newacct");
			}

			// Display the account creation template
			header('Cache-control: private');
			header('Pragma: no-cache');
			$smarty->skin_display('forms/native_newacct.tpl');
			exit();
		}
		break;

	/************************ LOGOUT USER *****************************/
	case 'logout':
		// Don't force a login if user isn't logged in
		$user = RPC::get_active_user();
		$acct_login_string = "<a href='{$config->app_relative_web_path}?acct=login'>Login</a>";
		if ($user)
		{
			$smarty->assign('user', NULL);
			$user = NULL;
			RPC::destroy_active_user();
			$smarty->assign('acct_success', "You have been logged out. ($acct_login_string)");
		}
		else
		{
			$smarty->assign('acct_success', "You are not logged in. ($acct_login_string)");
		}
		$smarty->assign('acct_action', 'logout');
		$smarty->skin_display('forms/native_modifyacct.tpl');
		break;
	/************************ MODIFY EXISTING ACCOUNT DETAILS *****************************/
	case 'modify':
	default:
		// Must have a logged-in user
		$user = RPC::get_active_user();
		if ($user)
		{
			$smarty->set_user($user);
			$smarty->assign('acct_action', 'modify');
			$smarty->assign('acct_handler', $config->app_fixed_web_path . "account/?acct=modify");
			// Is a form post, so process it
			if (isset($_POST['email']) && (isset($_SESSION['transid']) && $_POST['transid'] === $_SESSION['transid']))
			{
				$arr_resubmit = array();
				// Start with success flags for all changes.
				// If changes are made, they may be overwritten with failures...
				$modify_email_success = TRUE;
				$modify_type_success = TRUE;
				$modify_name_success = TRUE;
				$acct_error = "";
				// If changing email address, verify the new address isn't already in use
				// For native auth users, changing email also changes username.  For API auth
				// users, only the email address will change.  Either way, it can't be in use already
				if ($_POST['email'] !== $user->email)
				{
					if (!RPC_User::validate_email($_POST['email']))
					{
						$arr_resubmit['email'] = TRUE;
						$modify_email_success = FALSE;
						$acct_error = "\n<br />The supplied email address was invalid.";
					}
					else if (RPC_User::email_exists($_POST['email'], $db))
					{
						$arr_resubmit['email'] = TRUE;
						$modify_email_success = FALSE;
						$acct_error = "\n<br />The requested email address is already in use.";
					}
					// New email is usable, so update it
					else
					{
						$modify_email_success = $user->set_email($_POST['email']);
						if (!$modify_email_success) $arr_resubmit['name'] = TRUE;
					}
				}
				// Type changing
				if ($_POST['usertype'] !== $user->type)
				{
					$modify_type_success = $user->set_type($_POST['usertype']);
					if (!$modify_type_success) $arr_resubmit['usertype'] = TRUE;
				}
				// Name is changing...
				if ($_POST['name'] !== $user->name)
				{
					$modify_name_success = $user->set_name($_POST['name']);
					if (!$modify_name_success) $arr_resubmit['name'] = TRUE;
				}
				// Verify all actions were successful, and commit
				if ($modify_email_success && $modify_type_success && $modify_name_success)
				{
					$db->commit();
					unset($_SESSION['transid']);
					$smarty->assign('acct_success', "Your account settings were successfully changed. (<a href='{$config->app_fixed_web_path}'>Return to the home page</a>)");
					// For native authentication, and possibly others, the local username has now changed.
					// $_SESSION needs to be updated to reflect this
					$_SESSION['username'] = $user->username;
					$_SESSION['transid'] = md5(time() . rand());
					$smarty->assign('transid', $_SESSION['transid']);
					// Reload the user object into smarty to reflect new changes
					$smarty->set_user($user);
				}
				else
				{
					$db->rollback();
					$smarty->assign('transid', $_SESSION['transid']);
					$smarty->assign('resubmit', $arr_resubmit);
					$smarty->assign('acct_error', "Some fields could not be modified." . $acct_error);
				}
			}
	      /************************ CHANGE PASSWORD (NATIVE) *****************************/
			// Native authentication users may be changing passwords...
			else if (isset($_POST['oldpassword']) && (isset($_SESSION['transid']) && $_POST['transid'] === $_SESSION['transid']))
			{
				$arr_resubmit = array();
				// Passwords must match and be minimum 6 characters
				if ($_POST['password'] === $_POST['password-confirm'])
				{
					if ($user->set_password($_POST['oldpassword'], $_POST['password']))
					{
						$db->commit();
						$_SESSION['transid'] = md5(time() . rand());
						$smarty->assign('transid', $_SESSION['transid']);
						$smarty->assign('acct_success', "Your password has been changed.");
					}
					else
					{
						if ($user->error == Native_User::ERR_INCORRECT_CREDS)
						{
							$arr_resubmit['oldpassword'] = TRUE;
							$smarty->assign('resubmit', $arr_resubmit);
							$smarty->assign('transid', $_SESSION['transid']);
							$smarty->assign('acct_error', "You entered your old password incorrectly.");
						}
						else if ($user->error == Native_User::ERR_PASWORD_COMPLEXITY_UNMET)
						{
							$arr_resubmit['password'] = TRUE;
							$smarty->assign('resubmit', $arr_resubmit);
							$smarty->assign('transid', $_SESSION['transid']);
							$smarty->assign('acct_error', "New password must be at least 6 characters and contain at least one number.");
						}
						else
						{
							$db->rollback();
							$smarty->assign('transid', $_SESSION['transid']);
							$smarty->assign('resubmit', $arr_resubmit);
							$smarty->assign('acct_error', "A database error occurred.");
						}
					}
				}
				else
				{
					$arr_resubmit['password'] = TRUE;
					$smarty->assign('transid', $_SESSION['transid']);
					$smarty->assign('acct_error', "Your passwords did not match.");
				}
			}
			/************************ DELTE ACCOUNT *****************************/
			else if (isset($_POST['delete-confirm']) && isset($_SESSION['transid']) && $_POST['transid'] === $_SESSION['transid'])
			{
				if ($user->delete_account())
				{
					$db->commit();
					// Remove the user from smarty
					$smarty->assign('user', NULL);
					// Kill the local $user
					$user = NULL;
					// And kill the global user singleton
					RPC::destroy_active_user();
					$smarty->assign('acct_success', "Your account has been deleted. <a href='{$config->app_relative_web_path}'>Go to the home page</a>");
				}
				else
				{
					$db->rollback();
					$smarty->assign('transid', $_SESSION['transid']);
					$smarty->assign('acct_error', 'A database error occurred.  Your account could not be deleted.');
				}
			}
			// Otherwise setup the basic form
			else
			{
				$_SESSION['transid'] = md5(time() . rand());
				$smarty->assign('transid', $_SESSION['transid']);
			}
			// Display the account creation template
			header('Cache-control: private');
			header('Pragma: no-cache');
			$smarty->skin_display('forms/native_modifyacct.tpl');
			break;
		}
		// Failed user login: go to index.php
		else
		{
			header("Location: " . $config->app_fixed_web_path . "?acct=login");
			exit();
		}
}
?>
Return current item: Research Project Calculator