diff --git a/api/BusinessLogic/Attachments/AttachmentHandler.php b/api/BusinessLogic/Attachments/AttachmentHandler.php index 343c13c1..333a5ec8 100644 --- a/api/BusinessLogic/Attachments/AttachmentHandler.php +++ b/api/BusinessLogic/Attachments/AttachmentHandler.php @@ -6,6 +6,7 @@ namespace BusinessLogic\Attachments; use BusinessLogic\Exceptions\ApiFriendlyException; use BusinessLogic\Exceptions\ValidationException; use BusinessLogic\Security\UserContext; +use BusinessLogic\Security\UserPrivilege; use BusinessLogic\Security\UserToTicketChecker; use BusinessLogic\Tickets\Attachment; use BusinessLogic\Tickets\Ticket; @@ -54,7 +55,11 @@ class AttachmentHandler { $ticket = $this->ticketGateway->getTicketById($createAttachmentModel->ticketId, $heskSettings); - if (!$this->userToTicketChecker->isTicketWritableToUser($userContext, $ticket, $createAttachmentModel->isEditing, $heskSettings)) { + $extraPermissions = $createAttachmentModel->isEditing + ? array(UserPrivilege::CAN_EDIT_TICKETS) + : array(); + + if (!$this->userToTicketChecker->isTicketAccessibleToUser($userContext, $ticket, $heskSettings, $extraPermissions)) { throw new \Exception("User does not have access to ticket {$ticket->id} being created / edited!"); } @@ -81,14 +86,26 @@ class AttachmentHandler { return $ticketAttachment; } + /** + * Supports deleting attachments from both ticket messages AND replies + * + * @param $ticketId int The ticket ID + * @param $attachmentId int The attachment ID + * @param $userContext UserContext + * @param $heskSettings array + * @throws ApiFriendlyException + * @throws \Exception + */ function deleteAttachmentFromTicket($ticketId, $attachmentId, $userContext, $heskSettings) { $ticket = $this->ticketGateway->getTicketById($ticketId, $heskSettings); - if (!$this->userToTicketChecker->isTicketWritableToUser($userContext, $ticket, true, $heskSettings)) { + if (!$this->userToTicketChecker->isTicketAccessibleToUser($userContext, $ticket, $heskSettings, array(UserPrivilege::CAN_EDIT_TICKETS))) { throw new \Exception("User does not have access to ticket {$ticketId} being created / edited!"); } $indexToRemove = -1; + $attachmentType = AttachmentType::MESSAGE; + $replyId = -1; for ($i = 0; $i < count($ticket->attachments); $i++) { $attachment = $ticket->attachments[$i]; if ($attachment->id === $attachmentId) { @@ -97,13 +114,30 @@ class AttachmentHandler { } } - if ($indexToRemove === -1) { - throw new ApiFriendlyException("Attachment not found for ticket!", "Attachment not found", 404); + foreach ($ticket->replies as $reply) { + for ($i = 0; $i < count($reply->attachments); $i++) { + $attachment = $reply->attachments[$i]; + if ($attachment->id === $attachmentId) { + $indexToRemove = $i; + $replyId = $reply->id; + $attachmentType = AttachmentType::REPLY; + $this->fileDeleter->deleteFile($attachment->savedName, $heskSettings['attach_dir']); + } + } } - $attachments = $ticket->attachments; - unset($attachments[$indexToRemove]); - $this->ticketGateway->updateAttachmentsForTicket($ticketId, $attachments, $heskSettings); + if ($indexToRemove === -1) { + throw new ApiFriendlyException("Attachment not found for ticket or reply! ID: {$attachmentId}", "Attachment not found", 404); + } + + if ($attachmentType == AttachmentType::MESSAGE) { + $attachments = $ticket->attachments; + unset($attachments[$indexToRemove]); + $this->ticketGateway->updateAttachmentsForTicket($ticketId, $attachments, $heskSettings); + } else { + $attachments = $ticket->replies[$replyId]->attachments; + unset($attachments[$indexToRemove]); + } } /** diff --git a/api/BusinessLogic/Attachments/AttachmentRetriever.php b/api/BusinessLogic/Attachments/AttachmentRetriever.php index c4889206..cfdec67b 100644 --- a/api/BusinessLogic/Attachments/AttachmentRetriever.php +++ b/api/BusinessLogic/Attachments/AttachmentRetriever.php @@ -31,7 +31,7 @@ class AttachmentRetriever { function getAttachmentContentsForTicket($ticketId, $attachmentId, $userContext, $heskSettings) { $ticket = $this->ticketGateway->getTicketById($ticketId, $heskSettings); - if (!$this->userToTicketChecker->isTicketWritableToUser($userContext, $ticket, false, $heskSettings)) { + if (!$this->userToTicketChecker->isTicketAccessibleToUser($userContext, $ticket, $heskSettings)) { throw new \Exception("User does not have access to attachment {$attachmentId}!"); } diff --git a/api/BusinessLogic/Security/UserPrivilege.php b/api/BusinessLogic/Security/UserPrivilege.php index 4f2fb281..ad6064cc 100644 --- a/api/BusinessLogic/Security/UserPrivilege.php +++ b/api/BusinessLogic/Security/UserPrivilege.php @@ -13,4 +13,5 @@ class UserPrivilege { const CAN_VIEW_TICKETS = 'can_view_tickets'; const CAN_REPLY_TO_TICKETS = 'can_reply_tickets'; const CAN_EDIT_TICKETS = 'can_edit_tickets'; + const CAN_DELETE_TICKETS = 'can_del_tickets'; } \ No newline at end of file diff --git a/api/BusinessLogic/Security/UserToTicketChecker.php b/api/BusinessLogic/Security/UserToTicketChecker.php index 777bd200..3da75192 100644 --- a/api/BusinessLogic/Security/UserToTicketChecker.php +++ b/api/BusinessLogic/Security/UserToTicketChecker.php @@ -17,24 +17,34 @@ class UserToTicketChecker { /** * @param $user UserContext * @param $ticket Ticket - * @param $isEditing bool true if editing a ticket, false if creating * @param $heskSettings array + * @param $extraPermissions UserPrivilege[] additional privileges the user needs besides CAN_VIEW_TICKETS (if not an admin) + * for this to return true * @return bool */ - function isTicketWritableToUser($user, $ticket, $isEditing, $heskSettings) { - $hasAccess = $user->admin === true || - (in_array($ticket->categoryId, $user->categories) && - in_array(UserPrivilege::CAN_VIEW_TICKETS, $user->permissions)); - - if ($isEditing) { - $categoryManagerId = $this->userGateway->getManagerForCategory($ticket->categoryId, $heskSettings); - - $hasAccess = $hasAccess && - ($user->admin === true - || in_array(UserPrivilege::CAN_EDIT_TICKETS, $user->permissions) - || $categoryManagerId == $user->id); + function isTicketAccessibleToUser($user, $ticket, $heskSettings, $extraPermissions = array()) { + if ($user->admin === true) { + return true; } - return $hasAccess; + if (!in_array($ticket->categoryId, $user->categories)) { + return false; + } + + $categoryManagerId = $this->userGateway->getManagerForCategory($ticket->categoryId, $heskSettings); + + if ($user->id === $categoryManagerId) { + return true; + } + + $extraPermissions[] = UserPrivilege::CAN_VIEW_TICKETS; + + foreach ($extraPermissions as $permission) { + if (!in_array($permission, $user->permissions)) { + return false; + } + } + + return true; } } \ No newline at end of file diff --git a/api/BusinessLogic/Tickets/Ticket.php b/api/BusinessLogic/Tickets/Ticket.php index 2d7ba879..ea50b11e 100644 --- a/api/BusinessLogic/Tickets/Ticket.php +++ b/api/BusinessLogic/Tickets/Ticket.php @@ -127,7 +127,7 @@ class Ticket { $reply->isRead = $replyRow['read']; $reply->usesHtml = $replyRow['html']; - $replies[] = $reply; + $replies[$reply->id] = $reply; } $ticket->replies = $replies; diff --git a/api/BusinessLogic/Tickets/TicketDeleter.php b/api/BusinessLogic/Tickets/TicketDeleter.php new file mode 100644 index 00000000..6b181e4e --- /dev/null +++ b/api/BusinessLogic/Tickets/TicketDeleter.php @@ -0,0 +1,43 @@ +ticketGateway = $ticketGateway; + $this->userToTicketChecker = $userToTicketChecker; + $this->attachmentHandler = $attachmentHandler; + } + + function deleteTicket($ticketId, $userContext, $heskSettings) { + $ticket = $this->ticketGateway->getTicketById($ticketId, $heskSettings); + + if (!$this->userToTicketChecker->isTicketAccessibleToUser($userContext, $ticket, $heskSettings, + array(UserPrivilege::CAN_DELETE_TICKETS))) { + throw new \Exception("User does not have access to ticket {$ticketId}"); + } + + foreach ($ticket->attachments as $attachment) { + $this->attachmentHandler->deleteAttachmentFromTicket($ticketId, $attachment->id, $userContext, $heskSettings); + } + + //-- TODO Delete Replies + + $this->ticketGateway->deleteTicket($ticketId, $heskSettings); + } +} \ No newline at end of file diff --git a/api/Controllers/Tickets/TicketController.php b/api/Controllers/Tickets/CustomerTicketController.php similarity index 91% rename from api/Controllers/Tickets/TicketController.php rename to api/Controllers/Tickets/CustomerTicketController.php index a26b18e2..b1f83ed7 100644 --- a/api/Controllers/Tickets/TicketController.php +++ b/api/Controllers/Tickets/CustomerTicketController.php @@ -9,15 +9,15 @@ use BusinessLogic\Tickets\TicketRetriever; use Controllers\JsonRetriever; -class TicketController { - function get($id) { +class CustomerTicketController { + /*function get($id) { global $applicationContext, $hesk_settings, $userContext; /* @var $ticketRetriever TicketRetriever */ - $ticketRetriever = $applicationContext->get[TicketRetriever::class]; + /*$ticketRetriever = $applicationContext->get[TicketRetriever::class]; output($ticketRetriever->getTicketById($id, $hesk_settings, $userContext)); - } + }*/ function post() { global $applicationContext, $hesk_settings, $userContext; @@ -36,6 +36,10 @@ class TicketController { return output($ticket, 201); } + function delete($id) { + global $applicationContext, $hesk_settings, $userContext; + } + /** * @param $json array * @return CreateTicketByCustomerModel diff --git a/api/DataAccess/Tickets/TicketGateway.php b/api/DataAccess/Tickets/TicketGateway.php index faf0428c..8ce266d8 100644 --- a/api/DataAccess/Tickets/TicketGateway.php +++ b/api/DataAccess/Tickets/TicketGateway.php @@ -3,6 +3,7 @@ namespace DataAccess\Tickets; +use BusinessLogic\Attachments\AttachmentType; use BusinessLogic\Tickets\Attachment; use BusinessLogic\Tickets\Ticket; use BusinessLogic\Tickets\TicketGatewayGeneratedFields; @@ -55,8 +56,9 @@ class TicketGateway extends CommonDao { while ($row = hesk_dbFetchAssoc($rs)) { $linkedTicketsRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `parent` = " . intval($row['id'])); + $repliesRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto` = " . intval($id) . " ORDER BY `id` ASC"); - $tickets[] = Ticket::fromDatabaseRow($row, $linkedTicketsRs, $heskSettings); + $tickets[] = Ticket::fromDatabaseRow($row, $linkedTicketsRs, $repliesRs, $heskSettings); } $this->close(); @@ -79,8 +81,9 @@ class TicketGateway extends CommonDao { $row = hesk_dbFetchAssoc($rs); $linkedTicketsRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `parent` = " . intval($trackingId)); + $repliesRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto` = " . intval($id) . " ORDER BY `id` ASC"); - $ticket = Ticket::fromDatabaseRow($row, $linkedTicketsRs, $heskSettings); + $ticket = Ticket::fromDatabaseRow($row, $linkedTicketsRs, $repliesRs, $heskSettings); $this->close(); @@ -216,15 +219,42 @@ class TicketGateway extends CommonDao { */ function updateAttachmentsForTicket($ticketId, $attachments, $heskSettings) { $this->init(); + $this->updateAttachmentsFor($ticketId, $attachments, AttachmentType::MESSAGE, $heskSettings); + $this->close(); + } + private function updateAttachmentsFor($id, $attachments, $attachmentType, $heskSettings) { $attachmentStrings = array(); foreach ($attachments as $attachment) { $attachmentStrings[] = "{$attachment->id}#{$attachment->fileName}#{$attachment->savedName}"; } $attachmentStringToSave = implode(',', $attachmentStrings); - hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` + $tableName = $attachmentType == AttachmentType::MESSAGE ? 'tickets' : 'replies'; + + hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . $tableName . "` SET `attachments` = '" . hesk_dbEscape($attachmentStringToSave) . "' - WHERE `id` = " . intval($ticketId)); + WHERE `id` = " . intval($id)); + } + + /** + * @param $replyId int + * @param $attachments Attachment[] + * @param $heskSettings array + * + * Crappy logic that should just be pulled from the attachments table, but using for backwards compatibility + */ + function updateAttachmentsForReply($replyId, $attachments, $heskSettings) { + $this->init(); + $this->updateAttachmentsFor($replyId, $attachments, AttachmentType::REPLY, $heskSettings); + $this->close(); + } + + /** + * @param $ticketId int + * @param $heskSettings array + */ + function deleteTicket($ticketId, $heskSettings) { + hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `id` = " . intval($ticketId)); } } \ No newline at end of file diff --git a/api/Tests/BusinessLogic/Attachments/AttachmentHandlerTest.php b/api/Tests/BusinessLogic/Attachments/AttachmentHandlerTest.php index 9ff3ffd1..fb60f537 100644 --- a/api/Tests/BusinessLogic/Attachments/AttachmentHandlerTest.php +++ b/api/Tests/BusinessLogic/Attachments/AttachmentHandlerTest.php @@ -6,7 +6,9 @@ namespace BusinessLogic\Attachments; use BusinessLogic\Exceptions\ValidationException; use BusinessLogic\Security\UserContext; +use BusinessLogic\Security\UserPrivilege; use BusinessLogic\Security\UserToTicketChecker; +use BusinessLogic\Tickets\Reply; use BusinessLogic\Tickets\Ticket; use DataAccess\Attachments\AttachmentGateway; use DataAccess\Files\FileDeleter; @@ -72,7 +74,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheAttachmentBodyIsNull() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->attachmentContents = null; //-- Assert @@ -85,7 +87,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheAttachmentBodyIsEmpty() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->attachmentContents = ''; //-- Assert @@ -98,7 +100,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheAttachmentBodyIsInvalidBase64() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->attachmentContents = 'invalid base 64'; //-- Assert @@ -111,7 +113,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheDisplayNameIsNull() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->displayName = null; //-- Assert @@ -124,7 +126,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheDisplayNameIsEmpty() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->displayName = ''; //-- Assert @@ -137,7 +139,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheTicketIdIsNull() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->ticketId = null; //-- Assert @@ -150,7 +152,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheTicketIdIsANonPositiveInteger() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->ticketId = 0; //-- Assert @@ -163,7 +165,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheFileExtensionIsNotPermitted() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->heskSettings['attachments']['allowed_types'] = array('.gif'); $this->createAttachmentForTicketModel->ticketId = 0; @@ -177,7 +179,7 @@ class AttachmentHandlerTest extends TestCase { function testThatValidateThrowsAnExceptionWhenTheFileSizeIsLargerThanMaxPermitted() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->attachmentContents = base64_encode("msg"); $this->heskSettings['attachments']['max_size'] = 1; @@ -191,7 +193,7 @@ class AttachmentHandlerTest extends TestCase { function testItSavesATicketWithTheProperProperties() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->ticketId = 1; $ticket = new Ticket(); $ticket->trackingId = 'ABC-DEF-1234'; @@ -220,7 +222,7 @@ class AttachmentHandlerTest extends TestCase { function testItSavesTheFileToTheFileSystem() { //-- Arrange - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); $this->createAttachmentForTicketModel->ticketId = 1; $ticket = new Ticket(); $ticket->trackingId = 'ABC-DEF-1234'; @@ -252,8 +254,8 @@ class AttachmentHandlerTest extends TestCase { $ticket = new Ticket(); $this->ticketGateway->method('getTicketById') ->with($ticketId, $this->heskSettings)->willReturn($ticket); - $this->userToTicketChecker->method('isTicketWritableToUser') - ->with($this->userContext, $ticket, true, $this->heskSettings) + $this->userToTicketChecker->method('isTicketAccessibleToUser') + ->with($this->userContext, $ticket, $this->heskSettings, array(UserPrivilege::CAN_EDIT_TICKETS)) ->willReturn(false); //-- Assert @@ -274,7 +276,7 @@ class AttachmentHandlerTest extends TestCase { $this->heskSettings['attach_dir'] = 'attach-dir'; $ticket->attachments = array($attachment); $this->ticketGateway->method('getTicketById')->willReturn($ticket); - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); //-- Assert $this->fileDeleter->expects($this->once())->method('deleteFile')->with('foobar.txt', 'attach-dir'); @@ -293,7 +295,28 @@ class AttachmentHandlerTest extends TestCase { $this->heskSettings['attach_dir'] = 'attach-dir'; $ticket->attachments = array($attachment); $this->ticketGateway->method('getTicketById')->willReturn($ticket); - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); + + //-- Assert + $this->ticketGateway->expects($this->once())->method('updateAttachmentsForTicket'); + + //-- Act + $this->attachmentHandler->deleteAttachmentFromTicket($ticketId, 5, $this->userContext, $this->heskSettings); + } + + function testDeleteHandlesReplies() { + //-- Arrange + $ticketId = 1; + $ticket = new Ticket(); + $reply = new Reply(); + $attachment = new Attachment(); + $attachment->id = 5; + $attachment->savedName = 'foobar.txt'; + $this->heskSettings['attach_dir'] = 'attach-dir'; + $reply->attachments = array($attachment); + $ticket->replies = array($reply); + $this->ticketGateway->method('getTicketById')->willReturn($ticket); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); //-- Assert $this->ticketGateway->expects($this->once())->method('updateAttachmentsForTicket'); diff --git a/api/Tests/BusinessLogic/Attachments/AttachmentRetrieverTest.php b/api/Tests/BusinessLogic/Attachments/AttachmentRetrieverTest.php index d1b62e8a..5017ea91 100644 --- a/api/Tests/BusinessLogic/Attachments/AttachmentRetrieverTest.php +++ b/api/Tests/BusinessLogic/Attachments/AttachmentRetrieverTest.php @@ -40,7 +40,7 @@ class AttachmentRetrieverTest extends TestCase { $this->attachmentRetriever = new AttachmentRetriever($this->attachmentGateway, $this->fileReader, $this->ticketGateway, $this->userToTicketChecker); - $this->userToTicketChecker->method('isTicketWritableToUser')->willReturn(true); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); } function testItGetsTheMetadataFromTheGateway() { diff --git a/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php b/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php index 9304fa7a..d3afb126 100644 --- a/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php +++ b/api/Tests/BusinessLogic/Security/UserToTicketCheckerTest.php @@ -33,7 +33,7 @@ class UserToTicketCheckerTest extends TestCase { $ticket = new Ticket(); //-- Act - $result = $this->userToTicketChecker->isTicketWritableToUser($user, $ticket, false, $this->heskSettings); + $result = $this->userToTicketChecker->isTicketAccessibleToUser($user, $ticket, $this->heskSettings); //-- Assert self::assertThat($result, self::isTrue()); @@ -51,7 +51,7 @@ class UserToTicketCheckerTest extends TestCase { $ticket->categoryId = 1; //-- Act - $result = $this->userToTicketChecker->isTicketWritableToUser($user, $ticket, false, $this->heskSettings); + $result = $this->userToTicketChecker->isTicketAccessibleToUser($user, $ticket, $this->heskSettings); //-- Assert self::assertThat($result, self::isTrue()); @@ -69,7 +69,7 @@ class UserToTicketCheckerTest extends TestCase { $ticket->categoryId = 1; //-- Act - $result = $this->userToTicketChecker->isTicketWritableToUser($user, $ticket, false, $this->heskSettings); + $result = $this->userToTicketChecker->isTicketAccessibleToUser($user, $ticket, $this->heskSettings); //-- Assert self::assertThat($result, self::isFalse()); @@ -87,7 +87,7 @@ class UserToTicketCheckerTest extends TestCase { $ticket->categoryId = 1; //-- Act - $result = $this->userToTicketChecker->isTicketWritableToUser($user, $ticket, true, $this->heskSettings); + $result = $this->userToTicketChecker->isTicketAccessibleToUser($user, $ticket, $this->heskSettings, array(UserPrivilege::CAN_EDIT_TICKETS)); //-- Assert self::assertThat($result, self::isFalse()); @@ -106,7 +106,7 @@ class UserToTicketCheckerTest extends TestCase { $ticket->categoryId = 1; //-- Act - $result = $this->userToTicketChecker->isTicketWritableToUser($user, $ticket, true, $this->heskSettings); + $result = $this->userToTicketChecker->isTicketAccessibleToUser($user, $ticket, $this->heskSettings, array(UserPrivilege::CAN_EDIT_TICKETS)); //-- Assert self::assertThat($result, self::isTrue()); diff --git a/api/Tests/BusinessLogic/Tickets/TicketDeleterTest.php b/api/Tests/BusinessLogic/Tickets/TicketDeleterTest.php new file mode 100644 index 00000000..60b5c164 --- /dev/null +++ b/api/Tests/BusinessLogic/Tickets/TicketDeleterTest.php @@ -0,0 +1,93 @@ +userToTicketChecker = $this->createMock(UserToTicketChecker::class); + $this->ticketGateway = $this->createMock(TicketGateway::class); + $this->attachmentHandler = $this->createMock(AttachmentHandler::class); + + $this->ticketDeleter = new TicketDeleter($this->ticketGateway, $this->userToTicketChecker, $this->attachmentHandler); + } + + function testItThrowsAnExceptionWhenTheUserDoesNotHavePermissionToDeleteTheTicket() { + //-- Arrange + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(false); + + //-- Assert + $this->expectException(\Exception::class); + $this->expectExceptionMessage("User does not have access to ticket 1"); + + //-- Act + $this->ticketDeleter->deleteTicket(1, $this->userContext, $this->heskSettings); + } + + function testItDeletesAllAttachmentsForTheTicket() { + //-- Arrange + $ticket = new Ticket(); + $attachmentOne = new Attachment(); + $attachmentOne->id = 1; + $attachmentTwo = new Attachment(); + $attachmentTwo->id = 2; + $attachments = array($attachmentOne, $attachmentTwo); + $ticket->attachments = $attachments; + $this->ticketGateway->method('getTicketById')->willReturn($ticket); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); + + //-- Assert + $this->attachmentHandler->expects($this->exactly(2))->method('deleteAttachmentFromTicket'); + + //-- Act + $this->ticketDeleter->deleteTicket(1, $this->userContext, $this->heskSettings); + } + + function testItDeletesAllRepliesForTheTicket() { + //-- Arrange + + //-- Act + + //-- Assert + } + + function testItDeletesTheTicket() { + //-- Arrange + $ticket = new Ticket(); + $ticket->attachments = array(); + $ticket->id = 1; + $this->ticketGateway->method('getTicketById')->willReturn($ticket); + $this->userToTicketChecker->method('isTicketAccessibleToUser')->willReturn(true); + + //-- Assert + $this->ticketGateway->expects($this->once())->method('deleteTicket')->with(1, $this->heskSettings); + + //-- Act + $this->ticketDeleter->deleteTicket(1, $this->userContext, $this->heskSettings); + } +} diff --git a/api/index.php b/api/index.php index 1968e797..22db3b70 100644 --- a/api/index.php +++ b/api/index.php @@ -150,9 +150,10 @@ Link::all(array( '/v1/categories' => \Controllers\Categories\CategoryController::class . '::printAllCategories', '/v1/categories/{i}' => \Controllers\Categories\CategoryController::class, // Tickets - '/v1/tickets/{i}' => \Controllers\Tickets\TicketController::class, - '/v1/tickets' => \Controllers\Tickets\TicketController::class, - + '/v1/tickets/{i}' => \Controllers\Tickets\CustomerTicketController::class, + '/v1/tickets' => \Controllers\Tickets\CustomerTicketController::class, + // Tickets - Staff + '/v1/staff/tickets/{i}' => null, // Attachments '/v1/staff/tickets/{i}/attachments' => \Controllers\Attachments\StaffTicketAttachmentsController::class, '/v1/staff/tickets/{i}/attachments/{i}' => \Controllers\Attachments\StaffTicketAttachmentsController::class,