Add setup wizard with status tracking via SystemSetting model, implement /setup/status and /setup/complete endpoints to create initial admin user and optional cluster configuration, add workload insights endpoint with traffic analysis and policy matching including audit mode detection, implement enforcement_mode property on Policy model with audit/enforced states, add Modal component for dialogs, create SetupWizard page with multi
192 lines
3.8 KiB
TypeScript
192 lines
3.8 KiB
TypeScript
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "/api/v1";
|
|
|
|
export type Dashboard = {
|
|
clusters: number;
|
|
nodes: number;
|
|
workloads: number;
|
|
networks: number;
|
|
open_policy_violations: number;
|
|
faulty_nodes: Array<{ id: string; name: string; status: string }>;
|
|
top_talkers: Array<{ name: string; bytes: number }>;
|
|
};
|
|
|
|
export type SetupStatus = {
|
|
complete: boolean;
|
|
has_users: boolean;
|
|
has_clusters: boolean;
|
|
};
|
|
|
|
export type Cluster = {
|
|
id: string;
|
|
name: string;
|
|
api_url: string;
|
|
provider: string;
|
|
mode: string;
|
|
last_sync_status: string | null;
|
|
};
|
|
|
|
export type Project = {
|
|
id: string;
|
|
name: string;
|
|
tenant_id: string;
|
|
description: string | null;
|
|
};
|
|
|
|
export type Tenant = {
|
|
id: string;
|
|
name: string;
|
|
description: string | null;
|
|
};
|
|
|
|
export type User = {
|
|
id: string;
|
|
email: string;
|
|
display_name: string;
|
|
is_active: boolean;
|
|
};
|
|
|
|
export type Role = {
|
|
id: string;
|
|
name: string;
|
|
permissions: string[];
|
|
};
|
|
|
|
export type Subnet = {
|
|
id: string;
|
|
network_id: string;
|
|
cidr: string;
|
|
gateway: string | null;
|
|
dhcp_enabled: boolean;
|
|
};
|
|
|
|
export type IpAddress = {
|
|
id: string;
|
|
subnet_id: string;
|
|
address: string;
|
|
status: string;
|
|
note: string | null;
|
|
};
|
|
|
|
export type Network = {
|
|
id: string;
|
|
name: string;
|
|
kind: string;
|
|
vlan_id: number | null;
|
|
gateway: string | null;
|
|
mtu: number;
|
|
tags: string[];
|
|
};
|
|
|
|
export type SecurityGroup = {
|
|
id: string;
|
|
project_id: string | null;
|
|
name: string;
|
|
description: string | null;
|
|
};
|
|
|
|
export type SecurityRule = {
|
|
id: string;
|
|
security_group_id: string;
|
|
direction: string;
|
|
action: string;
|
|
protocol: string;
|
|
source: string;
|
|
destination: string;
|
|
port: string | null;
|
|
priority: number;
|
|
logging: boolean;
|
|
description: string | null;
|
|
};
|
|
|
|
export type Policy = {
|
|
id: string;
|
|
name: string;
|
|
version: number;
|
|
enabled: boolean;
|
|
enforcement_mode: string;
|
|
definition: Record<string, unknown>;
|
|
last_compiled: Record<string, unknown> | null;
|
|
};
|
|
|
|
export type Workload = {
|
|
id: string;
|
|
cluster_id: string;
|
|
node_id: string;
|
|
project_id: string | null;
|
|
external_id: string;
|
|
name: string;
|
|
kind: string;
|
|
status: string;
|
|
tags: string[];
|
|
};
|
|
|
|
export type WorkloadInsight = {
|
|
workload: Workload;
|
|
traffic: Array<Record<string, unknown>>;
|
|
matching_policies: Policy[];
|
|
effective_decision: string;
|
|
audit_mode_notes: string[];
|
|
};
|
|
|
|
export type ServiceCatalogItem = {
|
|
id: string;
|
|
name: string;
|
|
protocol: string;
|
|
ports: string;
|
|
editable: boolean;
|
|
};
|
|
|
|
export type AuditLog = {
|
|
id: string;
|
|
created_at: string;
|
|
action: string;
|
|
object_type: string;
|
|
result: string;
|
|
};
|
|
|
|
export function token() {
|
|
return localStorage.getItem("nexafabric.token");
|
|
}
|
|
|
|
export function setToken(value: string) {
|
|
localStorage.setItem("nexafabric.token", value);
|
|
}
|
|
|
|
export async function api<T>(path: string, init: RequestInit = {}): Promise<T> {
|
|
const response = await fetch(`${API_BASE_URL}${path}`, {
|
|
...init,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
...(token() ? { Authorization: `Bearer ${token()}` } : {}),
|
|
...init.headers,
|
|
},
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error(await response.text());
|
|
}
|
|
return response.json() as Promise<T>;
|
|
}
|
|
|
|
export async function publicApi<T>(path: string, init: RequestInit = {}): Promise<T> {
|
|
const response = await fetch(`${API_BASE_URL}${path}`, {
|
|
...init,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
...init.headers,
|
|
},
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error(await response.text());
|
|
}
|
|
return response.json() as Promise<T>;
|
|
}
|
|
|
|
export async function login(email: string, password: string) {
|
|
const data = await api<{ access_token: string }>("/auth/login", {
|
|
method: "POST",
|
|
body: JSON.stringify({ email, password }),
|
|
});
|
|
setToken(data.access_token);
|
|
return data;
|
|
}
|