144 lines
3.9 KiB
TypeScript
144 lines
3.9 KiB
TypeScript
import { apiFetch } from "./auth";
|
|
|
|
export interface AdminDashboardStats {
|
|
activeUsers: number;
|
|
totalServers: number;
|
|
runningServers: number;
|
|
queueLength: number;
|
|
onlineNodes: number;
|
|
failedJobs24h: number;
|
|
openAbuseReports: number;
|
|
openTickets: number;
|
|
generatedAt: string;
|
|
}
|
|
|
|
export interface AdminUser {
|
|
id: string;
|
|
email: string;
|
|
username: string;
|
|
displayName: string | null;
|
|
status: string;
|
|
roles: string[];
|
|
twoFactorEnabled: boolean;
|
|
sessionCount: number;
|
|
serverCount: number;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface AdminJob {
|
|
id: string;
|
|
queue: string;
|
|
jobName: string;
|
|
status: string;
|
|
attempts: number;
|
|
error: string | null;
|
|
startedAt: string | null;
|
|
completedAt: string | null;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface AdminAuditEvent {
|
|
id: string;
|
|
action: string;
|
|
entityType: string | null;
|
|
entityId: string | null;
|
|
metadata: unknown;
|
|
ipAddress: string | null;
|
|
createdAt: string;
|
|
user: { id: string; email: string; username: string } | null;
|
|
}
|
|
|
|
export interface GameNodeSummary {
|
|
id: string;
|
|
name: string;
|
|
hostname: string;
|
|
status: string;
|
|
maxServers: number;
|
|
maxRamMb: number;
|
|
platformRamMb: number;
|
|
activeServers: number;
|
|
reservedRamMb: number;
|
|
availableRamMb: number;
|
|
lastHeartbeatAt: string | null;
|
|
agentVersion: string | null;
|
|
drainRequestedAt: string | null;
|
|
createdAt: string;
|
|
}
|
|
|
|
export async function getAdminDashboardStats(): Promise<AdminDashboardStats> {
|
|
return apiFetch<AdminDashboardStats>("/admin/dashboard");
|
|
}
|
|
|
|
export async function listAdminNodes(): Promise<{ nodes: GameNodeSummary[] }> {
|
|
return apiFetch<{ nodes: GameNodeSummary[] }>("/admin/nodes");
|
|
}
|
|
|
|
export async function drainAdminNode(nodeId: string): Promise<GameNodeSummary> {
|
|
return apiFetch<GameNodeSummary>(`/admin/nodes/${nodeId}/drain`, {
|
|
method: "POST",
|
|
});
|
|
}
|
|
|
|
export async function setAdminNodeMaintenance(
|
|
nodeId: string,
|
|
enabled: boolean,
|
|
): Promise<GameNodeSummary> {
|
|
return apiFetch<GameNodeSummary>(`/admin/nodes/${nodeId}/maintenance`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ enabled }),
|
|
});
|
|
}
|
|
|
|
export async function searchAdminUsers(params?: {
|
|
q?: string;
|
|
limit?: number;
|
|
}): Promise<{ users: AdminUser[] }> {
|
|
const search = new URLSearchParams();
|
|
if (params?.q) search.set("q", params.q);
|
|
if (params?.limit) search.set("limit", String(params.limit));
|
|
const query = search.toString();
|
|
return apiFetch<{ users: AdminUser[] }>(
|
|
`/admin/users${query ? `?${query}` : ""}`,
|
|
);
|
|
}
|
|
|
|
export async function suspendAdminUser(userId: string): Promise<{ id: string; status: string }> {
|
|
return apiFetch<{ id: string; status: string }>(`/admin/users/${userId}/suspend`, {
|
|
method: "POST",
|
|
});
|
|
}
|
|
|
|
export async function unsuspendAdminUser(userId: string): Promise<{ id: string; status: string }> {
|
|
return apiFetch<{ id: string; status: string }>(`/admin/users/${userId}/unsuspend`, {
|
|
method: "POST",
|
|
});
|
|
}
|
|
|
|
export async function listAdminJobs(params?: {
|
|
limit?: number;
|
|
status?: string;
|
|
queue?: string;
|
|
}): Promise<{ jobs: AdminJob[] }> {
|
|
const search = new URLSearchParams();
|
|
if (params?.limit) search.set("limit", String(params.limit));
|
|
if (params?.status) search.set("status", params.status);
|
|
if (params?.queue) search.set("queue", params.queue);
|
|
const query = search.toString();
|
|
return apiFetch<{ jobs: AdminJob[] }>(`/admin/jobs${query ? `?${query}` : ""}`);
|
|
}
|
|
|
|
export async function listAdminAuditEvents(params?: {
|
|
limit?: number;
|
|
cursor?: string;
|
|
action?: string;
|
|
}): Promise<{ items: AdminAuditEvent[]; nextCursor: string | null }> {
|
|
const search = new URLSearchParams();
|
|
if (params?.limit) search.set("limit", String(params.limit));
|
|
if (params?.cursor) search.set("cursor", params.cursor);
|
|
if (params?.action) search.set("action", params.action);
|
|
const query = search.toString();
|
|
return apiFetch<{ items: AdminAuditEvent[]; nextCursor: string | null }>(
|
|
`/admin/audit${query ? `?${query}` : ""}`,
|
|
);
|
|
}
|