- Pure lookup: reports row for a ticket id -> found/reportId/campaignId/ticketNumber - Parameterized query only (WHERE ticket_id = $1), no requirePermission/NextResponse
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
/**
|
|
* Phishing Ticket -> Campaign Resolver (Phase 22, Wave 0)
|
|
*
|
|
* Pure lookup service: given an Autotask ticket id, finds the linked
|
|
* `reports` row (if any) and reports back its campaign linkage. No auth,
|
|
* no param parsing — that lives in the route (plan 02, GET
|
|
* /api/phishing/tickets/[ticket_id]/campaign). Extracted as its own module
|
|
* so it is unit-testable under vitest (whose `test.include` is
|
|
* `lib/**\/*.test.ts` only — `app/**` route files have no coverage).
|
|
*/
|
|
|
|
import { postgresClient } from './postgres-client';
|
|
|
|
export interface TicketCampaignResolution {
|
|
found: boolean;
|
|
reportId?: string;
|
|
campaignId?: string | null;
|
|
ticketNumber?: string | null;
|
|
}
|
|
|
|
interface ReportLookupRow {
|
|
id: string;
|
|
campaign_id: string | null;
|
|
ticket_number: string | null;
|
|
}
|
|
|
|
/**
|
|
* Looks up the `reports` row for a given ticket id (tickets.id / reports.ticket_id).
|
|
* - No row: `{ found: false }`
|
|
* - Row with `campaign_id = null`: `{ found: true, reportId, campaignId: null, ticketNumber }` — ungrouped report
|
|
* - Row with a `campaign_id`: `{ found: true, reportId, campaignId, ticketNumber }` — grouped into a campaign
|
|
*/
|
|
export async function resolveTicketToCampaign(ticketId: number): Promise<TicketCampaignResolution> {
|
|
const res = await postgresClient.query<ReportLookupRow>(
|
|
`SELECT id::text, campaign_id::text, ticket_number FROM reports WHERE ticket_id = $1`,
|
|
[ticketId]
|
|
);
|
|
const report = res.rows[0];
|
|
if (!report) {
|
|
return { found: false };
|
|
}
|
|
return {
|
|
found: true,
|
|
reportId: report.id,
|
|
campaignId: report.campaign_id,
|
|
ticketNumber: report.ticket_number,
|
|
};
|
|
}
|