Fix Cron URL Key on recurring tickets

This commit is contained in:
johnnyq
2026-07-29 16:11:36 -04:00
parent bc64c9e3d1
commit 7245ff0650
4 changed files with 37 additions and 6 deletions

View File

@@ -2,10 +2,6 @@
This file documents all notable changes made to ITFlow. This file documents all notable changes made to ITFlow.
# Changelog
This file documents all notable changes made to ITFlow.
## [26.08] ## [26.08]
### Breaking Changes and Notes ### Breaking Changes and Notes
@@ -78,6 +74,10 @@ This file documents all notable changes made to ITFlow.
- Added an **Urgent** ticket priority. - Added an **Urgent** ticket priority.
- **Multiple notes per asset**, mirroring the existing contact notes, with categorized note types - **Multiple notes per asset**, mirroring the existing contact notes, with categorized note types
(Maintenance, Repair, Configuration, Upgrade, Inspection, Note). (Maintenance, Repair, Configuration, Upgrade, Inspection, Note).
- **Ticket templates on recurring tickets.** A recurring ticket can now be assigned a ticket
template. Picking one fills in the subject and details, and the template's task list is stamped
onto every ticket the schedule raises - from the nightly cron run and from a forced run alike.
Clearing the template leaves the recurring ticket's own subject and details untouched.
- Added **ticket reply API endpoints** for creating and reading replies. - Added **ticket reply API endpoints** for creating and reading replies.
- Payments and Revenues have been combined into a single **Income** page, keeping all income in - Payments and Revenues have been combined into a single **Income** page, keeping all income in
one place, with CSV export. Revenue not tied to an invoice can still be added there; payments one place, with CSV export. Revenue not tied to an invoice can still be added there; payments
@@ -159,6 +159,12 @@ This file documents all notable changes made to ITFlow.
- Certificates can now be searched by description. - Certificates can now be searched by description.
- Fixed cents calculation rounding. - Fixed cents calculation rounding.
- Fixed guest view credential TOTP display, and removed the legacy OTP code path. - Fixed guest view credential TOTP display, and removed the legacy OTP code path.
- Bulk-creating tickets from a template against multiple assets only added the template's tasks to
the first ticket, and dropped each task's completion estimate.
- Tickets raised by the nightly recurring schedule were created without a guest URL key, so the
"View ticket" link in reply and task-approval emails for those tickets could not be opened.
Cron now generates a key like every other path that raises a ticket, and existing tickets
missing one are backfilled by the database update.
### Developer Updates ### Developer Updates
- Line endings normalized to LF across the codebase, with `.gitattributes` and `.editorconfig` - Line endings normalized to LF across the codebase, with `.gitattributes` and `.editorconfig`

View File

@@ -0,0 +1,24 @@
<?php
/*
* ITFlow - Database update to version 2.5.5 (from 2.5.4)
* Included by admin/database_updates.php - do not access directly
*/
defined('FROM_DB_UPDATER') || die("Direct file access is not allowed");
// Backfill guest URL keys. Every path that raises a ticket generates one
// except the recurring block in cron.php, which omitted the column - so
// every ticket the nightly schedule has ever created carries no key. The
// guest view matches on ticket_url_key, so those tickets cannot be opened
// from the "View ticket" link in reply and task-approval emails. It fails
// closed rather than open (NULL never matches), so this is a broken link
// rather than an exposure, but the links stay broken until a key exists.
$sql_tickets_without_url_key = mysqli_query($mysqli, "SELECT ticket_id FROM tickets WHERE ticket_url_key IS NULL OR ticket_url_key = ''");
while ($row = mysqli_fetch_assoc($sql_tickets_without_url_key)) {
$ticket_id = intval($row['ticket_id']);
$url_key = randomString(32);
mysqli_query($mysqli, "UPDATE tickets SET ticket_url_key = '$url_key' WHERE ticket_id = $ticket_id");
}

View File

@@ -318,6 +318,7 @@ if (mysqli_num_rows($sql_recurring_tickets) > 0) {
$asset_id = intval($row['recurring_ticket_asset_id']); $asset_id = intval($row['recurring_ticket_asset_id']);
$category = intval($row['recurring_ticket_category']); $category = intval($row['recurring_ticket_category']);
$ticket_template_id = intval($row['recurring_ticket_ticket_template_id']); $ticket_template_id = intval($row['recurring_ticket_ticket_template_id']);
$url_key = randomString(32);
$ticket_status = 1; // Default $ticket_status = 1; // Default
if ($assigned_id > 0) { if ($assigned_id > 0) {
@@ -342,7 +343,7 @@ if (mysqli_num_rows($sql_recurring_tickets) > 0) {
$ticket_number = mysqli_insert_id($mysqli); $ticket_number = mysqli_insert_id($mysqli);
// Raise the ticket // Raise the ticket
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Recurring', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = '$ticket_status', ticket_billable = $billable, ticket_created_by = $created_id, ticket_assigned_to = $assigned_id, ticket_contact_id = $contact_id, ticket_client_id = $client_id, ticket_asset_id = $asset_id, ticket_category = $category, ticket_recurring_ticket_id = $recurring_ticket_id"); mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Recurring', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = '$ticket_status', ticket_billable = $billable, ticket_url_key = '$url_key', ticket_created_by = $created_id, ticket_assigned_to = $assigned_id, ticket_contact_id = $contact_id, ticket_client_id = $client_id, ticket_asset_id = $asset_id, ticket_category = $category, ticket_recurring_ticket_id = $recurring_ticket_id");
$id = mysqli_insert_id($mysqli); $id = mysqli_insert_id($mysqli);
applyTicketSla($id); applyTicketSla($id);

2
db.sql
View File

@@ -3067,4 +3067,4 @@ CREATE TABLE `vendors` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2026-07-29 15:54:34 -- Dump completed on 2026-07-29 16:11:10