138 lines
3.1 KiB
TypeScript
138 lines
3.1 KiB
TypeScript
export type ServerStatus = "pending" | "active" | "offline";
|
|
export type KeySource = "uploaded" | "generated";
|
|
|
|
export interface Server {
|
|
id: string;
|
|
server_id: string;
|
|
hostname: string;
|
|
ip_address: string;
|
|
os_info: string;
|
|
status: ServerStatus;
|
|
last_seen: string;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface Key {
|
|
id: string;
|
|
key_id: string;
|
|
label: string;
|
|
public_key: string;
|
|
fingerprint: string;
|
|
source: KeySource;
|
|
generated_by_server_id?: string;
|
|
created_at: string;
|
|
assigned_count?: number;
|
|
}
|
|
|
|
export interface Assignment {
|
|
id: string;
|
|
key_id: string;
|
|
server_id: string;
|
|
assigned_at: string;
|
|
revoked_at: string | null;
|
|
}
|
|
|
|
export interface NewServerResponse {
|
|
server_id: string;
|
|
pre_reg_token: string;
|
|
install_command: string;
|
|
}
|
|
|
|
export interface KeyWithAssignments extends Key {
|
|
assignments: (Assignment & { server: Server })[];
|
|
}
|
|
|
|
export interface ServerWithKeys extends Server {
|
|
keys: (Assignment & { key: Key })[];
|
|
}
|
|
|
|
class ApiError extends Error {
|
|
constructor(
|
|
public status: number,
|
|
message: string
|
|
) {
|
|
super(message);
|
|
this.name = "ApiError";
|
|
}
|
|
}
|
|
|
|
async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
|
const res = await fetch(`/api${path}`, {
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
...options?.headers,
|
|
},
|
|
...options,
|
|
});
|
|
|
|
if (!res.ok) {
|
|
const text = await res.text().catch(() => res.statusText);
|
|
throw new ApiError(res.status, text || `HTTP ${res.status}`);
|
|
}
|
|
|
|
if (res.status === 204) {
|
|
return undefined as T;
|
|
}
|
|
|
|
return res.json();
|
|
}
|
|
|
|
export const api = {
|
|
// Servers
|
|
listServers(): Promise<Server[]> {
|
|
return request<Server[]>("/servers");
|
|
},
|
|
|
|
getServer(serverId: string): Promise<ServerWithKeys> {
|
|
return request<ServerWithKeys>(`/servers/${serverId}`);
|
|
},
|
|
|
|
createServer(): Promise<NewServerResponse> {
|
|
return request<NewServerResponse>("/servers/new", { method: "POST" });
|
|
},
|
|
|
|
deleteServer(serverId: string): Promise<void> {
|
|
return request<void>(`/servers/${serverId}`, { method: "DELETE" });
|
|
},
|
|
|
|
generateKeyForServer(serverId: string): Promise<{ key_id: string }> {
|
|
return request<{ key_id: string }>(`/servers/${serverId}/generate-key`, {
|
|
method: "POST",
|
|
});
|
|
},
|
|
|
|
// Keys
|
|
listKeys(): Promise<Key[]> {
|
|
return request<Key[]>("/keys");
|
|
},
|
|
|
|
getKey(keyId: string): Promise<KeyWithAssignments> {
|
|
return request<KeyWithAssignments>(`/keys/${keyId}`);
|
|
},
|
|
|
|
uploadKey(label: string, public_key: string): Promise<Key> {
|
|
return request<Key>("/keys", {
|
|
method: "POST",
|
|
body: JSON.stringify({ label, public_key }),
|
|
});
|
|
},
|
|
|
|
deleteKey(keyId: string): Promise<void> {
|
|
return request<void>(`/keys/${keyId}`, { method: "DELETE" });
|
|
},
|
|
|
|
// Assignments
|
|
assignKey(keyId: string, serverId: string): Promise<Assignment> {
|
|
return request<Assignment>(`/keys/${keyId}/assign`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ server_id: serverId }),
|
|
});
|
|
},
|
|
|
|
revokeKey(keyId: string, serverId: string): Promise<void> {
|
|
return request<void>(`/keys/${keyId}/assign/${serverId}`, {
|
|
method: "DELETE",
|
|
});
|
|
},
|
|
};
|