Harden recurring cron, bulk delete, error handling; fix semgrep CI
Continued fixes from the multi-agent review: - recurring tickets cron: now that the parse error is fixed the job runs, exposing two latent bugs. (1) next_run_at was only advanced after the full success path, so any failure (e.g. a NULL created_by passed to the non-nullable assignTicket() $assignedBy -> TypeError) left it in the past and re-created a duplicate ticket every cron cycle. Added an atomic claimForRun() (conditional UPDATE gated on still-due) called BEFORE creation, which also prevents overlapping runs from double-creating. (2) The cron used a raw mysqli with no utf8mb4, corrupting non-ASCII content; it now uses Database::getConnection(). Also guard the assignment so created_by NULL falls back to the assignee. - bulk delete: attachment files were unlinked inside the DB transaction, so an atomic-mode rollback restored rows but the files were already gone. deleteTicket() can now defer file removal to the caller, and BulkOperationsModel deletes files only after a successful commit. - UserModel: back-tick the `groups` column (reserved word on MySQL 8.0.2+). - create_ticket_api.php: stop leaking raw DB/exception messages to callers; log server-side and return a generic error. (Also includes a pre-existing working-tree tweak that adds title to the manual-ticket dedupe hash.) - CI: semgrep install failed under PEP 668; add --break-system-packages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+11
-2
@@ -45,9 +45,11 @@ $conn = new mysqli(
|
||||
);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
error_log('create_ticket_api: DB connection failed: ' . $conn->connect_error);
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error' => 'Database connection failed: ' . $conn->connect_error
|
||||
'error' => 'Internal server error'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
@@ -199,6 +201,11 @@ function generateTicketHash($data)
|
||||
)),
|
||||
];
|
||||
|
||||
// Manual tickets should be unique by title (so different software installs don't collide)
|
||||
if ($sourceType === 'manual') {
|
||||
$stableComponents['title'] = $title;
|
||||
}
|
||||
|
||||
// Include hostname for node-specific issues
|
||||
if (!$isClusterWide) {
|
||||
$stableComponents['hostname'] = $hostname;
|
||||
@@ -397,7 +404,9 @@ try {
|
||||
// Race condition: another node inserted the same hash between our SELECT and INSERT
|
||||
echo json_encode(['success' => false, 'error' => 'Duplicate ticket']);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
error_log('create_ticket_api: insert failed: ' . $e->getMessage());
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'error' => 'Internal server error']);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user