From 477b78080515c444b9b5efcacb52749f774d5b34 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 13 Sep 2017 21:27:02 -0400 Subject: [PATCH] Re-added all manager-related code --- README.md | 1 + admin/admin_reply_ticket.php | 6 ++- admin/admin_ticket.php | 49 +++++++++++++++---- admin/change_status.php | 6 ++- admin/edit_post.php | 15 ++++-- admin/manage_users.php | 37 ++++++++++++++ api/BusinessLogic/Categories/Category.php | 5 ++ .../Security/UserToTicketChecker.php | 6 +++ .../Categories/CategoryController.php | 1 + api/DataAccess/Categories/CategoryGateway.php | 6 ++- api/DataAccess/Security/UserGateway.php | 21 ++++++++ .../Security/UserToTicketCheckerTest.php | 19 +++++++ inc/common.inc.php | 1 + install/mods-for-hesk/database-validation.php | 1 + language/en/text.php | 4 ++ 15 files changed, 160 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index ea4cdd5d..a53bd5d5 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Mods for HESK is a set of modifications for [HESK](https://www.hesk.com) v2.7.x,
  • Custom service message icons
  • Permission templates
  • Request users location in tickets
  • +
  • Category managers
  • Show number of merged tickets in ticket search view
  • Enable / disable staff members
  • More-restricted settings page access
  • diff --git a/admin/admin_reply_ticket.php b/admin/admin_reply_ticket.php index aa373e96..96ab9f9f 100644 --- a/admin/admin_reply_ticket.php +++ b/admin/admin_reply_ticket.php @@ -39,7 +39,9 @@ hesk_dbConnect(); hesk_isLoggedIn(); /* Check permissions for this feature */ -hesk_checkPermission('can_reply_tickets'); +if (!isset($_REQUEST['isManager']) || !$_REQUEST['isManager']) { + hesk_checkPermission('can_reply_tickets'); +} /* A security check */ # hesk_token_check('POST'); @@ -279,7 +281,7 @@ if ($time_worked == '00:00:00') { $sql .= ",`time_worked` = ADDTIME(`time_worked`,'" . hesk_dbEscape($time_worked) . "') "; } -if (!empty($_POST['assign_self']) && (hesk_checkPermission('can_assign_self', 0))) { +if (!empty($_POST['assign_self']) && (hesk_checkPermission('can_assign_self', 0) || (isset($_REQUEST['isManager']) && $_REQUEST['isManager']))) { $revision = sprintf($hesklang['thist2'], hesk_date(), $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); $sql .= " , `owner`=" . intval($_SESSION['id']) . ", `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; } diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 4e23cb80..1e156790 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -107,14 +107,33 @@ if ($ticket['lastreplier']) { } /* Get category name and ID */ -$result = hesk_dbQuery("SELECT `id`, `name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` WHERE `id`='" . intval($ticket['category']) . "' LIMIT 1"); +$result = hesk_dbQuery("SELECT `id`, `name`, `manager` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` WHERE `id`='" . intval($ticket['category']) . "' LIMIT 1"); /* If this category has been deleted use the default category with ID 1 */ if (hesk_dbNumRows($result) != 1) { - $result = hesk_dbQuery("SELECT `id`, `name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` WHERE `id`='1' LIMIT 1"); + $result = hesk_dbQuery("SELECT `id`, `name`, `manager` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` WHERE `id`='1' LIMIT 1"); } $category = hesk_dbFetchAssoc($result); +$managerRS = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'users` WHERE `id` = ' . intval($_SESSION['id'])); +$managerRow = hesk_dbFetchAssoc($managerRS); +$isManager = $managerRow['id'] == $category['manager']; +if ($isManager) { + $can_del_notes = + $can_reply = + $can_delete = + $can_edit = + $can_archive = + $can_assign_self = + $can_view_unassigned = + $can_change_own_cat = + $can_change_cat = + $can_ban_emails = + $can_unban_emails = + $can_ban_ips = + $can_unban_ips = + $can_resolve = true; +} /* Is this user allowed to view tickets inside this category? */ hesk_okCategory($category['id']); @@ -971,6 +990,9 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); '; + if ($isManager) { + echo ''; + } echo ' @@ -994,12 +1016,15 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); '; + if ($isManager) { + echo ''; + } echo ' '; echo '

    ' . $hesklang['owner'] . '

    '; - if (hesk_checkPermission('can_assign_others', 0)) { + if (hesk_checkPermission('can_assign_others', 0) || $isManager) { echo '
    @@ -1242,14 +1267,15 @@ require_once(HESK_PATH . 'inc/footer.inc.php'); function hesk_getAdminButtons($category_id) { - global $hesk_settings, $hesklang, $modsForHesk_settings, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $can_resolve; + global $hesk_settings, $hesklang, $modsForHesk_settings, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $can_resolve, $isManager; $options = ''; /* Edit post */ if ($can_edit) { $tmp = $reply ? '&reply=' . $reply['id'] : ''; - $options .= ' ' . $hesklang['edit'] . ' '; + $mgr = $isManager ? '&isManager=true' : ''; + $options .= ' ' . $hesklang['edit'] . ' '; } @@ -1295,12 +1321,13 @@ function hesk_getAdminButtons($category_id) $isTicketClosed = $isTicketClosedRow['IsClosed']; $isClosable = $isTicketClosedRow['Closable'] == 'yes' || $isTicketClosedRow['Closable'] == 'sonly'; + $mgr = $isManager ? '&isManager=1' : ''; if ($isTicketClosed == 0 && $isClosable && $can_resolve) // Ticket is still open { - $options .= ' + $options .= ' ' . $hesklang['close_action'] . ' '; } elseif ($isTicketClosed == 1) { - $options .= ' + $options .= ' ' . $hesklang['open_action'] . ' '; } @@ -1486,7 +1513,7 @@ function hesk_getAdminButtons($category_id) function hesk_getAdminButtonsInTicket($reply = 0, $white = 1) { - global $hesk_settings, $hesklang, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete; + global $hesk_settings, $hesklang, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $isManager; $options = $reply ? '' : '
    '; @@ -1509,7 +1536,8 @@ function hesk_getAdminButtonsInTicket($reply = 0, $white = 1) /* Edit post */ if ($can_edit) { $tmp = $reply ? '&reply=' . $reply['id'] : ''; - $options .= ' ' . $hesklang['edtt'] . ' '; + $mgr = $isManager ? '&isManager=true' : ''; + $options .= ' ' . $hesklang['edtt'] . ' '; } @@ -2045,6 +2073,9 @@ function hesk_printReplyForm()
    + + +
    diff --git a/admin/change_status.php b/admin/change_status.php index d1d6551a..42d002f1 100644 --- a/admin/change_status.php +++ b/admin/change_status.php @@ -26,8 +26,10 @@ hesk_isLoggedIn(); $modsForHesk_settings = mfh_getSettings(); /* Check permissions for this feature */ -hesk_checkPermission('can_view_tickets'); -hesk_checkPermission('can_reply_tickets'); +if (!isset($_REQUEST['isManager']) || !$_REQUEST['isManager']) { + hesk_checkPermission('can_view_tickets'); + hesk_checkPermission('can_reply_tickets'); +} /* A security check */ hesk_token_check(); diff --git a/admin/edit_post.php b/admin/edit_post.php index 7dcdda44..f4312a2a 100644 --- a/admin/edit_post.php +++ b/admin/edit_post.php @@ -32,8 +32,11 @@ hesk_dbConnect(); hesk_isLoggedIn(); /* Check permissions for this feature */ -hesk_checkPermission('can_view_tickets'); -hesk_checkPermission('can_edit_tickets'); +if (!isset($_REQUEST['isManager']) || !$_REQUEST['isManager']) { + hesk_checkPermission('can_view_tickets'); + hesk_checkPermission('can_edit_tickets'); +} + $modsForHesk_settings = mfh_getSettings(); /* Ticket ID */ @@ -59,7 +62,10 @@ if (defined('HESK_DEMO')) { } /* Is this user allowed to view tickets inside this category? */ -hesk_okCategory($ticket['category']); +if (!isset($_REQUEST['isManager']) || !$_REQUEST['isManager']) { + hesk_okCategory($ticket['category']); +} + if (hesk_isREQUEST('reply')) { $tmpvar['id'] = intval(hesk_REQUEST('reply')) or die($hesklang['id_not_valid']); @@ -626,6 +632,9 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?> + + + diff --git a/admin/manage_users.php b/admin/manage_users.php index 4159d638..3fbbc2e3 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -621,6 +621,31 @@ function update_user() hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `owner`=0 WHERE `owner`='" . intval($myuser['id']) . "' AND `category` NOT IN (" . $myuser['categories'] . ")"); } + // Find the list of categories they are manager of. If they no longer have access to the category, revoke their manager permission. + if ($myuser['isadmin']) { + // Admins can't be managers + hesk_dbQuery('UPDATE `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'categories` SET `manager` = 0 WHERE `manager` = ' . intval($myuser['id'])); + } else { + $currentCatRs = hesk_dbQuery("SELECT `categories` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `id` = '" . intval($myuser['id']) . "' LIMIT 1"); + $rowOfCategories = hesk_dbFetchAssoc($currentCatRs); + $cats = $rowOfCategories['categories']; + $currentCategories = explode(',', $cats); + $newCategories = explode(',', $myuser['categories']); + + // If any any elements are in current but not in new, add them to the revoke array + $revokeCats = array(); + foreach ($currentCategories as $currentCategory) { + if (!in_array($currentCategory, $newCategories) && $currentCategory != '') { + array_push($revokeCats, $currentCategory); + } + } + + if (count($revokeCats) > 0) { + hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` SET `manager` = 0 WHERE `id` IN (" . implode(',', $revokeCats) . ")"); + } + } + + hesk_dbQuery( "UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `user`='" . hesk_dbEscape($myuser['user']) . "', @@ -651,6 +676,11 @@ function update_user() `default_calendar_view`=" . intval($myuser['default_calendar_view']) . " WHERE `id`='" . intval($myuser['id']) . "'"); + // If they are now inactive, remove any manager rights + if (!$myuser['active']) { + hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` SET `manager` = 0 WHERE `manager` = " . intval($myuser['id'])); + } + unset($_SESSION['save_userdata']); unset($_SESSION['userdata']); @@ -814,6 +844,10 @@ function remove() hesk_process_messages($hesklang['cant_del_own'], './manage_users.php'); } + // Revoke manager rights + hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` SET `manager` = 0 WHERE `manager` = " . intval($myuser)); + + /* Un-assign all tickets for this user */ $res = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `owner`=0 WHERE `owner`='" . intval($myuser) . "'"); @@ -877,6 +911,9 @@ function toggle_active() $active = 0; $tmp = $hesklang['user_deactivated']; + // Revoke any manager rights + hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` SET `manager` = 0 WHERE `manager` = " . intval($myuser)); + $notificationSql = ", `autoassign` = '0', `notify_new_unassigned` = '0', `notify_new_my` = '0', `notify_reply_unassigned` = '0', `notify_reply_my` = '0', `notify_assigned` = '0', `notify_pm` = '0', `notify_note` = '0', `notify_note_unassigned` = '0', `notify_overdue_unassigned` = '0'"; } diff --git a/api/BusinessLogic/Categories/Category.php b/api/BusinessLogic/Categories/Category.php index 7209823f..597c3410 100644 --- a/api/BusinessLogic/Categories/Category.php +++ b/api/BusinessLogic/Categories/Category.php @@ -51,6 +51,11 @@ class Category extends \BaseClass { */ public $priority; + /** + * @var int|null The manager for the Categories, if applicable + */ + public $manager; + /** * @var bool Indication if the user has access to the Categories */ diff --git a/api/BusinessLogic/Security/UserToTicketChecker.php b/api/BusinessLogic/Security/UserToTicketChecker.php index 13d88226..a49ecc55 100644 --- a/api/BusinessLogic/Security/UserToTicketChecker.php +++ b/api/BusinessLogic/Security/UserToTicketChecker.php @@ -31,6 +31,12 @@ class UserToTicketChecker extends \BaseClass { return false; } + $categoryManagerId = $this->userGateway->getManagerForCategory($ticket->categoryId, $heskSettings); + + if ($user->id === $categoryManagerId) { + return true; + } + $extraPermissions[] = UserPrivilege::CAN_VIEW_TICKETS; foreach ($extraPermissions as $permission) { diff --git a/api/Controllers/Categories/CategoryController.php b/api/Controllers/Categories/CategoryController.php index c89d1a1a..9d69df9f 100644 --- a/api/Controllers/Categories/CategoryController.php +++ b/api/Controllers/Categories/CategoryController.php @@ -63,6 +63,7 @@ class CategoryController extends \BaseClass { $category->description = Helpers::safeArrayGet($json, 'description'); $category->displayBorder = Helpers::safeArrayGet($json, 'displayBorder'); $category->foregroundColor = Helpers::safeArrayGet($json, 'foregroundColor'); + $category->manager = Helpers::safeArrayGet($json, 'manager'); $category->name = Helpers::safeArrayGet($json, 'name'); $category->priority = Helpers::safeArrayGet($json, 'priority'); $category->type = Helpers::safeArrayGet($json, 'type'); diff --git a/api/DataAccess/Categories/CategoryGateway.php b/api/DataAccess/Categories/CategoryGateway.php index 1a4c0d1c..2191373d 100644 --- a/api/DataAccess/Categories/CategoryGateway.php +++ b/api/DataAccess/Categories/CategoryGateway.php @@ -41,6 +41,7 @@ class CategoryGateway extends CommonDao { $category->foregroundColor = $row['foreground_color']; $category->displayBorder = $row['display_border_outline'] === '1'; $category->priority = intval($row['priority']); + $category->manager = intval($row['manager']) == 0 ? NULL : intval($row['manager']); $category->description = $row['mfh_description']; $category->numberOfTickets = intval($row['number_of_tickets']); $results[] = $category; @@ -63,11 +64,11 @@ class CategoryGateway extends CommonDao { $newOrder = hesk_dbFetchAssoc($newOrderRs); $sql = "INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "categories` - (`name`, `cat_order`, `autoassign`, `type`, `priority`, `background_color`, `usage`, + (`name`, `cat_order`, `autoassign`, `type`, `priority`, `manager`, `background_color`, `usage`, `foreground_color`, `display_border_outline`, `mfh_description`) VALUES ('" . hesk_dbEscape($category->name) . "', " . intval($newOrder['cat_order']) . ", '" . ($category->autoAssign ? 1 : 0) . "', '" . intval($category->type) . "', - '" . intval($category->priority) . "', + '" . intval($category->priority) . "', " . ($category->manager === null ? 0 : intval($category->manager)) . ", '" . hesk_dbEscape($category->backgroundColor) . "', " . intval($category->usage) . ", '" . hesk_dbEscape($category->foregroundColor) . "', '" . ($category->displayBorder ? 1 : 0) . "', '" . hesk_dbEscape($category->description) . "')"; @@ -94,6 +95,7 @@ class CategoryGateway extends CommonDao { `autoassign` = '" . ($category->autoAssign ? 1 : 0) . "', `type` = '" . intval($category->type) . "', `priority` = '" . intval($category->priority) . "', + `manager` = " . ($category->manager === null ? 0 : intval($category->manager)) . ", `background_color` = '" . hesk_dbEscape($category->backgroundColor) . "', `usage` = " . intval($category->usage) . ", `foreground_color` = '" . hesk_dbEscape($category->foregroundColor) . "', diff --git a/api/DataAccess/Security/UserGateway.php b/api/DataAccess/Security/UserGateway.php index 3ed4191b..e836f18a 100644 --- a/api/DataAccess/Security/UserGateway.php +++ b/api/DataAccess/Security/UserGateway.php @@ -99,4 +99,25 @@ class UserGateway extends CommonDao { return $users; } + + function getManagerForCategory($categoryId, $heskSettings) { + $this->init(); + + $rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "users` + WHERE `id` = ( + SELECT `manager` + FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "categories` + WHERE `id` = " . intval($categoryId) . ")"); + + if (hesk_dbNumRows($rs) === 0) { + $this->close(); + return null; + } + + $user = UserContext::fromDataRow(hesk_dbFetchAssoc($rs)); + + $this->close(); + + return $user; + } } \ No newline at end of file diff --git a/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php b/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php index cf6d1719..27d5b939 100644 --- a/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php +++ b/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php @@ -92,4 +92,23 @@ class UserToTicketCheckerTest extends TestCase { //-- Assert self::assertThat($result, self::isFalse()); } + + function testItReturnsTrueWhenTheUserDoesNotHaveEditPermissionsButIsTheCategoryManager() { + //-- Arrange + $user = new UserContext(); + $user->admin = false; + $user->categories = array(1); + $user->permissions = array(UserPrivilege::CAN_VIEW_TICKETS, 'something else'); + $user->id = 1; + $this->userGateway->method('getManagerForCategory')->willReturn(1); + + $ticket = new Ticket(); + $ticket->categoryId = 1; + + //-- Act + $result = $this->userToTicketChecker->isTicketAccessibleToUser($user, $ticket, $this->heskSettings, array(UserPrivilege::CAN_EDIT_TICKETS)); + + //-- Assert + self::assertThat($result, self::isTrue()); + } } diff --git a/inc/common.inc.php b/inc/common.inc.php index ec0ed464..94f487dc 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -2026,6 +2026,7 @@ function hesk_getFeatureArray() 'can_service_msg', /* User can manage service messages shown in customer interface */ 'can_email_tpl', /* User can manage email templates */ 'can_man_ticket_statuses', /* User can manage ticket statuses */ + 'can_set_manager', /* User can set category managers */ 'can_man_permission_tpl', /* User can manage permission templates */ 'can_man_settings', /* User can manage helpdesk settings */ 'can_change_notification_settings', /* User can change notification settings */ diff --git a/install/mods-for-hesk/database-validation.php b/install/mods-for-hesk/database-validation.php index 7f1534e8..22c34c98 100644 --- a/install/mods-for-hesk/database-validation.php +++ b/install/mods-for-hesk/database-validation.php @@ -93,6 +93,7 @@ hesk_dbConnect(); $all_good = $all_good & run_column_check('tickets', 'longitude'); $all_good = $all_good & run_column_check('stage_tickets', 'latitude'); $all_good = $all_good & run_column_check('stage_tickets', 'longitude'); + $all_good = $all_good & run_column_check('categories', 'manager'); $all_good = $all_good & run_column_check('users', 'permission_template'); $all_good = $all_good & run_table_check('permission_templates'); $all_good = $all_good & run_column_check('permission_templates', 'id'); diff --git a/language/en/text.php b/language/en/text.php index 72686f7a..4ef2c07b 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -1831,6 +1831,10 @@ $hesklang['your_current_location'] = 'Your location'; $hesklang['requesting_location_ellipsis'] = 'Requesting location...'; $hesklang['unable_to_determine_location'] = 'Unable to determine your location, or you declined to share it.'; $hesklang['save_to_see_updated_address'] = 'Save the new location to see the updated address'; +$hesklang['manager'] = 'Manager'; +$hesklang['manager_updated'] = 'Category manager has been updated.'; +$hesklang['can_set_manager'] = 'Can set category managers'; +$hesklang['no_manager'] = 'No manager'; $hesklang['manage_permission_templates'] = 'Manage Permission Templates'; $hesklang['manage_permission_templates_help'] = 'Here you can create and edit permission templates. These templates will appear when creating/editing a user. Please note that if you change the permission template\'s settings, it will NOT change the permissions of any users that are set to this permission template.';