Initial working state: CL3.5 complete (Plesk sync + suspend/unsuspend)
This commit is contained in:
93
lib/plesk.ts
Normal file
93
lib/plesk.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { decryptSecret } from "@/lib/crypto";
|
||||
|
||||
export type PleskAuthType = "api_key" | "basic" | "oauth_token";
|
||||
|
||||
export type PleskConnection = {
|
||||
baseUrl: string;
|
||||
authType: PleskAuthType;
|
||||
authSecretEncrypted: string;
|
||||
};
|
||||
|
||||
type PleskRequestOptions = {
|
||||
method?: "GET" | "POST";
|
||||
body?: unknown;
|
||||
};
|
||||
|
||||
function buildHeaders(authType: PleskAuthType, authSecret: string): Record<string, string> {
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
};
|
||||
|
||||
if (authType === "api_key") {
|
||||
headers["X-API-Key"] = authSecret;
|
||||
} else if (authType === "oauth_token") {
|
||||
headers.Authorization = `Bearer ${authSecret}`;
|
||||
} else {
|
||||
headers.Authorization = `Basic ${Buffer.from(authSecret).toString("base64")}`;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
function joinUrl(baseUrl: string, path: string) {
|
||||
const normalizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
||||
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
||||
return `${normalizedBase}${normalizedPath}`;
|
||||
}
|
||||
|
||||
export async function pleskRequest<T>(
|
||||
connection: PleskConnection,
|
||||
path: string,
|
||||
options: PleskRequestOptions = {},
|
||||
) {
|
||||
const authSecret = decryptSecret(connection.authSecretEncrypted);
|
||||
const response = await fetch(joinUrl(connection.baseUrl, path), {
|
||||
method: options.method ?? "GET",
|
||||
headers: buildHeaders(connection.authType, authSecret),
|
||||
body: options.body ? JSON.stringify(options.body) : undefined,
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const message = await response.text();
|
||||
throw new Error(`Plesk request failed (${response.status}): ${message}`);
|
||||
}
|
||||
|
||||
const contentType = response.headers.get("content-type") ?? "";
|
||||
if (!contentType.includes("application/json")) {
|
||||
return null as T;
|
||||
}
|
||||
|
||||
return (await response.json()) as T;
|
||||
}
|
||||
|
||||
export async function validatePleskConnection(connection: PleskConnection) {
|
||||
try {
|
||||
await pleskRequest(connection, "/api/v2/server");
|
||||
return true;
|
||||
} catch {
|
||||
await pleskRequest(connection, "/api/v2/subscriptions");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export async function listPleskSubscriptions(connection: PleskConnection): Promise<any[]> {
|
||||
const result = await pleskRequest<any[]>(connection, "/api/v2/subscriptions");
|
||||
return Array.isArray(result) ? result : [];
|
||||
}
|
||||
|
||||
export async function listPleskDomains(connection: PleskConnection): Promise<any[]> {
|
||||
const result = await pleskRequest<any[]>(connection, "/api/v2/domains");
|
||||
return Array.isArray(result) ? result : [];
|
||||
}
|
||||
|
||||
export async function suspendPleskSubscription(connection: PleskConnection, subscriptionId: string) {
|
||||
return pleskRequest(connection, `/api/v2/subscriptions/${subscriptionId}/suspend`, { method: "POST" });
|
||||
}
|
||||
|
||||
export async function unsuspendPleskSubscription(connection: PleskConnection, subscriptionId: string) {
|
||||
return pleskRequest(connection, `/api/v2/subscriptions/${subscriptionId}/unsuspend`, {
|
||||
method: "POST",
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user