194 lines
6.2 KiB
TypeScript
194 lines
6.2 KiB
TypeScript
import { ipsecServerSummaryDtoSchema, ipsecUserCreatedSchema, ipsecCertBundleSchema } from "@mmapp/contracts/ipsec"
|
|
import { requestJson } from "@/shared/api/http-client"
|
|
import type {
|
|
IpsecCertBundle,
|
|
IpsecInitRequest,
|
|
IpsecListResponse,
|
|
IpsecPeerPatch,
|
|
IpsecServerSummaryDto,
|
|
IpsecUserCreateRequest,
|
|
IpsecUserCreated,
|
|
IpsecUserPatch,
|
|
} from "@mmapp/contracts/ipsec"
|
|
|
|
export async function listIpsec(
|
|
baseUrl: string,
|
|
opts?: { serverId?: string },
|
|
): Promise<IpsecListResponse> {
|
|
const q = new URLSearchParams()
|
|
if (opts?.serverId) q.set("serverId", opts.serverId)
|
|
const suffix = q.size > 0 ? `?${q.toString()}` : ""
|
|
return requestJson<IpsecListResponse>(baseUrl, `/api/ipsec${suffix}`, { method: "GET" })
|
|
}
|
|
|
|
export async function initIpsecServer(
|
|
baseUrl: string,
|
|
body: IpsecInitRequest,
|
|
): Promise<IpsecServerSummaryDto> {
|
|
const response = await requestJson<unknown>(baseUrl, "/api/ipsec/server/init", {
|
|
method: "POST",
|
|
body: JSON.stringify(body),
|
|
})
|
|
const result = ipsecServerSummaryDtoSchema.safeParse(response)
|
|
if (!result.success || result.data.serverId !== body.serverId || !result.data.initialized) {
|
|
throw new Error("Сервер не подтвердил инициализацию IKEv2")
|
|
}
|
|
return result.data
|
|
}
|
|
|
|
export async function deleteIpsecServer(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
opts?: { removeCertificates?: boolean },
|
|
): Promise<{ ok: boolean }> {
|
|
const q = new URLSearchParams()
|
|
if (opts?.removeCertificates === false) q.set("removeCertificates", "false")
|
|
const suffix = q.size > 0 ? `?${q.toString()}` : ""
|
|
return requestJson<{ ok: boolean }>(
|
|
baseUrl,
|
|
`/api/ipsec/server/${encodeURIComponent(serverId)}${suffix}`,
|
|
{ method: "DELETE" },
|
|
)
|
|
}
|
|
|
|
export async function createIpsecUser(
|
|
baseUrl: string,
|
|
body: IpsecUserCreateRequest,
|
|
): Promise<IpsecUserCreated> {
|
|
const response = await requestJson<unknown>(baseUrl, "/api/ipsec/users", {
|
|
method: "POST",
|
|
body: JSON.stringify(body),
|
|
})
|
|
const result = ipsecUserCreatedSchema.safeParse(response)
|
|
if (!result.success || result.data.client.serverId !== String(body.serverId) || result.data.client.name !== body.name.trim() || result.data.client.authMethod !== (body.authMethod ?? "certificate")) {
|
|
throw new Error("Сервер не подтвердил создание клиента")
|
|
}
|
|
return result.data
|
|
}
|
|
|
|
export async function patchIpsecUser(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
clientId: string,
|
|
patch: IpsecUserPatch,
|
|
): Promise<{ ok: boolean }> {
|
|
const result = await requestJson<{ ok: boolean }>(
|
|
baseUrl,
|
|
`/api/ipsec/users/${encodeURIComponent(serverId)}/${encodeURIComponent(clientId)}`,
|
|
{ method: "PATCH", body: JSON.stringify(patch) },
|
|
)
|
|
if (result?.ok !== true) throw new Error("Сервер не подтвердил сохранение клиента")
|
|
return result
|
|
}
|
|
|
|
export async function deleteIpsecUser(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
clientId: string,
|
|
opts?: { removeCertificate?: boolean },
|
|
): Promise<{ ok: boolean }> {
|
|
const q = new URLSearchParams()
|
|
if (opts?.removeCertificate === false) q.set("removeCertificate", "false")
|
|
const suffix = q.size > 0 ? `?${q.toString()}` : ""
|
|
return requestJson<{ ok: boolean }>(
|
|
baseUrl,
|
|
`/api/ipsec/users/${encodeURIComponent(serverId)}/${encodeURIComponent(clientId)}${suffix}`,
|
|
{ method: "DELETE" },
|
|
)
|
|
}
|
|
|
|
function parseExportBundle(response: unknown): IpsecCertBundle {
|
|
const result = ipsecCertBundleSchema.safeParse(response)
|
|
if (!result.success || !result.data.filename.trim() || !result.data.user.trim() ||
|
|
!result.data.passphrase || result.data.passphrase.length < 8 ||
|
|
!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(result.data.contentB64) ||
|
|
!result.data.contentB64) {
|
|
throw new Error("Некорректный ответ экспорта сертификата")
|
|
}
|
|
return result.data
|
|
}
|
|
|
|
export async function exportIpsecUserCert(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
clientId: string,
|
|
passphrase: string,
|
|
): Promise<IpsecCertBundle> {
|
|
const response = await requestJson<unknown>(
|
|
baseUrl,
|
|
`/api/ipsec/users/${encodeURIComponent(serverId)}/${encodeURIComponent(clientId)}/cert`,
|
|
{ method: "POST", body: JSON.stringify({ passphrase }) },
|
|
)
|
|
return parseExportBundle(response)
|
|
}
|
|
|
|
export async function exportIpsecCertByName(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
name: string,
|
|
passphrase: string,
|
|
): Promise<IpsecCertBundle> {
|
|
const response = await requestJson<unknown>(
|
|
baseUrl,
|
|
`/api/ipsec/certs/${encodeURIComponent(serverId)}/export`,
|
|
{ method: "POST", body: JSON.stringify({ name, passphrase }) },
|
|
)
|
|
return parseExportBundle(response)
|
|
}
|
|
|
|
export async function restoreIpsecRevision(
|
|
baseUrl: string,
|
|
revisionId: string,
|
|
serverId: string,
|
|
): Promise<{ ok: boolean }> {
|
|
return requestJson<{ ok: boolean }>(baseUrl, `/api/ipsec/revisions/${encodeURIComponent(revisionId)}/restore`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ serverId }),
|
|
})
|
|
}
|
|
|
|
export async function patchIpsecPeer(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
peerId: string,
|
|
patch: IpsecPeerPatch,
|
|
): Promise<{ ok: boolean }> {
|
|
return requestJson<{ ok: boolean }>(
|
|
baseUrl,
|
|
`/api/ipsec/peers/${encodeURIComponent(serverId)}/${encodeURIComponent(peerId)}`,
|
|
{ method: "PATCH", body: JSON.stringify(patch) },
|
|
)
|
|
}
|
|
|
|
export async function deleteIpsecPeer(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
peerId: string,
|
|
opts?: { force?: boolean },
|
|
): Promise<{ ok: boolean }> {
|
|
const q = new URLSearchParams()
|
|
if (opts?.force) q.set("force", "true")
|
|
const suffix = q.size > 0 ? `?${q.toString()}` : ""
|
|
return requestJson<{ ok: boolean }>(
|
|
baseUrl,
|
|
`/api/ipsec/peers/${encodeURIComponent(serverId)}/${encodeURIComponent(peerId)}${suffix}`,
|
|
{ method: "DELETE" },
|
|
)
|
|
}
|
|
|
|
export async function deleteIpsecCert(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
name: string,
|
|
opts?: { force?: boolean },
|
|
): Promise<{ ok: boolean }> {
|
|
const q = new URLSearchParams()
|
|
if (opts?.force) q.set("force", "true")
|
|
const suffix = q.size > 0 ? `?${q.toString()}` : ""
|
|
return requestJson<{ ok: boolean }>(
|
|
baseUrl,
|
|
`/api/ipsec/certs/${encodeURIComponent(serverId)}${suffix}`,
|
|
{ method: "DELETE", body: JSON.stringify({ name }) },
|
|
)
|
|
}
|