diff --git a/include/ajax.users.php b/include/ajax.users.php index 71ebe426235f58789f8afcc934a9754415a5414b..3a102c272208de0c9b47c71bf68f64e09aed35bd 100644 --- a/include/ajax.users.php +++ b/include/ajax.users.php @@ -110,6 +110,91 @@ class UsersAjaxAPI extends AjaxController { include(STAFFINC_DIR . 'templates/user.tmpl.php'); } + function register($id) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, 'Login Required'); + elseif (!($user = User::lookup($id))) + Http::response(404, 'Unknown user'); + + $errors = $info = array(); + if ($_POST) { + // Register user on post + if ($user->getAccount()) + $info['error'] = 'User already registered'; + elseif ($user->register($_POST, $errors)) + Http::response(201, 'Account created successfully'); + + // Unable to create user. + $info = Format::htmlchars($_POST); + if ($errors['err']) + $info['error'] = $errors['err']; + else + $info['error'] = 'Unable to register user - try again!'; + } + + include(STAFFINC_DIR . 'templates/user-register.tmpl.php'); + } + + function manage($id, $target) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, 'Login Required'); + elseif (!($user = User::lookup($id))) + Http::response(404, 'Unknown user'); + + if (!($account = $user->getAccount())) + return self::register($id); + + $errors = array(); + $info = $account->getInfo(); + + if ($_POST) { + if ($account->update($_POST, $errors)) + Http::response(201, 'Account updated successfully'); + + // Unable to update account + $info = Format::htmlchars($_POST); + + if ($errors['err']) + $info['error'] = $errors['err']; + else + $info['error'] = 'Unable to update account - try again!'; + } + + $info['_target'] = $target; + + include(STAFFINC_DIR . 'templates/user-account.tmpl.php'); + } + + function delete($id) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, 'Login Required'); + elseif (!($user = User::lookup($id))) + Http::response(404, 'Unknown user'); + + //Switch to end user so we can get ticket stats + // fixme: use orm to get ticket count at the user model level. + $user = new EndUser($user); + + $info = array(); + if ($_SERVER['REQUEST_METHOD'] == 'DELETE') { + + if ($user->getNumTickets()) + $info['error'] = 'You cannot delete a user with tickets!'; + elseif ($user->delete()) + Http::response(204, 'User deleted successfully'); + else + $info['error'] = 'Unable to delete user - try again!'; + } + + include(STAFFINC_DIR . 'templates/user-delete.tmpl.php'); + } + function getUser($id=false) { if(($user=User::lookup(($id) ? $id : $_REQUEST['id']))) @@ -122,11 +207,19 @@ class UsersAjaxAPI extends AjaxController { function addUser() { - $form = UserForm::getUserForm()->getForm($_POST); - if (($user = User::fromForm($form))) - Http::response(201, $user->to_json()); + $info = array(); + + if ($_POST) { - $info = array('error' =>'Error adding user - try again!'); + $form = UserForm::getUserForm()->getForm($_POST); + if (($user = User::fromForm($form))) + Http::response(201, $user->to_json()); + + $info = array('error' =>'Error adding user - try again!'); + } else { + $info['lookuptype'] = remote; + $info['title'] = 'Add New User'; + } return self::_lookupform($form, $info); } diff --git a/include/staff/templates/user-account.tmpl.php b/include/staff/templates/user-account.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..2bd29e598692b7a13373c7e3f77db8602cd8e3e1 --- /dev/null +++ b/include/staff/templates/user-account.tmpl.php @@ -0,0 +1,162 @@ +<?php +$account = $user->getAccount(); +$access = (isset($info['_target']) && $info['_target'] == 'access'); + +if (!$info['title']) + $info['title'] = Format::htmlchars($user->getName()); +?> +<h3><?php echo $info['title']; ?></h3> +<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> +<div class="clear"></div> +<hr/> +<?php +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} ?> +<ul class="tabs"> + <li><a href="#user-account" <?php echo !$access? 'class="active"' : ''; ?> + ><i class="icon-user"></i> User Information</a></li> + <li><a href="#user-access" <?php echo $access? 'class="active"' : ''; ?> + ><i class="icon-fixed-width icon-lock faded"></i> Manage Access</a></li> +</ul> + + +<form method="post" class="user" action="#users/<?php echo $user->getId(); ?>/manage" > + <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" /> + <div class="tab_content" id="user-account" style="display:<?php echo $access? 'none' : 'block'; ?>; margin:5px;"> + <form method="post" class="user" action="#users/<?php echo $user->getId(); ?>/manage" > + <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" /> + <table width="100%"> + <tbody> + <tr> + <th colspan="2"> + <em><strong>User Information</strong></em> + </th> + </tr> + <tr> + <td width="180"> + Name: + </td> + <td> <?php echo $user->getName(); ?> </td> + </tr> + <tr> + <td width="180"> + Email: + </td> + <td> <?php echo $user->getEmail(); ?> </td> + </tr> + <tr> + <td width="180"> + Organization: + </td> + <td> + <input type="text" size="35" name="org" value="<?php echo $info['org']; ?>"> + <span class="error"> <?php echo $errors['org']; ?></span> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="2"><em><strong>User Preferences</strong></em></th> + </tr> + <td>Time Zone:</td> + <td> + <select name="timezone_id" id="timezone_id"> + <?php + $sql='SELECT id, offset,timezone FROM '.TIMEZONE_TABLE.' ORDER BY id'; + if(($res=db_query($sql)) && db_num_rows($res)){ + while(list($id,$offset, $tz)=db_fetch_row($res)){ + $sel=($info['timezone_id']==$id)?'selected="selected"':''; + echo sprintf('<option value="%d" %s>GMT %s - %s</option>',$id,$sel,$offset,$tz); + } + } + ?> + </select> + <span class="error"><?php echo $errors['timezone_id']; ?></span> + </td> + </tr> + <tr> + <td width="180"> + Daylight Saving: + </td> + <td> + <input type="checkbox" name="dst" value="1" <?php echo $info['dst']?'checked="checked"':''; ?>> + Observe daylight saving + </td> + </tr> + </tbody> + </table> + </div> + <div class="tab_content" id="user-access" style="display:<?php echo $access? 'block' : 'none'; ?>; margin:5px;"> + <table width="100%"> + <tbody> + <tr> + <th colspan="2"><em><strong>Account Access</strong></em></th> + </tr> + <tr> + <td width="180"> + Username: + </td> + <td> + <input type="text" size="35" name="username" value="<?php echo $info['username'] ?: $user->getEmail(); ?>"> + <span class="error"> <?php echo $errors['username']; ?></span> + </td> + </tr> + <tr> + <td width="180"> + New Password: + </td> + <td> + <input type="password" size="35" name="passwd1" value="<?php echo $info['passwd1']; ?>"> + <span class="error"> <?php echo + $errors['passwd1']; ?></span> + </td> + </tr> + <tr> + <td width="180"> + Confirm Password: + </td> + <td> + <input type="password" size="35" name="passwd2" value="<?php echo $info['passwd2']; ?>"> + <span class="error"> <?php echo $errors['passwd2']; ?></span> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="2"><em><strong>Account Flags</strong></em></th> + </tr> + <tr> + <td colspan="2"> + <div><input type="checkbox" name="flags[]" value="locked"> Locked (reason here) </div> + <div><input type="checkbox" name="flags[]" value="locked"> Require Password Reset</div> + </td> + </tr> + </tbody> + </table> + </div> + <hr> + <p class="full-width"> + <span class="buttons" style="float:left"> + <input type="reset" value="Reset"> + <input type="button" name="cancel" class="close" value="Cancel"> + </span> + <span class="buttons" style="float:right"> + <input type="submit" + value="Save Changes"> + </span> + </p> +</form> +<div class="clear"></div> +<script type="text/javascript"> +$(function() { + $(document).on('click', 'input#sendemail', function(e) { + if ($(this).prop('checked')) + $('tbody#password').hide(); + else + $('tbody#password').show(); + }); +}); +</script> diff --git a/include/staff/templates/user-delete.tmpl.php b/include/staff/templates/user-delete.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..661bfa70ee08148f1291238337edbf686ccdd77c --- /dev/null +++ b/include/staff/templates/user-delete.tmpl.php @@ -0,0 +1,93 @@ +<?php + +if (!$info['title']) + $info['title'] = 'Delete User: '.Format::htmlchars($user->getName()); + +$info['warn'] = 'Deleted users and tickets CANNOT be recovered'; + +?> +<h3><?php echo $info['title']; ?></h3> +<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> +<hr/> +<?php + +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['warn']) { + echo sprintf('<p id="msg_warning">%s</p>', $info['warn']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} ?> + +<div id="user-profile" style="margin:5px;"> + <i class="icon-user icon-4x pull-left icon-border"></i> + <?php + // TODO: Implement change of ownership + if (0 && $user->getNumTickets()) { ?> + <a class="action-button pull-right change-user" style="overflow:inherit" + href="#users/<?php echo $user->getId(); ?>/replace" ><i + class="icon-user"></i> Change Tickets Ownership</a> + <?php + } ?> + <div><b> <?php echo Format::htmlchars($user->getName()->getOriginal()); ?></b></div> + <div><<?php echo $user->getEmail(); ?>></div> + <table style="margin-top: 1em;"> +<?php foreach ($user->getDynamicData() as $entry) { +?> + <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php + echo $entry->getForm()->get('title'); ?></strong></td></tr> +<?php foreach ($entry->getAnswers() as $a) { ?> + <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label')); + ?>:</td> + <td style="border-bottom: 1px dotted #ccc"><?php echo $a->display(); ?></td> + </tr> +<?php } +} +?> + </table> + <div class="clear"></div> + <hr> + <?php + if ($user->getNumTickets()) { + echo sprintf('<div><input type="checkbox" name="deletetickets" value="1" > + <strong>Delete <a href="tickets.php?a=search&uid=%d" target="_blank">%d + %s</a> and any associated attachments and data.</strong></div><hr>', + $user->getId(), + $user->getNumTickets(), + ($user->getNumTickets() >1) ? 'tickets' : 'ticket' + ); + } + ?> + <form method="delete" class="user" + action="#users/<?php echo $user->getId(); ?>/delete"> + <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" /> + <p class="full-width"> + <span class="buttons" style="float:left"> + <input type="reset" value="Reset"> + <input type="button" name="cancel" class="close" + value="No, Cancel"> + </span> + <span class="buttons" style="float:right"> + <input type="submit" value="Yes, Delete User"> + </span> + </p> + </form> +</div> +<div class="clear"></div> +<script type="text/javascript"> +$(function() { + $('a#edituser').click( function(e) { + e.preventDefault(); + $('div#user-profile').hide(); + $('div#user-form').fadeIn(); + return false; + }); + + $(document).on('click', 'form.user input.cancel', function (e) { + e.preventDefault(); + $('div#user-form').hide(); + $('div#user-profile').fadeIn(); + return false; + }); +}); +</script> diff --git a/include/staff/templates/user-lookup.tmpl.php b/include/staff/templates/user-lookup.tmpl.php index 3604ed5a29ddff2246343d69a41a32a9cad810fc..39a617e01d4672c661cd65a2699d559c202dcb68 100644 --- a/include/staff/templates/user-lookup.tmpl.php +++ b/include/staff/templates/user-lookup.tmpl.php @@ -3,7 +3,11 @@ <b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> <hr/> <div><p id="msg_info"><i class="icon-info-sign"></i> Search existing users or add a new user.</p></div> -<div style="margin-bottom:10px;"><input type="text" class="search-input" style="width:100%;" placeholder="Search by email, phone or name" id="user-search" autocorrect="off" autocomplete="off"/></div> +<div style="margin-bottom:10px;"> + <input type="text" class="search-input" style="width:100%;" + placeholder="Search by email, phone or name" id="user-search" + autocorrect="off" autocomplete="off"/> +</div> <?php if ($info['error']) { echo sprintf('<p id="msg_error">%s</p>', $info['error']); @@ -73,7 +77,8 @@ $(function() { source: function (typeahead, query) { if (last_req) last_req.abort(); last_req = $.ajax({ - url: "ajax.php/users?q="+query, + url: "ajax.php/users<?php + echo $info['lookuptype'] ? "/{$info['lookuptype']}" : '' ?>?q="+query, dataType: 'json', success: function (data) { typeahead.process(data); diff --git a/include/staff/templates/user-register.tmpl.php b/include/staff/templates/user-register.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..805ee4a4f8df156e4d7a4cfaa97720e08b0526bd --- /dev/null +++ b/include/staff/templates/user-register.tmpl.php @@ -0,0 +1,131 @@ +<?php +if (!$info['title']) + $info['title'] = 'Register: '.Format::htmlchars($user->getName()); + +// TODO: Set defaults +if (!$_POST) { + $info['sendemail'] = true; // send email confirmation. +} + +?> +<h3><?php echo $info['title']; ?></h3> +<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b> +<div class="clear"></div> +<hr/> +<?php +if ($info['error']) { + echo sprintf('<p id="msg_error">%s</p>', $info['error']); +} elseif ($info['msg']) { + echo sprintf('<p id="msg_notice">%s</p>', $info['msg']); +} ?> +<div><p id="msg_info"><i class="icon-info-sign"></i> Complete the form +below to create a user account for <b><?php echo +$user->getName()->getOriginal(); ?></b>.</p></div> +<div id="user-registration" style="display:block; margin:5px;"> + <form method="post" class="user" + action="#users/<?php echo $user->getId(); ?>/register"> + <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" /> + <table width="100%"> + <tbody> + <tr> + <th colspan="2"> + <em><strong>User Account Login</strong></em> + </th> + </tr> + <tr> + <td width="180"> + Status: + </td> + <td> + <input type="checkbox" id="sendemail" name="sendemail" value="1" + <?php echo $info['sendemail'] ? 'checked="checked"' : ''; ?> > + Send account confirmation email to user. + </td> + </tr> + <tr> + <td width="180"> + Username: + </td> + <td> + <input type="text" size="35" name="username" value="<?php echo $info['username'] ?: $user->getEmail(); ?>"> + <span class="error"> <?php echo $errors['username']; ?></span> + </td> + </tr> + </tbody> + <tbody id="password" + style="<?php echo $info['sendemail'] ? 'display:none;' : ''; ?>" + > + <tr> + <td width="180"> + Temp. Password: + </td> + <td> + <input type="password" size="35" name="passwd1" value="<?php echo $info['passwd1']; ?>"> + <span class="error"> <?php echo + $errors['passwd1']; ?></span> + </td> + </tr> + <tr> + <td width="180"> + Confirm Password: + </td> + <td> + <input type="password" size="35" name="passwd2" value="<?php echo $info['passwd2']; ?>"> + <span class="error"> <?php echo $errors['passwd2']; ?></span> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="2"><em><strong>User Preferences</strong></em></th> + </tr> + <td>Time Zone:</td> + <td> + <select name="timezone_id" id="timezone_id"> + <?php + $sql='SELECT id, offset,timezone FROM '.TIMEZONE_TABLE.' ORDER BY id'; + if(($res=db_query($sql)) && db_num_rows($res)){ + while(list($id,$offset, $tz)=db_fetch_row($res)){ + $sel=($info['timezone_id']==$id)?'selected="selected"':''; + echo sprintf('<option value="%d" %s>GMT %s - %s</option>',$id,$sel,$offset,$tz); + } + } + ?> + </select> + <span class="error"><?php echo $errors['timezone_id']; ?></span> + </td> + </tr> + <tr> + <td width="180"> + Daylight Saving: + </td> + <td> + <input type="checkbox" name="dst" value="1" <?php echo $info['dst'] ? 'checked="checked"' : ''; ?>> + Observe daylight saving + </td> + </tr> + </tbody> + </table> + <hr> + <p class="full-width"> + <span class="buttons" style="float:left"> + <input type="reset" value="Reset"> + <input type="button" name="cancel" class="close" value="Cancel"> + </span> + <span class="buttons" style="float:right"> + <input type="submit" value="Create Account"> + </span> + </p> + </form> +</div> +<div class="clear"></div> +<script type="text/javascript"> +$(function() { + $(document).on('click', 'input#sendemail', function(e) { + if ($(this).prop('checked')) + $('tbody#password').hide(); + else + $('tbody#password').show(); + }); +}); +</script> diff --git a/scp/ajax.php b/scp/ajax.php index 7afd9ceb594f7396ebedc3dfca079d8a0e632b2b..4cc09c57abaa5d9333d27cd52090bf6319728b24 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -72,9 +72,16 @@ $dispatcher = patterns('', url('^/lookup$', 'getUser'), url_get('^/lookup/form$', 'getLookupForm'), url_post('^/lookup/form$', 'addUser'), + url_get('^/add$', 'addUser'), url_get('^/select$', 'selectUser'), url_get('^/select/(?P<id>\d+)$', 'selectUser'), url_get('^/select/auth:(?P<bk>\w+):(?P<id>.+)$', 'addRemoteUser'), + url_get('^/(?P<id>\d+)/register$', 'register'), + url_post('^/(?P<id>\d+)/register$', 'register'), + url_get('^/(?P<id>\d+)/delete$', 'delete'), + url_delete('^/(?P<id>\d+)/delete$', 'delete'), + url_get('^/(?P<id>\d+)/manage(?:/(?P<target>\w+))?$', 'manage'), + url_post('^/(?P<id>\d+)/manage(?:/(?P<target>\w+))?$', 'manage'), url_get('^/staff$', 'searchStaff') )), url('^/tickets/', patterns('ajax.tickets.php:TicketsAjaxAPI',