Files
itflow/api/v1/tickets/resolve.php
johnnyq 359851c876 Security sweep of the 26.11 work: API contact lookup by phone or mobile kept to the key's clients; API credentials refuse a wrong decrypt password instead of saving unreadable usernames and passwords, link credential_vendor_id and credential_software_id, and drop another client's contact or asset; Products Receive window lists expenses only with Financial access and only for clients the agent can open; account ledger, reconcile page and ledger export show lines for clients the agent can't open as Another client with only date, kind and amount, with search and the client filter kept to reachable clients; Tax Collected folds unreachable exempt clients into one line; client-limited agents no longer see other clients' names in the export window client filters, Transfer to Client, company vendor expense lists, My Activity or the New Client duplicate check; Stripe switched off stops guest pay links and saving cards, and the Stripe return never books a payment twice; Admin > Cron job window is admins only; records per page needs the CSRF token and takes only the listed sizes; uploads/canned_responses closed to direct access; Admin > Debug no longer stops at the footer; report export audit log no longer double-escapes names; bulk interface network refuses a deleted network; API assets/update keeps the primary interface IP, MAC and network, tickets/resolve reports success, software/read by name works, clients/create takes the company currency, certificates/create returns its error, clients/archive logs as Client, and the 405 response no longer echoes the method; changelog database step count corrected to sixty
2026-10-23 12:09:07 -04:00

57 lines
2.1 KiB
PHP

<?php
// Resolve endpoint for tickets
// Just send a POST here with a ticket & client id, and we do the rest
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse Info
$ticket_id = intval($_POST['ticket_id']);
// Default
$update_count = false;
if (!empty($ticket_id)) {
$ticket_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT ticket_first_response_at, ticket_id, ticket_number, ticket_prefix FROM tickets WHERE ticket_id = '$ticket_id' AND ticket_resolved_at IS NULL AND ticket_client_id = $client_id LIMIT 1"));
}
// Resolved already, another client's, or not there - nothing to do
if (!empty($ticket_row)) {
// Grab what we need, not using the model
$ticket_id = intval($ticket_row['ticket_id']); // Override so things fail if this is bad
$ticket_prefix = escapeSql($ticket_row['ticket_prefix']);
$ticket_number = intval($ticket_row['ticket_number']);
$ticket_first_response_at = escapeSql($ticket_row['ticket_first_response_at']);
// Mark FR (if not)
if (empty($ticket_first_response_at)) {
setTicketFirstResponse($ticket_id);
}
// Resolve - counted straight away, before the SLA updates below run queries of their own
$update_sql = mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 4, ticket_resolved_at = NOW() WHERE ticket_id = $ticket_id AND ticket_client_id = $client_id LIMIT 1");
$resolved_count = $update_sql ? mysqli_affected_rows($mysqli) : 0;
syncTicketSlaClock($ticket_id);
setTicketResolutionSlaMet($ticket_id);
// Check insert & get insert ID
if ($update_sql) {
$update_count = $resolved_count;
// Logging
logTicketHistory($ticket_id, "Resolved via the API ($api_key_name)");
logAudit("Ticket", "Resolve", "$ticket_prefix$ticket_number ticket via API ($api_key_name)", $client_id, $ticket_id);
logAudit("API", "Success", "Resolved ticket $ticket_prefix$ticket_number via API ($api_key_name)", $client_id);
}
triggerCustomAction('ticket_resolve', $ticket_id);
}
// Output
require_once '../update_output.php';