From 39e61b85c46643aa1ae508e568513391701de1ee Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 4 Dec 2017 12:56:09 -0500 Subject: [PATCH] Fixed some issues with the service messages endpoints: --- .../MissingAuthenticationTokenException.php | 4 +- api/BusinessLogic/Security/UserContext.php | 4 ++ .../GetServiceMessagesFilter.php | 12 ++++++ .../ServiceMessages/ServiceMessageHandler.php | 8 ++-- .../ServiceMessagesController.php | 38 +++++++++++++++---- .../ServiceMessagesGateway.php | 31 +++++++++++++-- api/index.php | 13 +++++-- 7 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 api/BusinessLogic/ServiceMessages/GetServiceMessagesFilter.php diff --git a/api/BusinessLogic/Exceptions/MissingAuthenticationTokenException.php b/api/BusinessLogic/Exceptions/MissingAuthenticationTokenException.php index 596839ff..267a82c0 100644 --- a/api/BusinessLogic/Exceptions/MissingAuthenticationTokenException.php +++ b/api/BusinessLogic/Exceptions/MissingAuthenticationTokenException.php @@ -4,8 +4,8 @@ namespace BusinessLogic\Exceptions; class MissingAuthenticationTokenException extends ApiFriendlyException { function __construct() { - parent::__construct("An 'X-Auth-Token' is required for all requests", + parent::__construct("An 'X-Auth-Token' is required for this request", 'Security Exception', - 400); + 401); } } \ No newline at end of file diff --git a/api/BusinessLogic/Security/UserContext.php b/api/BusinessLogic/Security/UserContext.php index 3055b4ff..6ce0fba0 100644 --- a/api/BusinessLogic/Security/UserContext.php +++ b/api/BusinessLogic/Security/UserContext.php @@ -57,6 +57,10 @@ class UserContext extends \BaseClass { /* @var $active bool */ public $active; + function isAnonymousUser() { + return $this->id === -1; + } + static function buildAnonymousUser() { $userContext = new UserContext(); $userContext->id = -1; diff --git a/api/BusinessLogic/ServiceMessages/GetServiceMessagesFilter.php b/api/BusinessLogic/ServiceMessages/GetServiceMessagesFilter.php new file mode 100644 index 00000000..a8f381d6 --- /dev/null +++ b/api/BusinessLogic/ServiceMessages/GetServiceMessagesFilter.php @@ -0,0 +1,12 @@ +serviceMessageGateway->createServiceMessage($serviceMessage, $heskSettings); } - function getServiceMessages($heskSettings) { - return $this->serviceMessageGateway->getServiceMessages($heskSettings); + function getServiceMessages($heskSettings, $searchFilter) { + return $this->serviceMessageGateway->getServiceMessages($heskSettings, $searchFilter); } function editServiceMessage($serviceMessage, $heskSettings) { @@ -78,7 +78,7 @@ class ServiceMessageHandler extends \BaseClass { } function sortServiceMessage($id, $direction, $heskSettings) { - $serviceMessages = $this->serviceMessageGateway->getServiceMessages($heskSettings); + $serviceMessages = $this->serviceMessageGateway->getServiceMessages($heskSettings, new GetServiceMessagesFilter()); $serviceMessage = null; foreach ($serviceMessages as $innerServiceMessage) { if (intval($innerServiceMessage->id) === intval($id)) { @@ -129,7 +129,7 @@ class ServiceMessageHandler extends \BaseClass { break; } } - if (!$languageFound) { + if (!$languageFound && !in_array('MISSING_LANGUAGE', $validationModel->errorKeys)) { $validationModel->errorKeys[] = 'LANGUAGE_NOT_INSTALLED'; } diff --git a/api/Controllers/ServiceMessages/ServiceMessagesController.php b/api/Controllers/ServiceMessages/ServiceMessagesController.php index b147f123..48da1a7d 100644 --- a/api/Controllers/ServiceMessages/ServiceMessagesController.php +++ b/api/Controllers/ServiceMessages/ServiceMessagesController.php @@ -6,6 +6,7 @@ use BusinessLogic\Exceptions\ApiFriendlyException; use BusinessLogic\Helpers; use BusinessLogic\Security\UserContext; use BusinessLogic\Security\UserPrivilege; +use BusinessLogic\ServiceMessages\GetServiceMessagesFilter; use BusinessLogic\ServiceMessages\ServiceMessage; use BusinessLogic\ServiceMessages\ServiceMessageHandler; use Controllers\ControllerWithSecurity; @@ -17,25 +18,41 @@ class ServiceMessagesController extends \BaseClass { * @throws ApiFriendlyException */ function checkSecurity($userContext) { - if (!in_array(UserPrivilege::CAN_MANAGE_SERVICE_MESSAGES, $userContext->permissions)) { + if (!$userContext->admin && !in_array(UserPrivilege::CAN_MANAGE_SERVICE_MESSAGES, $userContext->permissions)) { + throw new ApiFriendlyException("User does not have permission to access the following URI: " . $_SERVER['REQUEST_URI'], "Access Forbidden", 403); + } + } + + static function staticCheckSecurity($userContext) { + if (!$userContext->admin && !in_array(UserPrivilege::CAN_MANAGE_SERVICE_MESSAGES, $userContext->permissions)) { throw new ApiFriendlyException("User does not have permission to access the following URI: " . $_SERVER['REQUEST_URI'], "Access Forbidden", 403); } } function get() { + /* @var $userContext UserContext */ + /* @var $hesk_settings array */ global $applicationContext, $hesk_settings, $userContext; - $this->checkSecurity($userContext); + $searchFilter = new GetServiceMessagesFilter(); + if ($userContext->isAnonymousUser()) { + $searchFilter->includeDrafts = false; + $searchFilter->includeStaffServiceMessages = false; + } elseif (!$userContext->admin && !in_array(UserPrivilege::CAN_MANAGE_SERVICE_MESSAGES, $userContext->permissions)) { + $searchFilter->includeDrafts = false; + } /* @var $handler ServiceMessageHandler */ $handler = $applicationContext->get(ServiceMessageHandler::clazz()); - return output($handler->getServiceMessages($hesk_settings)); + return output($handler->getServiceMessages($hesk_settings, $searchFilter)); } function post() { global $applicationContext, $userContext, $hesk_settings; + $this->checkSecurity($userContext); + /* @var $handler ServiceMessageHandler */ $handler = $applicationContext->get(ServiceMessageHandler::clazz()); @@ -46,7 +63,9 @@ class ServiceMessagesController extends \BaseClass { } function put($id) { - global $applicationContext, $hesk_settings; + global $applicationContext, $hesk_settings, $userContext; + + $this->checkSecurity($userContext); /* @var $handler ServiceMessageHandler */ $handler = $applicationContext->get(ServiceMessageHandler::clazz()); @@ -60,7 +79,9 @@ class ServiceMessagesController extends \BaseClass { } function delete($id) { - global $applicationContext, $hesk_settings; + global $applicationContext, $hesk_settings, $userContext; + + $this->checkSecurity($userContext); /* @var $handler ServiceMessageHandler */ $handler = $applicationContext->get(ServiceMessageHandler::clazz()); @@ -79,7 +100,7 @@ class ServiceMessagesController extends \BaseClass { $serviceMessage = new ServiceMessage(); if (!$creating) { - $serviceMessage->order = $data['order']; + $serviceMessage->order = Helpers::safeArrayGet($data, 'order'); } if ($creating) { @@ -105,7 +126,10 @@ class ServiceMessagesController extends \BaseClass { } static function sort($id, $direction) { - global $applicationContext, $hesk_settings; + /* @var $userContext UserContext */ + global $applicationContext, $hesk_settings, $userContext; + + self::staticCheckSecurity($userContext); /* @var $handler ServiceMessageHandler */ $handler = $applicationContext->get(ServiceMessageHandler::clazz()); diff --git a/api/DataAccess/ServiceMessages/ServiceMessagesGateway.php b/api/DataAccess/ServiceMessages/ServiceMessagesGateway.php index d9d8985a..e15a593e 100644 --- a/api/DataAccess/ServiceMessages/ServiceMessagesGateway.php +++ b/api/DataAccess/ServiceMessages/ServiceMessagesGateway.php @@ -3,7 +3,9 @@ namespace DataAccess\ServiceMessages; +use BusinessLogic\ServiceMessages\GetServiceMessagesFilter; use BusinessLogic\ServiceMessages\ServiceMessage; +use BusinessLogic\ServiceMessages\ServiceMessageLocation; use BusinessLogic\ServiceMessages\ServiceMessageStyle; use DataAccess\CommonDao; @@ -56,14 +58,29 @@ class ServiceMessagesGateway extends CommonDao { /** * @param $heskSettings + * @param $searchFilter GetServiceMessagesFilter * @return ServiceMessage[] */ - function getServiceMessages($heskSettings) { + function getServiceMessages($heskSettings, $searchFilter) { $this->init(); $serviceMessages = array(); - $rs = hesk_dbQuery("SELECT * FROM `". hesk_dbEscape($heskSettings['db_pfix']) . "service_messages` ORDER BY `order`"); + $sql = "SELECT DISTINCT `service_messages`.* FROM `". hesk_dbEscape($heskSettings['db_pfix']) . "service_messages` AS `service_messages` "; + + if (!$searchFilter->includeStaffServiceMessages) { + $sql .= "INNER JOIN `" . hesk_dbEscape($heskSettings['db_pfix']) . "mfh_service_message_to_location` AS `location` + ON `location`.`service_message_id` = `service_messages`.`id` AND `location`.`location` LIKE 'CUSTOMER%' "; + } + + if (!$searchFilter->includeDrafts) { + $sql .= "WHERE `type` = '0' "; + } + + $sql .= "ORDER BY `order`"; + + + $rs = hesk_dbQuery($sql); while ($row = hesk_dbFetchAssoc($rs)) { $serviceMessage = new ServiceMessage(); $serviceMessage->id = $row['id']; @@ -78,8 +95,14 @@ class ServiceMessagesGateway extends CommonDao { $serviceMessage->language = $row['mfh_language']; $serviceMessage->locations = array(); - $locationsRs = hesk_dbQuery("SELECT `location` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "mfh_service_message_to_location` - WHERE `service_message_id` = " . intval($serviceMessage->id)); + $locationSql = "SELECT `location` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "mfh_service_message_to_location` + WHERE `service_message_id` = " . intval($serviceMessage->id); + + if (!$searchFilter->includeStaffServiceMessages) { + $locationSql .= " AND `location` LIKE 'CUSTOMER%'"; + } + + $locationsRs = hesk_dbQuery($locationSql); while ($innerRow = hesk_dbFetchAssoc($locationsRs)) { $serviceMessage->locations[] = $innerRow['location']; } diff --git a/api/index.php b/api/index.php index 8502e108..3a67c362 100644 --- a/api/index.php +++ b/api/index.php @@ -45,8 +45,15 @@ function internalOrAuthHandler() { function publicHandler() { global $userContext; - //-- Create an "anonymous" UserContext - $userContext = \BusinessLogic\Security\UserContext::buildAnonymousUser(); + // Check if we passed in a X-Auth-Token or X-Internal-Call header. Those take priority + if (\BusinessLogic\Helpers::getHeader('X-INTERNAL-CALL') === 'true') { + internalHandler(); + } elseif (\BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN') !== null) { + authTokenHandler(); + } else { + //-- Create an "anonymous" UserContext + $userContext = \BusinessLogic\Security\UserContext::buildAnonymousUser(); + } } function assertApiIsEnabled() { @@ -205,7 +212,7 @@ Link::all(array( // Service Messages '/v1/service-messages' => action(\Controllers\ServiceMessages\ServiceMessagesController::clazz(), array(RequestMethod::GET, RequestMethod::POST), - SecurityHandler::INTERNAL_OR_AUTH_TOKEN), + SecurityHandler::OPEN), '/v1/service-messages/{i}' => action(\Controllers\ServiceMessages\ServiceMessagesController::clazz(), array(RequestMethod::PUT, RequestMethod::DELETE), SecurityHandler::INTERNAL_OR_AUTH_TOKEN),