feat(phase-26): add Campaign models, endpoints, service with kill chain timeline UI (T-217 to T-220)
This commit is contained in:
153
frontend/src/api/campaigns.ts
Normal file
153
frontend/src/api/campaigns.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import client from "./client";
|
||||
|
||||
// ── Types ───────────────────────────────────────────────────────────
|
||||
|
||||
export interface CampaignTest {
|
||||
id: string;
|
||||
test_id: string;
|
||||
order_index: number;
|
||||
depends_on: string | null;
|
||||
phase: string | null;
|
||||
test_name: string | null;
|
||||
test_state: string | null;
|
||||
test_result: string | null;
|
||||
technique_mitre_id: string | null;
|
||||
technique_name: string | null;
|
||||
platform: string | null;
|
||||
}
|
||||
|
||||
export interface CampaignProgress {
|
||||
total: number;
|
||||
by_state: Record<string, number>;
|
||||
completion_pct: number;
|
||||
}
|
||||
|
||||
export interface Campaign {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
type: string;
|
||||
status: string;
|
||||
threat_actor_id: string | null;
|
||||
threat_actor_name: string | null;
|
||||
created_by: string | null;
|
||||
scheduled_at: string | null;
|
||||
completed_at: string | null;
|
||||
target_platform: string | null;
|
||||
tags: string[];
|
||||
created_at: string | null;
|
||||
tests: CampaignTest[];
|
||||
progress: CampaignProgress;
|
||||
}
|
||||
|
||||
export interface CampaignSummary {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
type: string;
|
||||
status: string;
|
||||
threat_actor_id: string | null;
|
||||
threat_actor_name: string | null;
|
||||
target_platform: string | null;
|
||||
tags: string[];
|
||||
created_at: string | null;
|
||||
test_count: number;
|
||||
completion_pct: number;
|
||||
}
|
||||
|
||||
export interface CampaignCreatePayload {
|
||||
name: string;
|
||||
description?: string;
|
||||
type?: string;
|
||||
threat_actor_id?: string;
|
||||
target_platform?: string;
|
||||
tags?: string[];
|
||||
scheduled_at?: string;
|
||||
}
|
||||
|
||||
export interface AddTestPayload {
|
||||
test_id: string;
|
||||
order_index?: number;
|
||||
depends_on?: string;
|
||||
phase?: string;
|
||||
}
|
||||
|
||||
// ── API Functions ───────────────────────────────────────────────────
|
||||
|
||||
/** List campaigns with optional filters. */
|
||||
export async function listCampaigns(params?: {
|
||||
type?: string;
|
||||
status?: string;
|
||||
threat_actor_id?: string;
|
||||
search?: string;
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
}): Promise<{ total: number; items: CampaignSummary[] }> {
|
||||
const { data } = await client.get("/campaigns", { params });
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Get a campaign detail with tests and progress. */
|
||||
export async function getCampaign(campaignId: string): Promise<Campaign> {
|
||||
const { data } = await client.get<Campaign>(`/campaigns/${campaignId}`);
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Create a new campaign. */
|
||||
export async function createCampaign(payload: CampaignCreatePayload): Promise<Campaign> {
|
||||
const { data } = await client.post<Campaign>("/campaigns", payload);
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Update a campaign. */
|
||||
export async function updateCampaign(
|
||||
campaignId: string,
|
||||
payload: Partial<CampaignCreatePayload>,
|
||||
): Promise<Campaign> {
|
||||
const { data } = await client.patch<Campaign>(`/campaigns/${campaignId}`, payload);
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Add a test to a campaign. */
|
||||
export async function addTestToCampaign(
|
||||
campaignId: string,
|
||||
payload: AddTestPayload,
|
||||
): Promise<CampaignTest> {
|
||||
const { data } = await client.post<CampaignTest>(`/campaigns/${campaignId}/tests`, payload);
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Remove a test from a campaign. */
|
||||
export async function removeTestFromCampaign(
|
||||
campaignId: string,
|
||||
campaignTestId: string,
|
||||
): Promise<void> {
|
||||
await client.delete(`/campaigns/${campaignId}/tests/${campaignTestId}`);
|
||||
}
|
||||
|
||||
/** Activate a campaign. */
|
||||
export async function activateCampaign(campaignId: string): Promise<Campaign> {
|
||||
const { data } = await client.post<Campaign>(`/campaigns/${campaignId}/activate`);
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Mark a campaign as completed. */
|
||||
export async function completeCampaign(campaignId: string): Promise<Campaign> {
|
||||
const { data } = await client.post<Campaign>(`/campaigns/${campaignId}/complete`);
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Get campaign progress. */
|
||||
export async function getCampaignProgress(campaignId: string): Promise<CampaignProgress & {
|
||||
campaign_id: string;
|
||||
campaign_name: string;
|
||||
}> {
|
||||
const { data } = await client.get(`/campaigns/${campaignId}/progress`);
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Generate a campaign from a threat actor. */
|
||||
export async function generateCampaignFromThreatActor(actorId: string): Promise<Campaign> {
|
||||
const { data } = await client.post<Campaign>(`/campaigns/from-threat-actor/${actorId}`);
|
||||
return data;
|
||||
}
|
||||
Reference in New Issue
Block a user