fix: admin auth for prod Neon Auth deployment
Deploy to route.crispygoat.com / deploy (push) Successful in 3m59s

- getAdminUser now properly supports platform_admin with 0 brand links and loads full brand_ids
- createAdminUser action now inserts into admin_user_brands join table
- Admin layout surfaces the signed-in email on Access Denied
- AdminAccessDenied links to /login instead of dead-end /admin
- Main dashboard uses direct pool query instead of dead supabase shim
- Improved provision-admin.ts script for prod bootstrap (loads .env.production too)
This commit is contained in:
openclaw
2026-06-09 15:30:23 -06:00
parent 1af47698a1
commit d312783f3a
6 changed files with 100 additions and 44 deletions
+17 -10
View File
@@ -8,16 +8,23 @@ import pg from "pg";
import * as fs from "fs";
import * as path from "path";
// Load .env.local manually
const envPath = path.join(process.cwd(), ".env.local");
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf-8");
for (const line of envContent.split("\n")) {
const trimmed = line.trim();
if (trimmed && !trimmed.startsWith("#")) {
const [key, ...valueParts] = trimmed.split("=");
process.env[key.trim()] = valueParts.join("=").trim();
// Load .env.local (or .env.production) manually so the script works in prod bootstrap
const envFiles = [".env.local", ".env.production"];
for (const f of envFiles) {
const envPath = path.join(process.cwd(), f);
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, "utf-8");
for (const line of envContent.split("\n")) {
const trimmed = line.trim();
if (trimmed && !trimmed.startsWith("#")) {
const [key, ...valueParts] = trimmed.split("=");
const k = key.trim();
if (!process.env[k]) {
process.env[k] = valueParts.join("=").trim();
}
}
}
console.log(`[provision] loaded ${f}`);
}
}
@@ -106,7 +113,7 @@ async function main() {
}
console.log(`\n✅ ${email} is now provisioned as ${role}!`);
console.log(` They can access the admin at http://localhost:4000/admin`);
console.log(` They can access the admin at your production URL /admin (sign in first if needed).`);
} finally {
await pool.end();