From d5a9d225f219b013cdfc512072f2ab57a2d5a74b Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Sun, 30 Jul 2017 01:15:27 +0000 Subject: [PATCH 001/248] Fix bootstrap-theme not disabling on Firefox --- inc/header.inc.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inc/header.inc.php b/inc/header.inc.php index 192e1580..f459df6c 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -55,10 +55,10 @@ if (is_dir(HESK_PATH . 'install')) { + > + rel="stylesheet" /> + Date: Sun, 30 Jul 2017 01:21:26 +0000 Subject: [PATCH 002/248] Swap == for != --- inc/header.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/header.inc.php b/inc/header.inc.php index f459df6c..ca27118b 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -55,7 +55,7 @@ if (is_dir(HESK_PATH . 'install')) { - + From 68308b02a5dc20de4bfa390f68197fead7aa8328 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Jul 2017 21:57:29 -0400 Subject: [PATCH 003/248] Some sort of progress on category endpoint --- .../Categories/CategoryHandler.php | 28 ++++++++++++++ .../Categories/CategoryController.php | 15 ++++++++ api/DataAccess/Categories/CategoryGateway.php | 19 ++++++++++ .../Categories/CategoryHandlerTest.php | 37 +++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 api/BusinessLogic/Categories/CategoryHandler.php create mode 100644 api/Tests/BusinessLogic/Categories/CategoryHandlerTest.php diff --git a/api/BusinessLogic/Categories/CategoryHandler.php b/api/BusinessLogic/Categories/CategoryHandler.php new file mode 100644 index 00000000..ca315998 --- /dev/null +++ b/api/BusinessLogic/Categories/CategoryHandler.php @@ -0,0 +1,28 @@ +categoryGateway = $categoryGateway; + } + + /** + * @param $category Category + * @param $heskSettings array + */ + function createCategory($category, $heskSettings) { + $this->categoryGateway->createCategory($category, $heskSettings); + } + + function editCategory($category, $heskSettings) { + + + } +} \ No newline at end of file diff --git a/api/Controllers/Categories/CategoryController.php b/api/Controllers/Categories/CategoryController.php index e376afef..bb729ca7 100644 --- a/api/Controllers/Categories/CategoryController.php +++ b/api/Controllers/Categories/CategoryController.php @@ -4,6 +4,7 @@ namespace Controllers\Categories; use BusinessLogic\Categories\CategoryRetriever; use BusinessLogic\Exceptions\ApiFriendlyException; +use Controllers\JsonRetriever; class CategoryController { function get($id) { @@ -28,4 +29,18 @@ class CategoryController { return $categoryRetriever->getAllCategories($hesk_settings, $userContext); } + + function post() { + //-- TODO: Create Category + $data = JsonRetriever::getJsonData(); + + } + + function put($id) { + //-- TODO: Edit category + } + + function delete($id) { + //-- TODO: Delete category + } } \ No newline at end of file diff --git a/api/DataAccess/Categories/CategoryGateway.php b/api/DataAccess/Categories/CategoryGateway.php index 4fd35c7b..fde6f824 100644 --- a/api/DataAccess/Categories/CategoryGateway.php +++ b/api/DataAccess/Categories/CategoryGateway.php @@ -40,4 +40,23 @@ class CategoryGateway extends CommonDao { return $results; } + + /** + * @param $category Category + * @param $heskSettings array + */ + function createCategory($category, $heskSettings) { + $this->init(); + + $sql = "INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "categories` () + VALUES ()"; + + $this->close(); + } + + function updateCategory($category, $heskSettings) { + $this->init(); + + $this->close(); + } } \ No newline at end of file diff --git a/api/Tests/BusinessLogic/Categories/CategoryHandlerTest.php b/api/Tests/BusinessLogic/Categories/CategoryHandlerTest.php new file mode 100644 index 00000000..32b5f99c --- /dev/null +++ b/api/Tests/BusinessLogic/Categories/CategoryHandlerTest.php @@ -0,0 +1,37 @@ +categoryGateway = $this->createMock(CategoryGateway::class); + + $this->categoryHandler = new CategoryHandler($this->categoryGateway); + $this->heskSettings = array(); + } + + function testCreateCallsTheGatewayWithTheCategory() { + //-- Arrange + $category = new Category(); + + //-- Assert + $this->categoryGateway->expects($this->once())->method('createCategory')->with($category, $this->heskSettings); + + //-- Act + $this->categoryHandler->createCategory($category, $this->heskSettings); + } +} From 4db151de66b88cd523148e7c11614c56133797b9 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 30 Jul 2017 14:52:03 -0400 Subject: [PATCH 004/248] Disable AutoTLS for PHPMailer --- api/BusinessLogic/Emails/BasicEmailSender.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/BusinessLogic/Emails/BasicEmailSender.php b/api/BusinessLogic/Emails/BasicEmailSender.php index 058ef937..fd6cecfe 100644 --- a/api/BusinessLogic/Emails/BasicEmailSender.php +++ b/api/BusinessLogic/Emails/BasicEmailSender.php @@ -15,6 +15,10 @@ class BasicEmailSender implements EmailSender { if ($heskSettings['smtp']) { $mailer->isSMTP(); $mailer->SMTPAuth = true; + + //-- We'll set this explicitly below if the user has it enabled. + $mailer->SMTPAutoTLS = false; + if ($heskSettings['smtp_ssl']) { $mailer->SMTPSecure = "ssl"; } elseif ($heskSettings['smtp_tls']) { From 84f491bd40e9fc2bd04ee1c18578924a6eb91c54 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 30 Jul 2017 15:05:53 -0400 Subject: [PATCH 005/248] Don't fail resending email when there is no owner --- api/BusinessLogic/Emails/EmailTemplateParser.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/BusinessLogic/Emails/EmailTemplateParser.php b/api/BusinessLogic/Emails/EmailTemplateParser.php index 4fbc3e65..e53a03b2 100644 --- a/api/BusinessLogic/Emails/EmailTemplateParser.php +++ b/api/BusinessLogic/Emails/EmailTemplateParser.php @@ -190,7 +190,9 @@ class EmailTemplateParser { $defaultStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::NEW_TICKET, $heskSettings); $statusName = hesk_msgToPlain($defaultStatus->localizedNames[$language]); $category = hesk_msgToPlain($this->categoryGateway->getAllCategories($heskSettings)[$ticket->categoryId]->name); - $owner = hesk_msgToPlain($this->userGateway->getUserById($ticket->ownerId, $heskSettings)->name); + $owner = $this->userGateway->getUserById($ticket->ownerId, $heskSettings); + + $ownerName = $owner === null ? $hesklang['unas'] : hesk_msgToPlain($owner->name); switch ($ticket->priorityId) { case Priority::CRITICAL: @@ -219,7 +221,7 @@ class EmailTemplateParser { $msg = str_replace('%%SITE_URL%%', $heskSettings['site_url'], $msg); $msg = str_replace('%%CATEGORY%%', $category, $msg); $msg = str_replace('%%PRIORITY%%', $priority, $msg); - $msg = str_replace('%%OWNER%%', $owner, $msg); + $msg = str_replace('%%OWNER%%', $ownerName, $msg); $msg = str_replace('%%STATUS%%', $statusName, $msg); $msg = str_replace('%%EMAIL%%', implode(';',$ticket->email), $msg); $msg = str_replace('%%CREATED%%', $ticket->dateCreated, $msg); From 73b3a01bc0470bf38ef80a552ca13d8f8e202bc6 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 10 Aug 2017 21:51:59 -0400 Subject: [PATCH 006/248] Version checks are now asynchronous --- admin/admin_settings.php | 299 ++++++------------ .../System/HeskVersionController.php | 56 ++++ api/index.php | 82 +++-- 3 files changed, 218 insertions(+), 219 deletions(-) create mode 100644 api/Controllers/System/HeskVersionController.php diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 6f686d97..fcf24ec4 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -355,86 +355,121 @@ $modsForHesk_settings = mfh_getSettings(); : - - + - ' . $hesklang['hud'] . ' '; - } elseif ($latest != -1) { - // Is this a beta/dev version? - if (strpos($hesk_settings['hesk_version'], 'beta') || strpos($hesk_settings['hesk_version'], 'dev') || strpos($hesk_settings['hesk_version'], 'RC')) { - echo ' ' . $hesklang['beta'] . ' '; ?> ' . $hesklang['hnw'] . ' '; ?> - - + - + + + + + + + + + - + target="_blank"> + : - - + - ' . $hesklang['beta'] . ' '; ?> ' . $hesklang['mfh_up_to_date'] . ''; - } else { - ?> - - - + - + + + + + + + + - - + + @@ -3935,130 +3970,6 @@ $modsForHesk_settings = mfh_getSettings(); } - function hesk_checkVersion() - { - global $hesk_settings; - - if ($latest = hesk_getLatestVersion()) { - if (strlen($latest) > 12) { - return -1; - } elseif ($latest == $hesk_settings['hesk_version']) { - return true; - } else { - return $latest; - } - } else { - return -1; - } - - } // END hesk_checkVersion() - - - function hesk_getLatestVersion() - { - global $hesk_settings; - - // Do we have a cached version file? - if (file_exists(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt')) { - if (preg_match('/^(\d+)\|([\d.]+)+$/', @file_get_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt'), $matches) && (time() - intval($matches[1])) < 3600) { - return $matches[2]; - } - } - - // No cached file or older than 3600 seconds, try to get an update - $hesk_version_url = 'https://hesk.com/version'; - - // Try using cURL - if (function_exists('curl_init')) { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $hesk_version_url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6); - $latest = curl_exec($ch); - curl_close($ch); - return hesk_cacheLatestVersion($latest); - } - - // Try using a simple PHP function instead - if ($latest = @file_get_contents($hesk_version_url)) { - return hesk_cacheLatestVersion($latest); - } - - // Can't check automatically, will need a manual check - return false; - - } // END hesk_getLatestVersion() - - function hesk_cacheLatestVersion($latest) - { - global $hesk_settings; - - @file_put_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt', time() . '|' . $latest); - - return $latest; - - } // END hesk_cacheLatestVersion() - - function hesk_checkMfhVersion($currentVersion) - { - if ($latest = hesk_getMfhLatestVersion()) { - if (strlen($latest) > 12) { - return -1; - } elseif ($latest == $currentVersion) { - return true; - } else { - return $latest; - } - } else { - return -1; - } - } - - function hesk_getMfhLatestVersion() - { - global $hesk_settings; - - // Do we have a cached version file? - if (file_exists(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest-mfh.txt')) { - if (preg_match('/^(\d+)\|([\d.]+)+$/', @file_get_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest-mfh.txt'), $matches) && (time() - intval($matches[1])) < 3600) { - return $matches[2]; - } - } - - // No cached file or older than 3600 seconds, try to get an update - $hesk_version_url = 'http://mods-for-hesk.mkochcs.com/latestversion.php'; - - // Try using cURL - if (function_exists('curl_init')) { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $hesk_version_url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6); - $latest = curl_exec($ch); - curl_close($ch); - return hesk_cacheMfhLatestVersion($latest); - } - - // Try using a simple PHP function instead - if ($latest = file_get_contents($hesk_version_url)) { - return hesk_cacheMfhLatestVersion($latest); - } - - // Can't check automatically, will need a manual check - return false; - } - - function hesk_cacheMfhLatestVersion($latest) - { - global $hesk_settings; - - @file_put_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest-mfh.txt', time() . '|' . $latest); - - return $latest; - - } - - function hesk_testLanguage($return_options = 0) { global $hesk_settings, $hesklang, $modsForHesk_settings; diff --git a/api/Controllers/System/HeskVersionController.php b/api/Controllers/System/HeskVersionController.php new file mode 100644 index 00000000..c07122ed --- /dev/null +++ b/api/Controllers/System/HeskVersionController.php @@ -0,0 +1,56 @@ + $matches[2])); + } + + // Try using cURL + if (function_exists('curl_init')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6); + $latest = curl_exec($ch); + curl_close($ch); + + self::cacheLatestVersion($latest, $fileName, $hesk_settings); + + return output(array('version' => $latest)); + } + + // Try using a simple PHP function instead + if ($latest = @file_get_contents($url)) { + self::cacheLatestVersion($latest, $fileName, $hesk_settings); + + return output(array('version' => $latest)); + } + + // Can't check automatically, will need a manual check + return http_response_code(408); + } + + private static function cacheLatestVersion($latest, $fileName, $hesk_settings) { + @file_put_contents(__DIR__ . '/../../../' . $hesk_settings['cache_dir'] . '/' . $fileName, + time() . '|' . $latest); + } +} \ No newline at end of file diff --git a/api/index.php b/api/index.php index 672bbf8b..63879505 100644 --- a/api/index.php +++ b/api/index.php @@ -15,26 +15,37 @@ function handle404() { ), 404); } -function before() { - if (defined('HESK_DEMO') && $_SERVER['REQUEST_METHOD'] !== 'GET') { +function globalBefore() { + if (defined('HESK_DEMO') && $_SERVER['REQUEST_METHOD'] === 'GET') { print_error('Demo Mode', 'Only read-only commands are available in demo mode!', null, 401); die(); } +} + +function internalHandler() { + buildUserContextFromSession(); +} +function authTokenHandler() { + assertApiIsEnabled(); + $token = \BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN'); + buildUserContext($token); +} + +function internalOrAuthHandler() { $internalUse = \BusinessLogic\Helpers::getHeader('X-INTERNAL-CALL'); if ($internalUse === 'true') { - buildUserContextFromSession(); - } elseif (preg_match('/\/v1\/tickets\/.+\/attachments\/\d+/', $_SERVER['PATH_INFO'])) { - //-- TODO Clean this up - return; + internalHandler(); } else { - assertApiIsEnabled(); - $token = \BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN'); - buildUserContext($token); + authTokenHandler(); } } +function publicHandler() { + //-- No-op +} + function assertApiIsEnabled() { global $applicationContext, $hesk_settings; @@ -172,34 +183,55 @@ function fatalErrorShutdownHandler() { } } -Link::before('before'); +Link::before('globalBefore'); Link::all(array( // Categories - '/v1/categories' => [\Controllers\Categories\CategoryController::class . '::printAllCategories'], - '/v1/categories/{i}' => \Controllers\Categories\CategoryController::class, + '/v1/categories' => action(\Controllers\Categories\CategoryController::class . '::printAllCategories'), + '/v1/categories/{i}' => action(\Controllers\Categories\CategoryController::class), // Tickets - '/v1/tickets' => \Controllers\Tickets\CustomerTicketController::class, + '/v1/tickets' => action(\Controllers\Tickets\CustomerTicketController::class), // Tickets - Staff - '/v1/staff/tickets/{i}' => \Controllers\Tickets\StaffTicketController::class, + '/v1/staff/tickets/{i}' => action(\Controllers\Tickets\StaffTicketController::class), // Attachments - '/v1/tickets/{a}/attachments/{i}' => \Controllers\Attachments\PublicAttachmentController::class . '::getRaw', - '/v1/staff/tickets/{i}/attachments' => \Controllers\Attachments\StaffTicketAttachmentsController::class, - '/v1/staff/tickets/{i}/attachments/{i}' => \Controllers\Attachments\StaffTicketAttachmentsController::class, + '/v1/tickets/{a}/attachments/{i}' => action(\Controllers\Attachments\PublicAttachmentController::class . '::getRaw'), + '/v1/staff/tickets/{i}/attachments' => action(\Controllers\Attachments\StaffTicketAttachmentsController::class), + '/v1/staff/tickets/{i}/attachments/{i}' => action(\Controllers\Attachments\StaffTicketAttachmentsController::class), // Statuses - '/v1/statuses' => \Controllers\Statuses\StatusController::class, + '/v1/statuses' => action(\Controllers\Statuses\StatusController::class), // Settings - '/v1/settings' => \Controllers\Settings\SettingsController::class, + '/v1/settings' => action(\Controllers\Settings\SettingsController::class), /* Internal use only routes */ // Resend email response - '/v1-internal/staff/tickets/{i}/resend-email' => \Controllers\Tickets\ResendTicketEmailToCustomerController::class, + '/v1-internal/staff/tickets/{i}/resend-email' => + action(\Controllers\Tickets\ResendTicketEmailToCustomerController::class, SecurityHandler::INTERNAL), // Custom Navigation - '/v1-internal/custom-navigation/all' => \Controllers\Navigation\CustomNavElementController::class . '::getAll', - '/v1-internal/custom-navigation' => \Controllers\Navigation\CustomNavElementController::class, - '/v1-internal/custom-navigation/{i}' => \Controllers\Navigation\CustomNavElementController::class, - '/v1-internal/custom-navigation/{i}/sort/{s}' => \Controllers\Navigation\CustomNavElementController::class . '::sort', + '/v1-internal/custom-navigation/all' => + action(\Controllers\Navigation\CustomNavElementController::class . '::getAll', SecurityHandler::INTERNAL), + '/v1-internal/custom-navigation' => + action(\Controllers\Navigation\CustomNavElementController::class, SecurityHandler::INTERNAL), + '/v1-internal/custom-navigation/{i}' => + action(\Controllers\Navigation\CustomNavElementController::class, SecurityHandler::INTERNAL), + '/v1-internal/custom-navigation/{i}/sort/{s}' => + action(\Controllers\Navigation\CustomNavElementController::class . '::sort', SecurityHandler::INTERNAL), + + '/v1-public/hesk-version' => + action(\Controllers\System\HeskVersionController::class . '::getHeskVersion', SecurityHandler::OPEN), + '/v1-public/mods-for-hesk-version' => + action(\Controllers\System\HeskVersionController::class . '::getModsForHeskVersion', SecurityHandler::OPEN), // Any URL that doesn't match goes to the 404 handler '404' => 'handle404' -)); \ No newline at end of file +)); + +function action($class, $securityHandler = SecurityHandler::AUTH_TOKEN) { + return [$class, $class, $securityHandler]; +} + +class SecurityHandler { + const OPEN = 'publicHandler'; + const INTERNAL = 'internalHandler'; + const AUTH_TOKEN = 'authTokenHandler'; + const INTERNAL_OR_AUTH_TOKEN = 'internalOrAuthHandler'; +} \ No newline at end of file From 65576d5c4333464102d272c70798f850a8846b50 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 12 Aug 2017 21:41:41 -0400 Subject: [PATCH 007/248] Fix document type on IE intranet pages --- inc/header.inc.php | 1 + inc/headerAdmin.inc.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/inc/header.inc.php b/inc/header.inc.php index ca27118b..f35f50fa 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -43,6 +43,7 @@ if (is_dir(HESK_PATH . 'install')) { $modsForHesk_settings = mfh_getSettings(); } +header('X-UA-Compatible: IE=edge'); ?> diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index ce2f0f1d..20501baa 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -21,6 +21,8 @@ if (!defined('IN_SCRIPT')) { define('ADMIN_PAGE', true); $modsForHesk_settings = mfh_getSettings(); + +header('X-UA-Compatible: IE=edge'); ?> From c60d2ed8662b9224fd6ee77935afafc7dc3ed289 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 12 Aug 2017 21:57:41 -0400 Subject: [PATCH 008/248] Update installer --- install/install_functions.inc.php | 2 +- install/mods-for-hesk/ajax/install-database-ajax.php | 2 ++ install/mods-for-hesk/installModsForHesk.php | 1 + install/mods-for-hesk/js/version-scripts.js | 3 +++ install/mods-for-hesk/modsForHesk.php | 1 + install/mods-for-hesk/sql/installSql.php | 7 +++++++ 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/install/install_functions.inc.php b/install/install_functions.inc.php index 864e6dc8..a498ab67 100644 --- a/install/install_functions.inc.php +++ b/install/install_functions.inc.php @@ -16,7 +16,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} // We will be installing this HESK version: define('HESK_NEW_VERSION','2.7.3'); -define('MODS_FOR_HESK_NEW_VERSION','3.1.0'); +define('MODS_FOR_HESK_NEW_VERSION','3.1.1'); define('REQUIRE_PHP_VERSION','5.3.0'); define('REQUIRE_MYSQL_VERSION','5.0.7'); diff --git a/install/mods-for-hesk/ajax/install-database-ajax.php b/install/mods-for-hesk/ajax/install-database-ajax.php index e28169ec..77aed493 100644 --- a/install/mods-for-hesk/ajax/install-database-ajax.php +++ b/install/mods-for-hesk/ajax/install-database-ajax.php @@ -90,6 +90,8 @@ if ($version == 2) { execute307Scripts(); } elseif ($version == 42) { execute310Scripts(); +} elseif ($version == 43) { + execute311Scripts(); } else { $response = 'The version "' . $version . '" was not recognized. Check the value submitted and try again.'; print $response; diff --git a/install/mods-for-hesk/installModsForHesk.php b/install/mods-for-hesk/installModsForHesk.php index cc89aaf4..cae36a82 100644 --- a/install/mods-for-hesk/installModsForHesk.php +++ b/install/mods-for-hesk/installModsForHesk.php @@ -51,6 +51,7 @@ $buildToVersionMap = array( 40 => '3.0.6', 41 => '3.0.7', 42 => '3.1.0', + 43 => '3.1.1', ); function echoInitialVersionRows($version, $build_to_version_map) diff --git a/install/mods-for-hesk/js/version-scripts.js b/install/mods-for-hesk/js/version-scripts.js index 68a83e12..a7a9d1fc 100644 --- a/install/mods-for-hesk/js/version-scripts.js +++ b/install/mods-for-hesk/js/version-scripts.js @@ -122,6 +122,9 @@ function processUpdates(startingVersion) { } else if (startingVersion < 42) { startVersionUpgrade('310'); executeUpdate(42, '310', '3.1.0'); + } else if (startingVersion < 43) { + startVersionUpgrade('311'); + executeUpdate(43, '311', '3.1.1'); } else { installationFinished(); } diff --git a/install/mods-for-hesk/modsForHesk.php b/install/mods-for-hesk/modsForHesk.php index 386a53ff..4496bc49 100644 --- a/install/mods-for-hesk/modsForHesk.php +++ b/install/mods-for-hesk/modsForHesk.php @@ -118,6 +118,7 @@ hesk_dbConnect(); buildCategoryFromJson($data); - $category->id = $id; + $category->id = intval($id); /* @var $categoryHandler CategoryHandler */ $categoryHandler = $applicationContext->get[CategoryHandler::class]; diff --git a/api/index.php b/api/index.php index 25b77ee3..ffaf590d 100644 --- a/api/index.php +++ b/api/index.php @@ -188,8 +188,8 @@ Link::before('globalBefore'); Link::all(array( // Categories '/v1/categories/all' => action(\Controllers\Categories\CategoryController::class . '::printAllCategories', [RequestMethod::GET], SecurityHandler::INTERNAL_OR_AUTH_TOKEN), - '/v1/categories' => action(\Controllers\Categories\CategoryController::class, [RequestMethod::POST]), - '/v1/categories/{i}' => action(\Controllers\Categories\CategoryController::class, [RequestMethod::GET, RequestMethod::PUT, RequestMethod::DELETE]), + '/v1/categories' => action(\Controllers\Categories\CategoryController::class, [RequestMethod::POST], SecurityHandler::INTERNAL_OR_AUTH_TOKEN), + '/v1/categories/{i}' => action(\Controllers\Categories\CategoryController::class, [RequestMethod::GET, RequestMethod::PUT, RequestMethod::DELETE], SecurityHandler::INTERNAL_OR_AUTH_TOKEN), // Tickets '/v1/tickets' => action(\Controllers\Tickets\CustomerTicketController::class), // Tickets - Staff diff --git a/internal-api/js/manage-categories.js b/internal-api/js/manage-categories.js index a7716ad7..077eb423 100644 --- a/internal-api/js/manage-categories.js +++ b/internal-api/js/manage-categories.js @@ -62,9 +62,10 @@ function loadTable() { // Low $priority.text(mfhLang.text('low')).addClass('normal'); } + var linkPattern = $('input[name="show-tickets-path"]').val(); $template.find('a[data-property="number-of-tickets"]') .text(this.numberOfTickets) - .attr('href', '#' + this.numberOfTickets); + .attr('href', linkPattern.replace('{0}', this.id)); var percentText = mfhLang.text('perat'); var percentage = Math.round(this.numberOfTickets / totalNumberOfTickets * 100); $template.find('div.progress').attr('title', percentText.replace('%s', percentage + '%')); @@ -165,6 +166,9 @@ function bindEditModal() { $modal.find('input[name="foreground-color"]') .colorpicker(colorpickerOptions).end().modal('show'); $modal.find('input[name="cat-order"]').val(element.catOrder); + $modal.find('input[name="autoassign"]').val(element.autoAssign); + $modal.find('input[name="type"]').val(element.type); + $modal.find('textarea[name="description"]').val(element.description === null ? '' : element.description); $modal.modal('show'); }); @@ -189,16 +193,16 @@ function bindFormSubmit() { var $modal = $('#category-modal'); var data = { - autoassign: $modal.find('input[name="autoassign"]').val(), + autoassign: $modal.find('input[name="autoassign"]').val() === 'true', backgroundColor: $modal.find('input[name="background-color"]').val(), description: $modal.find('textarea[name="description"]').val(), - displayBorder: $modal.find('input[name="display-border"]:checked').val(), - foregroundColor: $modal.find('input[name="foreground-color"]').val() === '' ? 'AUTO' : $modal.find('input[name="foreground-color"]'), + displayBorder: $modal.find('input[name="display-border"]:checked').val() === '1', + foregroundColor: $modal.find('input[name="foreground-color"]').val() === '' ? 'AUTO' : $modal.find('input[name="foreground-color"]').val(), name: $modal.find('input[name="name"]').val(), - priority: $modal.find('select[name="priority"]').val(), - type: $modal.find('input[name="type"]').val(), - usage: $modal.find('select[name="usage"]').val(), - catOrder: $modal.find('input[name="cat-order"]').val() + priority: parseInt($modal.find('select[name="priority"]').val()), + type: parseInt($modal.find('input[name="type"]').val()), + usage: parseInt($modal.find('select[name="usage"]').val()), + catOrder: parseInt($modal.find('input[name="cat-order"]').val()) }; var url = heskUrl + 'api/index.php/v1/categories/'; @@ -206,16 +210,14 @@ function bindFormSubmit() { var categoryId = $modal.find('input[name="id"]').val(); if (categoryId !== -1) { - url += id; + url += categoryId; method = 'PUT'; } $modal.find('#action-buttons').find('.cancel-button').attr('disabled', 'disabled'); $modal.find('#action-buttons').find('.save-button').attr('disabled', 'disabled'); - console.log('') - - /*$.ajax({ + $.ajax({ method: 'POST', url: url, headers: { @@ -224,7 +226,7 @@ function bindFormSubmit() { }, data: JSON.stringify(data), success: function(data) { - if (id === -1) { + if (categoryId === -1) { mfhAlert.success('CREATED'); } else { mfhAlert.success('SAVED'); @@ -240,6 +242,6 @@ function bindFormSubmit() { $modal.find('#action-buttons').find('.cancel-button').removeAttr('disabled'); $modal.find('#action-buttons').find('.save-button').removeAttr('disabled'); } - });*/ + }); }); } \ No newline at end of file From 24cdb08449d60f5d7076b8aa336f474ca1b4083b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 30 Aug 2017 22:03:51 -0400 Subject: [PATCH 029/248] Categories can be created, modify modal --- admin/manage_categories.php | 89 ++++++++++++++++++++-------- internal-api/js/manage-categories.js | 74 ++++++++++++++++++++++- language/en/text.php | 3 + 3 files changed, 140 insertions(+), 26 deletions(-) diff --git a/admin/manage_categories.php b/admin/manage_categories.php index b90caebb..ad504c95 100644 --- a/admin/manage_categories.php +++ b/admin/manage_categories.php @@ -297,17 +297,18 @@ $res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix'])
- - \ No newline at end of file From 109a4fa25feb962e18d48aeb98ae1b2990582702 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 20 Oct 2017 13:07:01 -0400 Subject: [PATCH 121/248] Uninstaller works --- install/database-validation.php | 4 ++-- install/js/install-script.js | 10 +++++----- install/js/uninstall-script.js | 16 ++++++++-------- install/uninstall.php | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/install/database-validation.php b/install/database-validation.php index 4eaf4c8a..e7ae6853 100644 --- a/install/database-validation.php +++ b/install/database-validation.php @@ -31,7 +31,7 @@ hesk_dbConnect();
+
+ +
-
-
-

-
-
-
-
- +
+
+
+
+ +
+
+ +
+ diff --git a/language/en/text.php b/language/en/text.php index 0de8b91c..a994fc6c 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -2238,6 +2238,7 @@ $hesklang['show_event_start_time_help'] = 'Always show the start time on event t $hesklang['highlight_ticket_rows_based_on_priority'] = 'Highlight ticket rows based on priority'; $hesklang['highlight_ticket_rows_based_on_priority_help'] = 'If enabled, each ticket on the tickets page will be highlighted based on priority. If disabled, only * Critical * and High priority tickets will be highlighted.'; $hesklang['highlight_ticket_rows_based_on_priority_descr'] = 'Highlight all ticket rows based on priority'; +$hesklang['protected_group'] = 'This is a protected group; you cannot change accessible categories / features.'; // DO NOT CHANGE BELOW if (!defined('IN_SCRIPT')) die('PHP syntax OK!'); From 48b28fc3cdfdcb7d27ce39c2599a3947d66a5397 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 7 Feb 2018 22:03:55 -0500 Subject: [PATCH 230/248] Only modify permissions the user has access to --- admin/manage_permission_groups.php | 36 +++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/admin/manage_permission_groups.php b/admin/manage_permission_groups.php index 4220ea3d..9eb410a0 100644 --- a/admin/manage_permission_groups.php +++ b/admin/manage_permission_groups.php @@ -365,7 +365,6 @@ function save() WHERE `id` = " . intval($templateId)); $row = hesk_dbFetchAssoc($res); - // Add 'can ban emails' if 'can unban emails' is set (but not added). Same with 'can ban ips' $catArray = hesk_POST_array('categories'); $featArray = hesk_POST_array('features'); @@ -380,6 +379,41 @@ function save() $features = implode(',', $featArray); $name = hesk_POST('name'); + // Only allow users to add what they are allowed to add + // Admins can handle anything + if (!$_SESSION['isadmin']) { + // Update categories based on user visibility + $originalCategories = explode(',', $row['categories']); + $newCategories = array(); + foreach ($originalCategories as $innerCategory) { + if (in_array($innerCategory, $catArray) && in_array($innerCategory, $_SESSION['categories'])) { + $newCategories[] = $innerCategory; + } elseif (!in_array($innerCategory, $catArray) && !in_array($innerCategory, $_SESSION['categories'])) { + // The user can't modify this, so keep it in + $newCategories[] = $innerCategory; + } + // If neither, the user removed it. + } + + // Update features based on user visibility + $originalFeatures = explode(',', $row['features']); + $newFeatures = array(); + foreach ($originalFeatures as $innerFeature) { + if (in_array($innerFeature, $featArray) && strpos($_SESSION['heskprivileges'], $innerFeature) !== false) { + $newFeatures[] = $innerFeature; + } elseif (!in_array($innerFeature, $featArray) && strpos($_SESSION['heskprivileges'], $innerFeature) === false) { + // The user can't modify this, so keep it in + $newFeatures[] = $innerFeature; + } + // If neither, the user removed it. + } + + $categories = implode(',', $newCategories); + $features = implode(',', $newFeatures); + } + + + hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "permission_templates` SET `categories` = '" . hesk_dbEscape($categories) . "', `heskprivileges` = '" . hesk_dbEscape($features) . "', `name` = '" . hesk_dbEscape($name) . "' From 35ed664dfdef0ea48600b134a8030c08196a35d4 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 11 Feb 2018 22:00:44 -0500 Subject: [PATCH 231/248] Only allow users to modify permissions that they have access to --- admin/manage_permission_groups.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/manage_permission_groups.php b/admin/manage_permission_groups.php index 9eb410a0..9b9449ac 100644 --- a/admin/manage_permission_groups.php +++ b/admin/manage_permission_groups.php @@ -198,7 +198,7 @@ function createEditModal($template, $features, $categories) $disabled = ' disabled'; }?> - +