Enhance API with OIDC support, including login and callback endpoints. Update environment variables for OIDC configuration in .env.example. Add new features to the catalog service for listing software families, Minecraft versions, and deployment regions. Implement server management actions such as kill, delete, and update in the servers module. Integrate feature flags for maintenance mode in server operations. Update pnpm-lock.yaml with new dependencies and versions.
This commit is contained in:
143
apps/web/src/lib/api/admin.ts
Normal file
143
apps/web/src/lib/api/admin.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
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}` : ""}`,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user