diff --git a/account.php b/account.php index d9c0793f996084f16c0824109816179c7198c760..7b8c7fa28ad5cda25a074de8b16844ca41217cca 100644 --- a/account.php +++ b/account.php @@ -55,15 +55,13 @@ elseif ($_POST) { $user_form = UserForm::getUserForm()->getForm($_POST); if (!$user_form->isValid(function($f) { return !$f->get('internal'); })) $errors['err'] = 'Incomplete client information'; - elseif (!$_POST['passwd1']) + elseif (!$_POST['backend'] && !$_POST['passwd1']) $errors['passwd1'] = 'New password required'; - elseif ($_POST['passwd2'] != $_POST['passwd1']) + elseif (!$_POST['backend'] && $_POST['passwd2'] != $_POST['passwd1']) $errors['passwd1'] = 'Passwords do not match'; // XXX: The email will always be in use already if a guest is logged in // and is registering for an account. Instead, - elseif (!($user = $thisclient ?: User::fromForm($user_form))) - $errors['err'] = 'Unable to register account. See messages below'; elseif (($addr = $user_form->getField('email')->getClean()) && ClientAccount::lookupByUsername($addr)) { $user_form->getField('email')->addError( @@ -71,6 +69,12 @@ elseif ($_POST) { .urlencode($addr).'" style="color:inherit"><strong>sign in</strong></a>?'); $errors['err'] = 'Unable to register account. See messages below'; } + // Users created from ClientCreateRequest + elseif (isset($_POST['backend']) && !($user = User::fromVars($user_form->getClean()))) + $errors['err'] = 'Unable to create local account. See messages below'; + // New users and users registering from a ticket access link + elseif (!$user && !($user = $thisclient ?: User::fromForm($user_form))) + $errors['err'] = 'Unable to register account. See messages below'; else { if (!($acct = ClientAccount::createForUser($user))) $errors['err'] = 'Internal error. Unable to create new account'; @@ -84,6 +88,18 @@ elseif ($_POST) { $content = Page::lookup(Page::getIdByType('registration-confirm')); $inc = 'register.confirm.inc.php'; $acct->sendResetEmail('registration-client'); + break; + case 'import': + foreach (UserAuthenticationBackend::allRegistered() as $bk) { + if ($bk::$id == $_POST['backend']) { + $cl = new ClientSession(new EndUser($user)); + $acct->confirm(); + if ($user = $bk->login($cl, $bk)) + Http::redirect('tickets.php'); + break; + } + } + break; } } diff --git a/include/class.auth.php b/include/class.auth.php index 31459cd01d734b8d8bca1b70a913d5d150aeafe4..a1b8c52209cbcd272bd44b025172a3b1bc47a350 100644 --- a/include/class.auth.php +++ b/include/class.auth.php @@ -50,6 +50,44 @@ interface AuthDirectorySearch { function search($query); } +/** + * Class: ClientCreateRequest + * + * Simple container to represent a remote authentication success for a + * client which should be imported into the local database. The class will + * provide access to the backend that authenticated the user, the username + * that the user entered when logging in, and any other information about + * the user that the backend was able to lookup. Generally, this extra + * information would be the same information retrieved from calling the + * AuthDirectorySearch::lookup() method. + */ +class ClientCreateRequest { + + var $backend; + var $username; + var $info; + + function __construct($backend, $username, $info=array()) { + $this->backend = $backend; + $this->username = $username; + $this->info = $info; + } + + function getBackend() { + return $this->backend; + } + function setBackend($what) { + $this->backend = $what; + } + + function getUsername() { + return $this->username; + } + function getInfo() { + return $this->info; + } +} + /** * Authentication backend * @@ -133,6 +171,9 @@ abstract class AuthenticationBackend { if ($result instanceof AuthenticatedUser && ($bk->login($result, $bk))) return $result; + elseif ($result instanceof ClientCreateRequest + && $bk instanceof UserAuthenticationBackend) + return $result; elseif ($result instanceof AccessDenied) { break; } @@ -407,8 +448,20 @@ abstract class UserAuthenticationBackend extends AuthenticationBackend { } function getAllowedBackends($userid) { - // White listing backends for specific user not supported. - return array(); + $backends = array(); + $sql = 'SELECT A1.backend FROM '.USER_ACCOUNT_TABLE + .' A1 INNER JOIN '.USER_EMAIL_TABLE.' A2 ON (A2.user_id = A1.user_id)' + .' WHERE backend IS NOT NULL ' + .' AND (A1.username='.db_input($userid) + .' OR A2.`address`='.db_input($userid).')'; + + if (!($res=db_query($sql, false))) + return $backends; + + while (list($bk) = db_fetch_row($res)) + $backends[] = $bk; + + return array_filter($backends); } function login($user, $bk) { diff --git a/include/class.client.php b/include/class.client.php index 8dfb211a8b95603ef9bf67ea1734ed4eb4e599f6..7d1dfbcb7c93e6852070098c10774cee7f891dab 100644 --- a/include/class.client.php +++ b/include/class.client.php @@ -474,6 +474,12 @@ class ClientAccount extends ClientAccountModel { $this->set('timezone_id', $vars['timezone_id']); $this->set('dst', isset($vars['dst']) ? 1 : 0); + if ($vars['backend']) { + $this->set('backend', $vars['backend']); + if ($vars['username']) + $this->set('username', $vars['username']); + } + if ($vars['passwd1']) { $this->set('passwd', Passwd::hash($vars['passwd1'])); $info = array('password' => $vars['passwd1']); diff --git a/include/client/register.inc.php b/include/client/register.inc.php index 71e54eb8027f7aba7420d0e5792d3cd88b55c86f..0a5676781c0de4625ac2e033279ed3c67ec7bbf5 100644 --- a/include/client/register.inc.php +++ b/include/client/register.inc.php @@ -1,18 +1,31 @@ <?php -$info = $_POST ?: array( - 'timezone_id' => $cfg->getDefaultTimezoneId(), - 'dst' => $cfg->observeDaylightSaving(), -); +$info = $_POST; +if (!isset($info['timezone_id'])) + $info += array( + 'timezone_id' => $cfg->getDefaultTimezoneId(), + 'dst' => $cfg->observeDaylightSaving(), + 'backend' => null, + ); +if (isset($user) && $user instanceof ClientCreateRequest) { + $bk = $user->getBackend(); + $info = array_merge($info, array( + 'backend' => $bk::$id, + 'username' => $user->getUsername(), + )); +} + ?> <h1>Account Registration</h1> <p> -Use the forms below to update the information we have on file for your -account +Use the forms below to create or update the information we have on file for +your account </p> <form action="account.php" method="post"> <?php csrf_token(); ?> - <input type="hidden" name="do" value="<?php echo $_REQUEST['do'] ?: 'create'; ?>" /> + <input type="hidden" name="do" value="<?php echo $_REQUEST['do'] + ?: ($info['backend'] ? 'import' :'create'); ?>" /> <table width="800" class="padded"> +<tbody> <?php $cf = $user_form ?: UserForm::getInstance(); $cf->render(false); @@ -54,6 +67,23 @@ account <div><hr><h3>Access Credentials</h3></div> </td> </tr> +<?php if ($info['backend']) { ?> +<tr> + <td width="180"> + Login With: + </td> + <td> + <input type="hidden" name="backend" value="<?php echo $info['backend']; ?>"/> + <input type="hidden" name="username" value="<?php echo $info['username']; ?>"/> +<?php foreach (UserAuthenticationBackend::allRegistered() as $bk) { + if ($bk::$id == $info['backend']) { + echo $bk::$name; + break; + } +} ?> + </td> +</tr> +<?php } else { ?> <tr> <td width="180"> Create a Password: @@ -72,6 +102,8 @@ account <span class="error"> <?php echo $errors['passwd2']; ?></span> </td> </tr> +<?php } ?> +</tbody> </table> <hr> <p style="text-align: center;"> diff --git a/login.php b/login.php index 4d9bda78c78661ac0fde10bb3005aabdba0cad56..41658e48364725c00be88ba3baf476d91165aaf7 100644 --- a/login.php +++ b/login.php @@ -35,7 +35,21 @@ if ($_POST && isset($_POST['luser'])) { $errors['err'] = 'Valid username or email address is required'; elseif (($user = UserAuthenticationBackend::process($_POST['luser'], $_POST['lpasswd'], $errors))) { - Http::redirect($_SESSION['_client']['auth']['dest'] ?: 'tickets.php'); + if ($user instanceof ClientCreateRequest) { + if ($cfg && $cfg->isClientRegistrationEnabled()) { + $inc = 'register.inc.php'; + $user_form = UserForm::getUserForm()->getForm($user->getInfo()); + } + else { + $errors['err'] = 'Access Denied. Contact your help desk + administrator to have an account registered for you'; + // fall through to show login page again + } + } + else { + Http::redirect($_SESSION['_client']['auth']['dest'] + ?: 'tickets.php'); + } } elseif(!$errors['err']) { $errors['err'] = 'Invalid username or password - try again!'; }