Fix requeue: fallback to finding_ids_json when queue items are deleted or absent
The requeue endpoint now handles three scenarios: 1. Original queue items still exist — uses their finding data (ideal case) 2. Queue items deleted (Clear Completed) — looks up findings from ivanti_findings table using finding_ids_json 3. FP created outside dashboard (no queue_item_ids) — same fallback to finding_ids_json and ivanti_findings lookup 4. Last resort — creates queue items with just finding IDs if the findings aren't in ivanti_findings either
This commit is contained in:
@@ -1004,27 +1004,53 @@ function createIvantiFpWorkflowRouter() {
|
||||
let queueItemIds = [];
|
||||
try {
|
||||
queueItemIds = JSON.parse(submission.queue_item_ids_json || '[]');
|
||||
} catch (e) {
|
||||
return res.status(400).json({ error: 'Could not parse queue_item_ids_json.' });
|
||||
} catch (e) { /* ignore parse errors */ }
|
||||
|
||||
// Parse finding IDs (always available, even for submissions created outside dashboard)
|
||||
let findingIds = [];
|
||||
try {
|
||||
findingIds = JSON.parse(submission.finding_ids_json || '[]');
|
||||
} catch (e) { /* ignore */ }
|
||||
|
||||
if ((!Array.isArray(queueItemIds) || queueItemIds.length === 0) &&
|
||||
(!Array.isArray(findingIds) || findingIds.length === 0)) {
|
||||
return res.status(400).json({ error: 'No findings associated with this submission.' });
|
||||
}
|
||||
|
||||
if (!Array.isArray(queueItemIds) || queueItemIds.length === 0) {
|
||||
return res.status(400).json({ error: 'No queue items associated with this submission.' });
|
||||
// Fetch original queue items to get finding data (if they still exist)
|
||||
let findingsToQueue = [];
|
||||
if (queueItemIds.length > 0) {
|
||||
const { rows: originalItems } = await pool.query(
|
||||
`SELECT finding_id, finding_title, cves_json, ip_address, hostname FROM ivanti_todo_queue WHERE id = ANY($1)`,
|
||||
[queueItemIds]
|
||||
);
|
||||
findingsToQueue = originalItems;
|
||||
}
|
||||
|
||||
// Fetch original queue items to get finding data
|
||||
const { rows: originalItems } = await pool.query(
|
||||
`SELECT finding_id, finding_title, cves_json, ip_address, hostname FROM ivanti_todo_queue WHERE id = ANY($1)`,
|
||||
[queueItemIds]
|
||||
);
|
||||
// Fallback: if original queue items were deleted or never existed,
|
||||
// use finding_ids_json to look up finding data from ivanti_findings
|
||||
if (findingsToQueue.length === 0 && findingIds.length > 0) {
|
||||
const { rows: findings } = await pool.query(
|
||||
`SELECT id AS finding_id, title AS finding_title, cves AS cves_json, ip_address, host_name AS hostname FROM ivanti_findings WHERE id = ANY($1)`,
|
||||
[findingIds.map(String)]
|
||||
);
|
||||
findingsToQueue = findings;
|
||||
|
||||
if (originalItems.length === 0) {
|
||||
return res.status(400).json({ error: 'No original queue items found for this submission.' });
|
||||
// Last resort: create items with just the finding IDs (minimal data)
|
||||
if (findingsToQueue.length === 0) {
|
||||
findingsToQueue = findingIds.map(id => ({
|
||||
finding_id: String(id),
|
||||
finding_title: null,
|
||||
cves_json: null,
|
||||
ip_address: null,
|
||||
hostname: null,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// INSERT new pending queue items for each finding
|
||||
const newItems = [];
|
||||
for (const item of originalItems) {
|
||||
for (const item of findingsToQueue) {
|
||||
const { rows: inserted } = await pool.query(
|
||||
`INSERT INTO ivanti_todo_queue
|
||||
(user_id, finding_id, finding_title, cves_json, ip_address, hostname, vendor, workflow_type)
|
||||
@@ -1042,12 +1068,12 @@ function createIvantiFpWorkflowRouter() {
|
||||
);
|
||||
|
||||
// Audit log (fire-and-forget)
|
||||
const finding_ids = originalItems.map(i => i.finding_id).filter(Boolean);
|
||||
const auditFindingIds = findingsToQueue.map(i => i.finding_id).filter(Boolean);
|
||||
logAudit({
|
||||
userId: req.user.id, username: req.user.username,
|
||||
action: 'fp_submission_requeued', entityType: 'ivanti_fp_submissions',
|
||||
entityId: String(submission.id),
|
||||
details: { target_workflow_type: workflow_type, items_created: newItems.length, finding_ids },
|
||||
details: { target_workflow_type: workflow_type, items_created: newItems.length, finding_ids: auditFindingIds },
|
||||
ipAddress: req.ip
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user