From 3663936dbb19f90a6aa5f3aad80ae863b4d7a83a Mon Sep 17 00:00:00 2001 From: Romain Lecouvreur <102067890+RomainLvr@users.noreply.github.com> Date: Mon, 6 May 2024 09:32:28 +0200 Subject: [PATCH] Add post update processing to prevent unauthorized deletion of ticket actors (#186) * Add post update processing to prevent unauthorized deletion of ticket actors * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Romain B <8530352+Rom1-B@users.noreply.github.com> --- CHANGELOG.md | 8 +++++- inc/ticket.class.php | 60 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e74b631..3c71a63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [2.9.4] - 20204-04-03 +## [unreleased] - + +### Fixed + +- Fix unauthorized deletion of ticket actors according to plugin configuration + +## [2.9.4] - 2024-04-03 ### Fixed diff --git a/inc/ticket.class.php b/inc/ticket.class.php index 16fd6eb..814ff34 100644 --- a/inc/ticket.class.php +++ b/inc/ticket.class.php @@ -43,7 +43,11 @@ public static function pre_item_update(CommonDBTM $item) !empty(array_filter( $item->input['_actors']['assign'] ?? [], fn ($actor) => $actor['itemtype'] == 'Group' - )) && $item->input['_from_assignment'] + )) + && ( + isset($item->input['_from_assignment']) + && $item->input['_from_assignment'] + ) ) { //handle status behavior if ($_SESSION['plugins']['escalade']['config']['ticket_last_status'] != -1) { @@ -54,6 +58,60 @@ public static function pre_item_update(CommonDBTM $item) if (isset($input['_itil_assign'])) { $item->input['_do_not_compute_status'] = true; } + + $config = $_SESSION['plugins']['escalade']['config']; + + // Get actual actors for the ticket + if ($item instanceof Ticket) { + $actorTypes = [CommonITILActor::REQUESTER, CommonITILActor::OBSERVER, CommonITILActor::ASSIGN]; + $ticket_actors = array_reduce( + $actorTypes, + function ($carry, $type) use ($item) { + $carry[$item->getActorFieldNameType($type)] = $item->getActorsForType($type); + return $carry; + }, + [] + ); + + // Get updated actors + $actors_update = $item->input['_actors'] ?? []; + + // Get deletion rights for each type of actor + $deletion_rights = [ + User::getType() => [ + 'requester' => $config['remove_delete_requester_user_btn'], + 'observer' => $config['remove_delete_watcher_user_btn'], + 'assign' => $config['remove_delete_assign_user_btn'], + ], + Group::getType() => [ + 'requester' => $config['remove_delete_requester_group_btn'], + 'observer' => $config['remove_delete_watcher_group_btn'], + 'assign' => $config['remove_delete_assign_group_btn'], + ], + Supplier::getType() => [ + 'assign' => $config['remove_delete_assign_supplier_btn'], + ], + ]; + + // Iteration through actor types and verification of deletion rights + foreach ($ticket_actors as $type => $actors) { + $updatedActors = array_map( + function ($a) { + return [$a['items_id'], $a['itemtype']]; + }, + $actors_update[$type] ?? [] + ); + + foreach ($actors as $actor) { + $actorKey = [$actor['items_id'], $actor['itemtype']]; + + // If the actor has been deleted and deletion is forbidden, it is readjusted to simulate a non-deletion + if (!in_array($actorKey, $updatedActors) && empty($deletion_rights[$actor['itemtype']][$type])) { + $item->input['_actors'][$type][] = $actor; + } + } + } + } } /**