Skip to content

Commit

Permalink
fix ticket list ignoring validation role
Browse files Browse the repository at this point in the history
  • Loading branch information
btry authored Jun 26, 2024
1 parent 6d9f81b commit aa4ad2c
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 95 deletions.
252 changes: 157 additions & 95 deletions src/Ticket.php
Original file line number Diff line number Diff line change
Expand Up @@ -5395,6 +5395,7 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0)
self::$rightname,
[self::READALL, self::READMY, self::READASSIGN, CREATE]
)
&& !Session::haveRightsOr(TicketValidation::$rightname, TicketValidation::getValidateRights())
) {
return false;
}
Expand All @@ -5404,65 +5405,23 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0)
}

$criteria = self::getCommonCriteria();
$restrict = [];
$options = [
'criteria' => [],
'reset' => 'reset',
];
$restrict = self::getListForItemRestrict($item);
$criteria['WHERE'] = $restrict + getEntitiesRestrictCriteria(self::getTable());
$criteria['WHERE']['glpi_tickets.is_deleted'] = 0;
$criteria['LIMIT'] = (int)$_SESSION['glpilist_limit'];

switch (get_class($item)) {
case User::class:
$restrict['glpi_tickets_users.users_id'] = $item->getID();
$restrict['glpi_tickets_users.type'] = CommonITILActor::REQUESTER;

$options['criteria'][0]['field'] = 4; // status
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

case SLA::class:
$restrict[] = [
'OR' => [
'slas_id_tto' => $item->getID(),
'slas_id_ttr' => $item->getID()
]
];
$criteria['ORDERBY'] = 'glpi_tickets.time_to_resolve DESC';

$options['criteria'][0]['field'] = 30;
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

case OLA::class:
$restrict[] = [
'OR' => [
'olas_id_tto' => $item->getID(),
'olas_id_ttr' => $item->getID()
]
];
$criteria['ORDERBY'] = 'glpi_tickets.internal_time_to_resolve DESC';

$options['criteria'][0]['field'] = 30;
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

case Supplier::class:
$restrict['glpi_suppliers_tickets.suppliers_id'] = $item->getID();
$restrict['glpi_suppliers_tickets.type'] = CommonITILActor::ASSIGN;

$options['criteria'][0]['field'] = 6;
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

case Group::class:
// Mini search engine
// Mini search engine
/** @var Group $item */
if ($item->haveChildren()) {
$tree = Session::getSavedOption(__CLASS__, 'tree', 0);
echo "<table class='tab_cadre_fixe'>";
Expand All @@ -5479,56 +5438,10 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0)
$tree = 0;
}
echo "</td></tr></table>";

$restrict['glpi_groups_tickets.groups_id'] = ($tree ? getSonsOf('glpi_groups', $item->getID()) : $item->getID());
$restrict['glpi_groups_tickets.type'] = CommonITILActor::REQUESTER;

$options['criteria'][0]['field'] = 71;
$options['criteria'][0]['searchtype'] = ($tree ? 'under' : 'equals');
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

default:
$restrict['glpi_items_tickets.items_id'] = $item->getID();
$restrict['glpi_items_tickets.itemtype'] = $item->getType();

// you can only see your tickets
if (!Session::haveRight(self::$rightname, self::READALL)) {
$or = [
'glpi_tickets.users_id_recipient' => Session::getLoginUserID(),
[
'AND' => [
'glpi_tickets_users.tickets_id' => new \QueryExpression('glpi_tickets.id'),
'glpi_tickets_users.users_id' => Session::getLoginUserID()
]
]
];
if (count($_SESSION['glpigroups'])) {
$or['glpi_groups_tickets.groups_id'] = $_SESSION['glpigroups'];
}
$restrict[] = ['OR' => $or];
}

$options['criteria'][0]['field'] = 12;
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = 'all';
$options['criteria'][0]['link'] = 'AND';

$options['metacriteria'][0]['itemtype'] = $item->getType();
$options['metacriteria'][0]['field'] = Search::getOptionNumber(
$item->getType(),
'id'
);
$options['metacriteria'][0]['searchtype'] = 'equals';
$options['metacriteria'][0]['value'] = $item->getID();
$options['metacriteria'][0]['link'] = 'AND';
/** @var CommonDBTM $item */
break;
}

$criteria['WHERE'] = $restrict + getEntitiesRestrictCriteria(self::getTable());
$criteria['WHERE']['glpi_tickets.is_deleted'] = 0;
$criteria['LIMIT'] = (int)$_SESSION['glpilist_limit'];
$iterator = $DB->request($criteria);
$number = count($iterator);

Expand Down Expand Up @@ -5590,6 +5503,7 @@ public static function showListForItem(CommonDBTM $item, $withtemplate = 0)
)
);

$options = self::getListForItemSearchOptionsCriteria($item);
echo "<tr class='noHover'><th colspan='$colspan'>";
$title = sprintf(_n('Last %d ticket', 'Last %d tickets', $number), $number);
$link = "<a href='" . Ticket::getSearchURL() . "?" .
Expand Down Expand Up @@ -5786,6 +5700,13 @@ public static function getCommonCriteria()
]
];

$criteria['LEFT JOIN']['glpi_ticketvalidations'] = [
'ON' => [
self::getTable() => 'id',
'glpi_ticketvalidations' => 'tickets_id'
]
];

return $criteria;
}

Expand Down Expand Up @@ -7077,4 +6998,145 @@ public static function getContentTemplatesParametersClass(): string
{
return TicketParameters::class;
}

public static function getListForItemRestrict(CommonDBTM $item)
{
$restrict = [];

switch (get_class($item)) {
case User::class:
$restrict['glpi_tickets_users.users_id'] = $item->getID();
$restrict['glpi_tickets_users.type'] = CommonITILActor::REQUESTER;
break;

case SLA::class:
$restrict[] = [
'OR' => [
'slas_id_tto' => $item->getID(),
'slas_id_ttr' => $item->getID()
]
];
break;

case OLA::class:
$restrict[] = [
'OR' => [
'olas_id_tto' => $item->getID(),
'olas_id_ttr' => $item->getID()
]
];
break;

case Supplier::class:
$restrict['glpi_suppliers_tickets.suppliers_id'] = $item->getID();
$restrict['glpi_suppliers_tickets.type'] = CommonITILActor::ASSIGN;
break;

case Group::class:
/** @var Group $item */
if ($item->haveChildren()) {
$tree = Session::getSavedOption(__CLASS__, 'tree', 0);
} else {
$tree = 0;
}
$restrict['glpi_groups_tickets.groups_id'] = ($tree ? getSonsOf('glpi_groups', $item->getID()) : $item->getID());
$restrict['glpi_groups_tickets.type'] = CommonITILActor::REQUESTER;
/** @var CommonDBTM $item */
break;

default:
$restrict['glpi_items_tickets.items_id'] = $item->getID();
$restrict['glpi_items_tickets.itemtype'] = $item->getType();
// you can only see your tickets
if (!Session::haveRight(self::$rightname, self::READALL)) {
$or = [
'glpi_tickets.users_id_recipient' => Session::getLoginUserID(),
[
'AND' => [
'glpi_tickets_users.tickets_id' => new \QueryExpression('glpi_tickets.id'),
'glpi_tickets_users.users_id' => Session::getLoginUserID()
]
]
];
if (Session::haveRightsOr(TicketValidation::$rightname, [TicketValidation::VALIDATEINCIDENT, TicketValidation::VALIDATEREQUEST])) {
$or[] = [
'AND' => [
'glpi_ticketvalidations.tickets_id' => new \QueryExpression('glpi_tickets.id'),
'glpi_ticketvalidations.users_id_validate' => Session::getLoginUserID(),
]
];
}
if (count($_SESSION['glpigroups'])) {
$or['glpi_groups_tickets.groups_id'] = $_SESSION['glpigroups'];
}
$restrict[] = ['OR' => $or];
}
}

return $restrict;
}

private static function getListForItemSearchOptionsCriteria(CommonDBTM $item): array
{
$options = [
'criteria' => [],
'reset' => 'reset',
];

switch (get_class($item)) {
case User::class:
$options['criteria'][0]['field'] = 4; // status
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

case SLA::class:
case OLA::class:
$options['criteria'][0]['field'] = 30;
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

case Supplier::class:
$options['criteria'][0]['field'] = 6;
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
break;

case Group::class:
/** @var Group $item */
if ($item->haveChildren()) {
$tree = Session::getSavedOption(__CLASS__, 'tree', 0);
} else {
$tree = 0;
}
$options['criteria'][0]['field'] = 71;
$options['criteria'][0]['searchtype'] = ($tree ? 'under' : 'equals');
$options['criteria'][0]['value'] = $item->getID();
$options['criteria'][0]['link'] = 'AND';
/** @var CommonDBTM $item */
break;

default:
$options['criteria'][0]['field'] = 12;
$options['criteria'][0]['searchtype'] = 'equals';
$options['criteria'][0]['value'] = 'all';
$options['criteria'][0]['link'] = 'AND';

$options['metacriteria'][0]['itemtype'] = $item->getType();
$options['metacriteria'][0]['field'] = Search::getOptionNumber(
$item->getType(),
'id'
);
$options['metacriteria'][0]['searchtype'] = 'equals';
$options['metacriteria'][0]['value'] = $item->getID();
$options['metacriteria'][0]['link'] = 'AND';
break;
}

return $options;
}
}
67 changes: 67 additions & 0 deletions tests/functional/Ticket.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
use Ticket_User;
use TicketValidation;
use User;
use Session;

/* Test for inc/ticket.class.php */

Expand Down Expand Up @@ -6984,4 +6985,70 @@ public function testRestrictedDropdownValues()
$this->array($values['results'])->size->isGreaterThan(1);
$this->boolean($fn_dropdown_has_id($values['results'], $not_my_tickets_id))->isTrue();
}

public function testGetCommonCriteria()
{
global $DB;

$this->login('tech', 'tech');

$item = new \Project();
$item->add([
'name' => $this->getUniqueString(),
]);
$this->boolean($item->isNewItem())->isFalse();

// Find tickets already in the entity
$request = \Ticket::getCommonCriteria();
$request['WHERE'] = $this->callPrivateMethod(new \Ticket(), 'getListForItemRestrict', $item);
$request['WHERE'] = $request['WHERE'] + getEntitiesRestrictCriteria(\Ticket::getTable());
$result = $DB->request($request);
$existing_tickets = $result->count();

// Create a ticket with no actor and a valdiator
$ticket = new \Ticket();
$ticket->add([
'name' => __FUNCTION__,
'content' => __FUNCTION__,
'entities_id' => $this->getTestRootEntity(true),
'users_id_recipient' => getItemByTypeName(User::class, 'tech', true),
]);
$this->boolean($ticket->isNewItem())->isFalse();

$item_ticket = new \Item_Ticket();
$item_ticket->add([
'tickets_id' => $ticket->getID(),
'itemtype' => $item->getType(),
'items_id' => $item->getID(),
]);
$this->boolean($item_ticket->isNewItem())->isFalse();

$user = new \Ticket_User();
$users = $user->find([
'tickets_id' => $ticket->getID(),
]);
$this->integer(count($users))->IsEqualTo(0);

$this->login('post-only', 'postonly');
$_SESSION['glpiactiveprofile'][\TicketValidation::$rightname] = \TicketValidation::VALIDATEINCIDENT + \TicketValidation::VALIDATEREQUEST;

// Check the ticket is not found
$request['WHERE'] = $this->callPrivateMethod(new \Ticket(), 'getListForItemRestrict', $item);
$request['WHERE'] = $request['WHERE'] + getEntitiesRestrictCriteria(\Ticket::getTable());
$result = $DB->request($request);
$this->integer($result->count())->isEqualTo($existing_tickets);

$ticket_valdiation = new TicketValidation();
$ticket_valdiation->add([
'tickets_id' => $ticket->getID(),
'entities_id' => $ticket->fields['entities_id'],
'users_id_validate' => Session::getLoginUserID(),
'timeline_position' => 1,
]);
$this->boolean($ticket_valdiation->isNewItem())->isFalse();

// Check the ticket under valdiation is found
$result = $DB->request($request);
$this->integer($result->count())->isEqualTo($existing_tickets + 1);
}
}

0 comments on commit aa4ad2c

Please sign in to comment.