feat(setup): allow declaring a server setup token through env variable

This commit is contained in:
Varun Narravula
2025-12-14 16:24:17 -08:00
parent 97631c068c
commit 474b9a685d

View File

@@ -16,11 +16,23 @@ function generateToken(): string {
return generateRandomString(random, alphabet, 32);
}
function validateToken(token: string): boolean {
const tokenRegex = /^[a-z0-9]{32}$/;
return tokenRegex.test(token);
}
function generateId(length: number): string {
const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
return generateRandomString(random, alphabet, length);
}
function showSetupToken(token: string, source: string): void {
console.log(`=== SETUP TOKEN ${source} ===`);
console.log("Token:", token);
console.log("Use this token on the initial setup page");
console.log("================================");
}
export async function ensureSetupToken() {
try {
// Check if a server admin already exists
@@ -38,17 +50,48 @@ export async function ensureSetupToken() {
}
// Check if a setup token already exists
const existingTokens = await db
const [existingToken] = await db
.select()
.from(setupTokens)
.where(eq(setupTokens.used, false));
const envSetupToken = process.env.PANGOLIN_SETUP_TOKEN;
console.debug("PANGOLIN_SETUP_TOKEN:", envSetupToken);
if (envSetupToken) {
if (!validateToken(envSetupToken)) {
throw new Error(
"invalid token format for PANGOLIN_SETUP_TOKEN"
);
}
if (existingToken?.token !== envSetupToken) {
console.warn(
"Overwriting existing token in DB since PANGOLIN_SETUP_TOKEN is set"
);
await db
.update(setupTokens)
.set({ token: envSetupToken })
.where(eq(setupTokens.tokenId, existingToken.tokenId));
} else {
const tokenId = generateId(15);
await db.insert(setupTokens).values({
tokenId: tokenId,
token: envSetupToken,
used: false,
dateCreated: moment().toISOString(),
dateUsed: null
});
}
showSetupToken(envSetupToken, "FROM ENVIRONMENT");
return;
}
// If unused token exists, display it instead of creating a new one
if (existingTokens.length > 0) {
console.log("=== SETUP TOKEN EXISTS ===");
console.log("Token:", existingTokens[0].token);
console.log("Use this token on the initial setup page");
console.log("================================");
if (existingToken) {
showSetupToken(existingToken.token, "EXISTS");
return;
}
@@ -64,10 +107,7 @@ export async function ensureSetupToken() {
dateUsed: null
});
console.log("=== SETUP TOKEN GENERATED ===");
console.log("Token:", token);
console.log("Use this token on the initial setup page");
console.log("================================");
showSetupToken(token, "GENERATED");
} catch (error) {
console.error("Failed to ensure setup token:", error);
throw error;