Files
ForgeFlow/scripts/validate-installed-connections.cjs
T

96 lines
3.0 KiB
JavaScript

"use strict";
const fs = require("node:fs/promises");
const path = require("node:path");
const { app, safeStorage } = require("electron");
const configuredUserData = process.env.FORGEFLOW_USER_DATA
? path.resolve(process.env.FORGEFLOW_USER_DATA)
: path.join(app.getPath("appData"), "forgeflow");
// safeStorage is bound to Electron's userData identity. Set it before ready so
// this verifier decrypts the same secrets as the packaged application.
app.setPath("userData", configuredUserData);
function result(name, ok, detail) {
console.log(
`${ok ? "PASS" : "FAIL"} ${name}${detail ? ` — ${detail}` : ""}`,
);
return ok;
}
app.whenReady().then(async () => {
let passed = true;
try {
const userDataPath = configuredUserData;
const configPath = path.join(userDataPath, "forgeflow-config.json");
const config = JSON.parse(await fs.readFile(configPath, "utf8"));
const baseUrl = String(config.gitea?.baseUrl || "").replace(/\/+$/, "");
const encrypted = String(config.gitea?.encryptedToken || "");
passed =
result(
"secure storage",
safeStorage.isEncryptionAvailable(),
"OS-backed encryption available",
) && passed;
passed =
result(
"encrypted token",
Boolean(encrypted),
encrypted ? "present in ForgeFlow configuration" : "missing",
) && passed;
if (!baseUrl || !encrypted)
throw new Error("ForgeFlow Gitea configuration is incomplete.");
const token = safeStorage.decryptString(Buffer.from(encrypted, "base64"));
const headers = {
Accept: "application/json",
Authorization: `token ${token}`,
};
const userResponse = await fetch(`${baseUrl}/api/v1/user`, {
headers,
signal: AbortSignal.timeout(15_000),
});
const user = userResponse.ok ? await userResponse.json() : null;
passed =
result(
"Gitea API authentication",
userResponse.ok,
userResponse.ok
? `authenticated as ${user.login}`
: `HTTP ${userResponse.status}`,
) && passed;
if (userResponse.ok) {
const repositoryResponse = await fetch(
`${baseUrl}/api/v1/repos/Jens/ForgeFlow`,
{ headers, signal: AbortSignal.timeout(15_000) },
);
passed =
result(
"ForgeFlow repository access",
repositoryResponse.ok,
repositoryResponse.ok
? "read access confirmed"
: `HTTP ${repositoryResponse.status}`,
) && passed;
const actionsResponse = await fetch(
`${baseUrl}/api/v1/repos/Jens/ForgeFlow/actions/runs?limit=1`,
{ headers, signal: AbortSignal.timeout(15_000) },
);
passed =
result(
"Gitea Actions access",
actionsResponse.ok,
actionsResponse.ok
? "workflow access confirmed"
: `HTTP ${actionsResponse.status}`,
) && passed;
}
} catch (error) {
passed = result("connection validation", false, error.message) && passed;
} finally {
process.exitCode = passed ? 0 : 1;
app.quit();
}
});