228 lines
8.0 KiB
TypeScript
228 lines
8.0 KiB
TypeScript
import type { ServiceAccessException, ServiceAppRole, ServiceGrant } from "../../entities/access/types";
|
|
import type { Client } from "../../entities/client/types";
|
|
import type { Invite } from "../../entities/invite/types";
|
|
import type { Service } from "../../entities/service/types";
|
|
import type { SyncStatus } from "../../entities/sync/types";
|
|
import type { ClientGroup, ClientMembership, LauncherUser } from "../../entities/user/types";
|
|
import type { LauncherData, LauncherSettings } from "./mockApi";
|
|
|
|
export type AdminAccessAssignmentValue = Exclude<ServiceAppRole, "owner"> | "deny" | "unset";
|
|
|
|
export interface ControlPlaneSnapshot {
|
|
actor: {
|
|
id: string;
|
|
name: string;
|
|
email: string | null;
|
|
source: string;
|
|
};
|
|
counts: Record<string, number>;
|
|
data: LauncherData;
|
|
}
|
|
|
|
export interface ControlPlaneMutationResult {
|
|
data: LauncherData;
|
|
provisioning?: {
|
|
authentikUserId: string;
|
|
email: string;
|
|
name: string;
|
|
groups: string[];
|
|
created: boolean;
|
|
temporaryPassword: string | null;
|
|
} | null;
|
|
}
|
|
|
|
export async function fetchControlPlaneSnapshot(): Promise<ControlPlaneSnapshot> {
|
|
return requestJson<ControlPlaneSnapshot>("/api/admin/control-plane");
|
|
}
|
|
|
|
export async function createAdminClient(payload: Partial<Client>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/clients", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function updateAdminClient(clientId: string, patch: Partial<Client>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/clients/${encodeURIComponent(clientId)}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(patch),
|
|
});
|
|
}
|
|
|
|
export async function deleteAdminClient(clientId: string): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/clients/${encodeURIComponent(clientId)}`, { method: "DELETE" });
|
|
}
|
|
|
|
export async function updateAdminUserProfile(userId: string, patch: Partial<LauncherUser>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/users/${encodeURIComponent(userId)}/profile`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(patch),
|
|
});
|
|
}
|
|
|
|
export async function createAdminUser(payload: {
|
|
clientId: string;
|
|
email: string;
|
|
name?: string;
|
|
role?: ClientMembership["role"];
|
|
groupIds?: string[];
|
|
provisionAuth?: boolean;
|
|
generatePassword?: boolean;
|
|
password?: string;
|
|
}): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/users", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function provisionAdminUserAuthentik(
|
|
userId: string,
|
|
payload: { generatePassword?: boolean; password?: string } = {}
|
|
): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/users/${encodeURIComponent(userId)}/provision-authentik`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function updateAdminMembership(
|
|
membershipId: string,
|
|
patch: Partial<ClientMembership>
|
|
): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/memberships/${encodeURIComponent(membershipId)}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(patch),
|
|
});
|
|
}
|
|
|
|
export async function deleteAdminMembership(membershipId: string): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/memberships/${encodeURIComponent(membershipId)}`, { method: "DELETE" });
|
|
}
|
|
|
|
export async function createAdminGroup(payload: Pick<ClientGroup, "clientId"> & Partial<ClientGroup>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/groups", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function updateAdminGroup(groupId: string, patch: Partial<ClientGroup>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/groups/${encodeURIComponent(groupId)}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(patch),
|
|
});
|
|
}
|
|
|
|
export async function deleteAdminGroup(groupId: string): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/groups/${encodeURIComponent(groupId)}`, { method: "DELETE" });
|
|
}
|
|
|
|
export async function createAdminService(payload: Partial<Service> = {}): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/services", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function updateAdminService(serviceId: string, patch: Partial<Service>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/services/${encodeURIComponent(serviceId)}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(patch),
|
|
});
|
|
}
|
|
|
|
export async function reorderAdminServices(orderedServiceIds: string[]): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/services/reorder", {
|
|
method: "PATCH",
|
|
body: JSON.stringify({ orderedServiceIds }),
|
|
});
|
|
}
|
|
|
|
export async function deleteAdminService(serviceId: string): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/services/${encodeURIComponent(serviceId)}`, { method: "DELETE" });
|
|
}
|
|
|
|
export async function createAdminInvite(
|
|
payload: Pick<Invite, "clientId" | "email" | "role">
|
|
): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/invites", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function updateAdminInvite(inviteId: string, patch: Partial<Invite>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/invites/${encodeURIComponent(inviteId)}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(patch),
|
|
});
|
|
}
|
|
|
|
export async function deleteAdminInvite(inviteId: string): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/invites/${encodeURIComponent(inviteId)}`, { method: "DELETE" });
|
|
}
|
|
|
|
export async function setAdminUserServiceAccess(payload: {
|
|
userId: string;
|
|
serviceId: string;
|
|
value: AdminAccessAssignmentValue;
|
|
}): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/access/user-service", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function upsertAdminGrant(payload: Partial<ServiceGrant>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/access/grants", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function upsertAdminException(payload: Partial<ServiceAccessException>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/access/exceptions", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function retryAdminSync(syncId: string): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>(`/api/admin/sync/${encodeURIComponent(syncId)}/retry`, { method: "POST" });
|
|
}
|
|
|
|
export async function updateAdminSettings(patch: Partial<LauncherSettings>): Promise<ControlPlaneMutationResult> {
|
|
return requestJson<ControlPlaneMutationResult>("/api/admin/settings", {
|
|
method: "PATCH",
|
|
body: JSON.stringify(patch),
|
|
});
|
|
}
|
|
|
|
async function requestJson<T>(url: string, init: RequestInit = {}): Promise<T> {
|
|
const headers = new Headers(init.headers);
|
|
if (!headers.has("Content-Type")) {
|
|
headers.set("Content-Type", "application/json");
|
|
}
|
|
|
|
const response = await fetch(url, {
|
|
...init,
|
|
headers,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(await readErrorMessage(response));
|
|
}
|
|
|
|
return (await response.json()) as T;
|
|
}
|
|
|
|
async function readErrorMessage(response: Response) {
|
|
try {
|
|
const payload = (await response.json()) as { error?: string };
|
|
return payload.error ?? response.statusText;
|
|
} catch {
|
|
return response.statusText;
|
|
}
|
|
}
|