Some checks are pending
CD Production (Hetzner k3s) / Promote Images (preprod → prod) (push) Waiting to run
CD Production (Hetzner k3s) / Deploy to k3s (xpeditis-prod) (push) Blocked by required conditions
CD Production (Hetzner k3s) / Smoke Tests (push) Blocked by required conditions
CD Production (Hetzner k3s) / Deployment Summary (push) Blocked by required conditions
CD Production (Hetzner k3s) / Notify Success (push) Blocked by required conditions
CD Production (Hetzner k3s) / Notify Failure (push) Blocked by required conditions
Aligns main with the complete application codebase (cicd branch). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
4.0 KiB
TypeScript
125 lines
4.0 KiB
TypeScript
/**
|
|
* Audit Logs API
|
|
*
|
|
* Endpoints for viewing audit trail (admin/manager only)
|
|
*/
|
|
|
|
import { get } from './client';
|
|
import type { AuditLogListResponse } from '@/types/api';
|
|
|
|
/**
|
|
* List audit logs with pagination
|
|
* GET /api/v1/audit?page=1&limit=50&action=CREATE_BOOKING&userId=xxx&entityType=Booking&startDate=2024-01-01&endDate=2024-12-31
|
|
* Requires: ADMIN or MANAGER role
|
|
*/
|
|
export async function listAuditLogs(params?: {
|
|
page?: number;
|
|
limit?: number;
|
|
action?: string;
|
|
userId?: string;
|
|
entityType?: string;
|
|
entityId?: string;
|
|
startDate?: string;
|
|
endDate?: string;
|
|
}): Promise<AuditLogListResponse> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.page) queryParams.append('page', params.page.toString());
|
|
if (params?.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params?.action) queryParams.append('action', params.action);
|
|
if (params?.userId) queryParams.append('userId', params.userId);
|
|
if (params?.entityType) queryParams.append('entityType', params.entityType);
|
|
if (params?.entityId) queryParams.append('entityId', params.entityId);
|
|
if (params?.startDate) queryParams.append('startDate', params.startDate);
|
|
if (params?.endDate) queryParams.append('endDate', params.endDate);
|
|
|
|
const queryString = queryParams.toString();
|
|
return get<AuditLogListResponse>(`/api/v1/audit${queryString ? `?${queryString}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get audit logs for specific entity
|
|
* GET /api/v1/audit/entity/:entityType/:entityId
|
|
* Requires: ADMIN or MANAGER role
|
|
*/
|
|
export async function getEntityAuditLogs(
|
|
entityType: string,
|
|
entityId: string
|
|
): Promise<AuditLogListResponse> {
|
|
return get<AuditLogListResponse>(`/api/v1/audit/entity/${entityType}/${entityId}`);
|
|
}
|
|
|
|
/**
|
|
* Get audit logs for specific user
|
|
* GET /api/v1/audit/user/:userId?page=1&limit=50
|
|
* Requires: ADMIN or MANAGER role
|
|
*/
|
|
export async function getUserAuditLogs(
|
|
userId: string,
|
|
params?: { page?: number; limit?: number }
|
|
): Promise<AuditLogListResponse> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.page) queryParams.append('page', params.page.toString());
|
|
if (params?.limit) queryParams.append('limit', params.limit.toString());
|
|
|
|
const queryString = queryParams.toString();
|
|
return get<AuditLogListResponse>(
|
|
`/api/v1/audit/user/${userId}${queryString ? `?${queryString}` : ''}`
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get audit statistics
|
|
* GET /api/v1/audit/stats?startDate=2024-01-01&endDate=2024-12-31
|
|
* Requires: ADMIN role
|
|
*/
|
|
export async function getAuditStats(params?: {
|
|
startDate?: string;
|
|
endDate?: string;
|
|
}): Promise<any> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.startDate) queryParams.append('startDate', params.startDate);
|
|
if (params?.endDate) queryParams.append('endDate', params.endDate);
|
|
|
|
const queryString = queryParams.toString();
|
|
return get<any>(`/api/v1/audit/stats${queryString ? `?${queryString}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Export audit logs (CSV)
|
|
* GET /api/v1/audit/export?format=csv&startDate=2024-01-01&endDate=2024-12-31
|
|
* Requires: ADMIN role
|
|
* Returns blob for download
|
|
*/
|
|
export async function exportAuditLogs(params?: {
|
|
format?: 'csv';
|
|
startDate?: string;
|
|
endDate?: string;
|
|
action?: string;
|
|
userId?: string;
|
|
}): Promise<Blob> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.format) queryParams.append('format', params.format);
|
|
if (params?.startDate) queryParams.append('startDate', params.startDate);
|
|
if (params?.endDate) queryParams.append('endDate', params.endDate);
|
|
if (params?.action) queryParams.append('action', params.action);
|
|
if (params?.userId) queryParams.append('userId', params.userId);
|
|
|
|
const response = await fetch(
|
|
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/audit/export?${queryParams.toString()}`,
|
|
{
|
|
method: 'GET',
|
|
headers: {
|
|
Authorization: `Bearer ${
|
|
typeof window !== 'undefined' ? localStorage.getItem('access_token') : ''
|
|
}`,
|
|
},
|
|
}
|
|
);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Export failed: ${response.statusText}`);
|
|
}
|
|
|
|
return response.blob();
|
|
}
|