Persist shared auth config in DB
Add ncue_app_config and /api/config/auth endpoints, and hydrate Auth0 config from the server so other browsers don't see the setup modal. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
75
server.js
75
server.js
@@ -32,6 +32,9 @@ const DB_NAME = must("DB_NAME");
|
||||
const DB_USER = must("DB_USER");
|
||||
const DB_PASSWORD = must("DB_PASSWORD");
|
||||
const TABLE = safeIdent(env("TABLE", "ncue_user") || "ncue_user");
|
||||
const CONFIG_TABLE = "ncue_app_config";
|
||||
const CONFIG_TOKEN = env("CONFIG_TOKEN", "").trim();
|
||||
const ADMIN_EMAILS = new Set(["dosangyoon@gmail.com", "dsyoon@ncue.net"]);
|
||||
|
||||
const pool = new pg.Pool({
|
||||
host: DB_HOST,
|
||||
@@ -98,6 +101,21 @@ async function ensureUserTable() {
|
||||
await pool.query(`alter table public.${TABLE} add column if not exists last_logout_at timestamptz`);
|
||||
}
|
||||
|
||||
async function ensureConfigTable() {
|
||||
await pool.query(`
|
||||
create table if not exists public.${CONFIG_TABLE} (
|
||||
key text primary key,
|
||||
value jsonb not null,
|
||||
updated_at timestamptz not null default now()
|
||||
)
|
||||
`);
|
||||
}
|
||||
|
||||
function isAdminEmail(email) {
|
||||
const e = String(email || "").trim().toLowerCase();
|
||||
return ADMIN_EMAILS.has(e);
|
||||
}
|
||||
|
||||
app.post("/api/auth/sync", async (req, res) => {
|
||||
try {
|
||||
await ensureUserTable();
|
||||
@@ -170,6 +188,63 @@ app.post("/api/auth/logout", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Shared auth config for all browsers (read-only public)
|
||||
app.get("/api/config/auth", async (_req, res) => {
|
||||
try {
|
||||
await ensureConfigTable();
|
||||
const r = await pool.query(`select value, updated_at from public.${CONFIG_TABLE} where key = $1`, ["auth"]);
|
||||
if (!r.rows?.length) return res.status(404).json({ ok: false, error: "not_set" });
|
||||
res.json({ ok: true, value: r.rows[0].value, updated_at: r.rows[0].updated_at });
|
||||
} catch (e) {
|
||||
res.status(500).json({ ok: false, error: "server_error" });
|
||||
}
|
||||
});
|
||||
|
||||
// Write auth config (protected by CONFIG_TOKEN)
|
||||
app.post("/api/config/auth", async (req, res) => {
|
||||
try {
|
||||
await ensureConfigTable();
|
||||
if (!CONFIG_TOKEN) return res.status(403).json({ ok: false, error: "config_token_not_set" });
|
||||
const token = String(req.headers["x-config-token"] || "").trim();
|
||||
if (token !== CONFIG_TOKEN) return res.status(403).json({ ok: false, error: "forbidden" });
|
||||
|
||||
const body = req.body && typeof req.body === "object" ? req.body : {};
|
||||
const auth0 = body.auth0 && typeof body.auth0 === "object" ? body.auth0 : {};
|
||||
const connections = body.connections && typeof body.connections === "object" ? body.connections : {};
|
||||
const allowedEmails = Array.isArray(body.allowedEmails) ? body.allowedEmails : [];
|
||||
|
||||
const domain = String(auth0.domain || "").trim();
|
||||
const clientId = String(auth0.clientId || "").trim();
|
||||
const googleConn = String(connections.google || "").trim();
|
||||
const emails = allowedEmails.map((x) => String(x).trim().toLowerCase()).filter(Boolean);
|
||||
|
||||
if (!domain || !clientId || !googleConn) {
|
||||
return res.status(400).json({ ok: false, error: "missing_fields" });
|
||||
}
|
||||
|
||||
// Optional safety: ensure at least one admin is present in allowedEmails
|
||||
if (emails.length && !emails.some(isAdminEmail)) {
|
||||
return res.status(400).json({ ok: false, error: "admin_email_missing" });
|
||||
}
|
||||
|
||||
const value = {
|
||||
auth0: { domain, clientId },
|
||||
connections: { google: googleConn },
|
||||
allowedEmails: emails,
|
||||
};
|
||||
|
||||
await pool.query(
|
||||
`insert into public.${CONFIG_TABLE} (key, value, updated_at)
|
||||
values ($1, $2::jsonb, now())
|
||||
on conflict (key) do update set value = excluded.value, updated_at = now()`,
|
||||
["auth", JSON.stringify(value)]
|
||||
);
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res.status(500).json({ ok: false, error: "server_error" });
|
||||
}
|
||||
});
|
||||
|
||||
// Serve static site
|
||||
app.use(express.static(__dirname, { extensions: ["html"] }));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user