670948f113
- CRITICAL: Change DNS zones endpoint from GET to POST to avoid leaking API token in URL query parameters - HIGH: Add sync.RWMutex to protect dnsProvider field in Server, Deployer, and proxy Manager against concurrent read/write races - HIGH: Capture old DNS provider reference synchronously before launching background cleanup goroutine - HIGH: Use getDNS()/getDNSProviderLocked() accessors instead of direct field reads in all DNS operations
72 lines
1.7 KiB
JavaScript
72 lines
1.7 KiB
JavaScript
const TOKEN_KEY = "auth_token";
|
|
function getAuthToken() {
|
|
if (typeof localStorage !== "undefined") {
|
|
return localStorage.getItem(TOKEN_KEY);
|
|
}
|
|
return null;
|
|
}
|
|
function clearAuth() {
|
|
if (typeof localStorage !== "undefined") {
|
|
localStorage.removeItem(TOKEN_KEY);
|
|
}
|
|
}
|
|
class ApiError extends Error {
|
|
constructor(message, status) {
|
|
super(message);
|
|
this.status = status;
|
|
this.name = "ApiError";
|
|
}
|
|
}
|
|
async function request(path, init) {
|
|
const token = getAuthToken();
|
|
const headers = {
|
|
"Content-Type": "application/json",
|
|
...init?.headers
|
|
};
|
|
if (token) {
|
|
headers["Authorization"] = `Bearer ${token}`;
|
|
}
|
|
const res = await fetch(path, {
|
|
...init,
|
|
headers
|
|
});
|
|
if (res.status === 401 && typeof window !== "undefined" && !path.includes("/auth/")) {
|
|
clearAuth();
|
|
window.location.href = "/login";
|
|
throw new ApiError("Authentication required", 401);
|
|
}
|
|
let envelope;
|
|
try {
|
|
envelope = await res.json();
|
|
} catch {
|
|
throw new ApiError(
|
|
`Server returned non-JSON response (HTTP ${res.status})`,
|
|
res.status
|
|
);
|
|
}
|
|
if (!envelope.success) {
|
|
throw new ApiError(envelope.error ?? "Unknown API error", res.status);
|
|
}
|
|
return envelope.data;
|
|
}
|
|
function post(path, body) {
|
|
return request(path, {
|
|
method: "POST",
|
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
});
|
|
}
|
|
function validateProxy(host, port) {
|
|
return post("/api/proxies/validate", { host, port });
|
|
}
|
|
function cleanupStaleContainer(id) {
|
|
return post(`/api/containers/stale/${id}/cleanup`);
|
|
}
|
|
function bulkCleanupStaleContainers() {
|
|
return post("/api/containers/stale/cleanup");
|
|
}
|
|
export {
|
|
bulkCleanupStaleContainers as b,
|
|
cleanupStaleContainer as c,
|
|
validateProxy as v
|
|
};
|