import fs from 'node:fs'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; function findRoot() { const candidates = []; if (process.env.ACTUAL_SERVER_ROOT) { candidates.push(process.env.ACTUAL_SERVER_ROOT); } candidates.push('/app'); candidates.push('/usr/src/app'); candidates.push('/srv/app'); candidates.push('/opt/actual-server'); for (const base of candidates) { if (!base) { continue; } const accountDb = path.join(base, 'src', 'account-db.js'); if (fs.existsSync(accountDb)) { return base; } } return ''; } const root = findRoot(); if (!root) { console.error('actual server root not found'); process.exit(1); } const accountDbUrl = pathToFileURL(path.join(root, 'src', 'account-db.js')).href; const loadConfigUrl = pathToFileURL(path.join(root, 'src', 'load-config.js')).href; const accountDb = await import(accountDbUrl); const { default: finalConfig } = await import(loadConfigUrl); const openIdEnv = (() => { if ( !process.env.ACTUAL_OPENID_DISCOVERY_URL && !process.env.ACTUAL_OPENID_AUTHORIZATION_ENDPOINT ) { return null; } if (process.env.ACTUAL_OPENID_DISCOVERY_URL) { return { issuer: process.env.ACTUAL_OPENID_DISCOVERY_URL, client_id: process.env.ACTUAL_OPENID_CLIENT_ID, client_secret: process.env.ACTUAL_OPENID_CLIENT_SECRET, server_hostname: process.env.ACTUAL_OPENID_SERVER_HOSTNAME, }; } return { issuer: { name: process.env.ACTUAL_OPENID_PROVIDER_NAME, authorization_endpoint: process.env.ACTUAL_OPENID_AUTHORIZATION_ENDPOINT, token_endpoint: process.env.ACTUAL_OPENID_TOKEN_ENDPOINT, userinfo_endpoint: process.env.ACTUAL_OPENID_USERINFO_ENDPOINT, }, client_id: process.env.ACTUAL_OPENID_CLIENT_ID, client_secret: process.env.ACTUAL_OPENID_CLIENT_SECRET, server_hostname: process.env.ACTUAL_OPENID_SERVER_HOSTNAME, }; })(); const openId = finalConfig?.openId ?? openIdEnv; if (!openId) { console.error('missing openid configuration'); process.exit(1); } const active = accountDb.getActiveLoginMethod(); if (active === 'openid') { console.log('openid already enabled'); process.exit(0); } try { if (accountDb.needsBootstrap()) { const result = await accountDb.bootstrap({ openId }); if (result?.error && result.error !== 'already-bootstrapped') { console.error(`bootstrap failed: ${result.error}`); process.exit(1); } } else { const result = await accountDb.enableOpenID({ openId }); if (result?.error) { console.error(`enable openid failed: ${result.error}`); process.exit(1); } } console.log('openid bootstrap complete'); } catch (err) { console.error('openid bootstrap error:', err); process.exit(1); }