diff --git a/include/class.auth.php b/include/class.auth.php index 0912239241c5dfb14771ffc77530123909459d94..563a79b1908b83cc462b3e8a7442a0675c823196 100644 --- a/include/class.auth.php +++ b/include/class.auth.php @@ -800,6 +800,41 @@ class AuthTokenAuthentication extends UserAuthenticationBackend { } UserAuthenticationBackend::register('AuthTokenAuthentication'); +//Simple ticket lookup backend used to recover ticket access link. +// We're using authentication backend so we can guard aganist brute force +// attempts (which doesn't buy much since the link is emailed) +class AccessLinkAuthentication extends UserAuthenticationBackend { + static $name = "Ticket Access Link Authentication"; + static $id = "authlink"; + + function authenticate($email, $number) { + + if (!($ticket = Ticket::lookupByNumber($number)) + || !($user=User::lookup(array('emails__address' => + $email)))) + return false; + + //Ticket owner? + if ($ticket->getUserId() == $user->getId()) + $user = $ticket->getOwner(); + //Collaborator? + elseif (!($user = Collaborator::lookup(array('userId' => + $user->getId(), 'ticketId' => + $ticket->getId())))) + return false; //Bro, we don't know you! + + + return new ClientSession($user); + } + + //We are not actually logging in the user.... + function login($user, $bk) { + return true; + } + +} +UserAuthenticationBackend::register('AccessLinkAuthentication'); + class osTicketClientAuthentication extends UserAuthenticationBackend { static $name = "Local Client Authentication"; static $id = "client"; diff --git a/include/class.client.php b/include/class.client.php index 105eba9cc3eb314c9cfc55544c952e4c7259d29b..14533f9bba16d7d52d3bb0274a427138e42bb381 100644 --- a/include/class.client.php +++ b/include/class.client.php @@ -51,9 +51,8 @@ abstract class TicketUser { global $ost; if (!($ticket = $this->getTicket()) - || !($dept = $ticket->getDept()) - || !($email = $dept->getAutoRespEmail()) - || !($tpl = $dept->getTemplate()->getMsgTemplate('user.accesslink'))) + || !($email = $ost->getConfig()->getDefaultEmail()) + || !($content = Page::lookup(Page::getIdByType('access-link')))) return; $vars = array( @@ -61,8 +60,13 @@ abstract class TicketUser { 'ticket' => $this->getTicket(), 'recipient' => $this); - $msg = $ost->replaceTemplateVariables($tpl->asArray(), $vars); - $email->send($this->getEmail(), $msg['subj'], $msg['body']); + $msg = $ost->replaceTemplateVariables(array( + 'subj' => $content->getName(), + 'body' => $content->getBody(), + ), $vars); + + $email->send($this->getEmail(), Format::striptags($msg['subj']), + $msg['body']); } protected function getAuthToken($algo=1) { diff --git a/include/client/accesslink.inc.php b/include/client/accesslink.inc.php new file mode 100644 index 0000000000000000000000000000000000000000..f588f3249f33d3f5684a2867487e67aa3cf655a2 --- /dev/null +++ b/include/client/accesslink.inc.php @@ -0,0 +1,34 @@ +<?php +if(!defined('OSTCLIENTINC')) die('Access Denied'); + +$email=Format::input($_POST['lemail']?$_POST['lemail']:$_GET['e']); +$ticketid=Format::input($_POST['lticket']?$_POST['lticket']:$_GET['t']); +?> +<h1>Check Ticket Status</h1> +<p>Please provide us with your email address and a ticket number, and an access +link will be emailed to you.</p> +<form action="login.php" method="post" id="clientLogin"> + <?php csrf_token(); ?> +<div style="display:table-row"> + <div style="display:table-cell;width:40%"> + <strong><?php echo Format::htmlchars($errors['login']); ?></strong> + <br> + <div> + <label for="email">E-Mail Address:</label><br/> + <input id="email" type="text" name="lemail" size="30" value="<?php echo $email; ?>"> + </div> + <div> + <label for="ticketno">Ticket Number:</label><br/> + <input id="ticketno" type="text" name="lticket" size="16" value="<?php echo $ticketid; ?>"></td> + </div> + <p> + <input class="btn" type="submit" value="Email Access Link"> + </p> + </div> + <div style="display:table-cell"></div> +</div> +</form> +<br> +<p> +If this is your first time contacting us or you've lost the ticket number, please <a href="open.php">open a new ticket</a>. +</p> diff --git a/include/staff/settings-access.inc.php b/include/staff/settings-access.inc.php index 119369908b5e1265e723228486e95ca187953d97..753d8ca43098d4f144d5f09523243c099447fd6a 100644 --- a/include/staff/settings-access.inc.php +++ b/include/staff/settings-access.inc.php @@ -141,7 +141,8 @@ if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin() || !$config) ?><a href="#ajax.php/content/<?php echo $content; ?>/manage" onclick="javascript: $.dialog($(this).attr('href').substr(1), 200); - return false;"><?php echo Format::htmlchars($title); ?></a><?php + return false;"><i class="icon-file-text"></i> <?php + echo Format::htmlchars($title); ?></a><?php }; ?> <tr><td>Password Reset Emails</td> <td><?php $manage_content('Staff Members', 'pwreset-staff'); ?> diff --git a/login.php b/login.php index 7e7e35cd6b0a5769bb8e006f9f95ad306fb0e34c..d543cc9ea11330447f7454244013566df577c2db 100644 --- a/login.php +++ b/login.php @@ -24,8 +24,12 @@ define('OSTCLIENTINC',TRUE); //make includes happy require_once(INCLUDE_DIR.'class.client.php'); require_once(INCLUDE_DIR.'class.ticket.php'); -$inc = 'login.inc.php'; -if ($_POST) { +if ($cfg->getClientRegistrationMode() == 'disabled') + $inc = 'accesslink.inc.php'; +else + $inc = 'login.inc.php'; + +if ($_POST && isset($_POST['luser'])) { if (!$_POST['luser']) $errors['err'] = 'Valid username or email address is required'; elseif (($user = UserAuthenticationBackend::process($_POST['luser'], @@ -35,6 +39,21 @@ if ($_POST) { $errors['err'] = 'Invalid email or ticket number - try again!'; } } +elseif ($_POST && isset($_POST['lticket'])) { + if (!Validator::is_email($_POST['lemail'])) + $errors['err'] = 'Valid email address and ticket number required'; + elseif (($user = UserAuthenticationBackend::process($_POST['lemail'], + $_POST['lticket'], $errors))) { + // We're using authentication backend so we can guard aganist brute + // force attempts (which doesn't buy much since the link is emailed) + $user->sendAccessLink(); + $msg = sprintf("%s - access link sent to your email!", + $user->getName()->getFirst()); + $_POST = null; + } elseif(!$errors['err']) { + $errors['err'] = 'Invalid email or ticket number - try again!'; + } +} if (!$nav) { $nav = new UserNav(); diff --git a/scp/css/scp.css b/scp/css/scp.css index ea1a1dddeec181a5c63271437c39f00925068394..4500c2dfbeb0a04c7820a08775f148bcef77c5be 100644 --- a/scp/css/scp.css +++ b/scp/css/scp.css @@ -12,6 +12,10 @@ a { text-decoration:none; } +.form_table a:hover { + text-decoration: underline; +} + .centered { text-align:center; } @@ -544,6 +548,7 @@ a.print { .form_table td { border-bottom:1px solid #ddd; + height: 20px; } table.fixed {