From f1c75faba198253d1a59c689cef685c3717e3a10 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 7 Jun 2026 19:46:01 +0000 Subject: [PATCH] feat[agent]: add admin setup wizard (first-time admin creation) with secure password handling --- webapp/src/routes/setup.js | 33 ++++++++++++++ webapp/src/views/pages/setup.ejs | 74 +++++++++++++++----------------- 2 files changed, 68 insertions(+), 39 deletions(-) create mode 100644 webapp/src/routes/setup.js diff --git a/webapp/src/routes/setup.js b/webapp/src/routes/setup.js new file mode 100644 index 0000000..5c111d7 --- /dev/null +++ b/webapp/src/routes/setup.js @@ -0,0 +1,33 @@ +const express = require('express'); +const router = express.Router(); +const bcrypt = require('bcryptjs'); +const supabase = require('../services/supabase'); + +// GET /setup – show wizard if no admin exists +router.get('/', async (req, res) => { + const { count } = await supabase.from('portal_users').select('*', { count: 'exact', head: true }).eq('role', 'admin'); + if (count > 0) return res.redirect('/login'); // admin already exists + res.render('pages/setup', { error: null }); +}); + +// POST /setup – create first admin securely +router.post('/', async (req, res) => { + const { username, password } = req.body; + if (!username || !password) return res.render('pages/setup', { error: 'All fields are required' }); + + // ensure admin does not already exist (race‑condition safety) + const { data: existing } = await supabase.from('portal_users').select('id').eq('role', 'admin').single(); + if (existing) return res.render('pages/setup', { error: 'Admin already configured' }); + + const hash = await bcrypt.hash(password, 12); + await supabase.from('portal_users').insert({ + username, + password_hash: hash, + role: 'admin', + is_active: true, + }); + // redirect to login after creation + res.redirect('/login'); +}); + +module.exports = router; diff --git a/webapp/src/views/pages/setup.ejs b/webapp/src/views/pages/setup.ejs index f72cea7..1a8220c 100644 --- a/webapp/src/views/pages/setup.ejs +++ b/webapp/src/views/pages/setup.ejs @@ -1,46 +1,42 @@ - + - - - Setup — <%= appName %> - - + + + FreightDesk | Admin Setup + + - -
-