Skip to content

Commit

Permalink
Prevent unselection of players who cannot be removed
Browse files Browse the repository at this point in the history
  • Loading branch information
Lainow committed May 17, 2024
1 parent 59ff114 commit d0d7a64
Show file tree
Hide file tree
Showing 5 changed files with 292 additions and 59 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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/).

<<<<<<< HEAD
## [2.9.5] - 2024-05-06

### Fixed
Expand All @@ -13,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fix unsended notifications while `Delete old groups when adding a new one` is set to `No`

## [2.9.4] - 2024-04-03
=======
## [2.9.4] - 20204-04-03
>>>>>>> parent of 3663936 (Add post update processing to prevent unauthorized deletion of ticket actors (#186))
### Fixed

Expand Down
60 changes: 1 addition & 59 deletions inc/ticket.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ public static function pre_item_update(CommonDBTM $item)
!empty(array_filter(
$item->input['_actors']['assign'] ?? [],
fn ($actor) => $actor['itemtype'] == 'Group'
))
&& (
isset($item->input['_from_assignment'])
&& $item->input['_from_assignment']
)
)) && $item->input['_from_assignment']
) {
//handle status behavior
if ($_SESSION['plugins']['escalade']['config']['ticket_last_status'] != -1) {
Expand All @@ -58,60 +54,6 @@ 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;
}
}
}
}
}

/**
Expand Down
186 changes: 186 additions & 0 deletions js/lockfields.js.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
<?php

/**
* -------------------------------------------------------------------------
* Escalade plugin for GLPI
* -------------------------------------------------------------------------
*
* LICENSE
*
* This file is part of Escalade.
*
* Escalade is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Escalade is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Escalade. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2015-2023 by Escalade plugin team.
* @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html
* @link https://github.com/pluginsGLPI/escalade
* -------------------------------------------------------------------------
*/

include("../../../inc/includes.php");

//change mimetype
header("Content-type: application/javascript");

//not executed in self-service interface & right verification
if ($_SESSION['glpiactiveprofile']['interface'] == "central") {
$locale_actor = __('Actor');
$esc_config = $_SESSION['plugins']['escalade']['config'];

$remove_delete_requester_user_btn = "true";
if (
isset($esc_config['remove_delete_requester_user_btn'])
&& $esc_config['remove_delete_requester_user_btn']
) {
$remove_delete_requester_user_btn = "false";
}

$remove_delete_requester_group_btn = "true";
if (
isset($esc_config['remove_delete_requester_group_btn'])
&& $esc_config['remove_delete_requester_group_btn']
) {
$remove_delete_requester_group_btn = "false";
}

$remove_delete_watcher_user_btn = "true";
if (
isset($esc_config['remove_delete_watcher_user_btn'])
&& $esc_config['remove_delete_watcher_user_btn']
) {
$remove_delete_watcher_user_btn = "false";
}

$remove_delete_watcher_group_btn = "true";
if (
isset($esc_config['remove_delete_watcher_group_btn'])
&& $esc_config['remove_delete_watcher_group_btn']
) {
$remove_delete_watcher_group_btn = "false";
}

$remove_delete_assign_user_btn = "true";
if (
isset($esc_config['remove_delete_assign_user_btn'])
&& $esc_config['remove_delete_assign_user_btn']
) {
$remove_delete_assign_user_btn = "false";
}

$remove_delete_assign_group_btn = "true";
if (
isset($esc_config['remove_delete_assign_group_btn'])
&& $esc_config['remove_delete_assign_group_btn']
) {
$remove_delete_assign_group_btn = "false";
}

$remove_delete_assign_supplier_btn = "true";
if (
isset($esc_config['remove_delete_assign_supplier_btn'])
&& $esc_config['remove_delete_assign_supplier_btn']
) {
$remove_delete_assign_supplier_btn = "false";
}

$JS = <<<JAVASCRIPT
var hideSelectedOptions = function(itemtype, actortype) {
if (!$("#actors .actor_entry").length) {
// Not yet loaded
return false;
}
const target = $("#actors .actor_entry[data-itemtype="+itemtype+"][data-actortype="+actortype+"]");
//var selectedOptions = target.siblings('.select2-selection__choice');
//target.siblings('.select2 select2-container select2-container--default select2-container--below').select2({"placeholder": "La forme ?"});
// Disable selected options
// target.find('option:selected').prop('disabled', true);
// // Update Select2
// target.select2();
// Remove "x" from select2 tag
// console.log(actortype);
// var requester_form = $(".form-select.select2-hidden-accessible[data-actor-type="+actortype+"]");
// console.log(requester_form);
// var select2_choice = requester_form.nextAll('.select2-selection__choice').first();
// console.log(select2_choice);
// requester_form.before(requester_form);
// var content = select2_choice.text();
// requester_form.before(content);
//target.find('.select2-selection__choice').remove();
// Set the input as required to prevent empty submit if at least one value exist
// if (target.length) {
// target.closest(".field-container").find('select').prop("required", true);
// }
// Data is loaded
return true;
}
var hideAllSelectedOptions = function(options_to_hide) {
// Iterate on all itemtype + actortype combinations
for (const [itemtype, actortypes] of Object.entries(options_to_hide)) {
for (const [actortype, to_hide] of Object.entries(actortypes)) {
if (to_hide) {
// Keep enabled in options_to_hide until success
options_to_hide[itemtype][actortype] = !(hideSelectedOptions(itemtype, actortype));
}
}
}
return options_to_hide;
}
$(document).ready(function() {
// only in ticket form
if (location.pathname.indexOf('ticket.form.php') > 0
|| location.pathname.indexOf('problem.form.php') > 0
|| location.pathname.indexOf('change.form.php') > 0) {
$(document).on('glpi.tab.loaded', function() {
var requester_form = $(".form-select.select2-hidden-accessible[data-actor-type=assign]");
var select2_container = requester_form.next('.select2-container');
var select2_choice = select2_container.find('.select2-selection.select2-selection--multiple.actor-field span.actor_entry').first();
var item_id = select2_choice.data('items-id');
var itemtype = select2_choice.data('itemtype');
let options_to_hide = {
Group: {
requester: {$remove_delete_requester_group_btn},
observer: {$remove_delete_watcher_group_btn},
assign: {$remove_delete_assign_group_btn},
},
User: {
requester: {$remove_delete_requester_user_btn},
observer: {$remove_delete_watcher_user_btn},
assign: {$remove_delete_assign_user_btn},
},
Supplier: {
assign: {$remove_delete_assign_supplier_btn},
}
};
hideAllSelectedOptions(options_to_hide);
// as the ticket loading may be long, try to disable until 10s pass
var tt = setInterval(hideSelectedOptions, 500);
setTimeout(function() { clearInterval(tt); }, 10000);
});
}
});
JAVASCRIPT;
echo $JS;
}
Loading

0 comments on commit d0d7a64

Please sign in to comment.