[OWL] Wire setup route file, remove inline setup routes from server.js
This commit is contained in:
parent
0da63ae676
commit
071f759b8a
2 changed files with 37 additions and 56 deletions
|
|
@ -2,32 +2,54 @@ const express = require('express');
|
|||
const router = express.Router();
|
||||
const bcrypt = require('bcryptjs');
|
||||
const supabase = require('../services/supabase');
|
||||
const { asyncHandler } = require('../middleware/security');
|
||||
|
||||
// GET /setup — show wizard if no admin exists
|
||||
router.get('/', asyncHandler(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');
|
||||
|
||||
// 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) => {
|
||||
// POST /setup — create first admin securely (race-condition safe)
|
||||
router.post('/', asyncHandler(async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
if (!username || !password) return res.render('pages/setup', { error: 'All fields are required' });
|
||||
if (!username || !password) {
|
||||
return res.render('pages/setup', { error: 'Username and password are required' });
|
||||
}
|
||||
if (password.length < 6) {
|
||||
return res.render('pages/setup', { error: 'Password must be at least 6 characters' });
|
||||
}
|
||||
|
||||
// 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' });
|
||||
// Race-condition safety: double-check no admin exists
|
||||
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({
|
||||
const { error } = await supabase.from('portal_users').insert({
|
||||
username,
|
||||
password_hash: hash,
|
||||
role: 'admin',
|
||||
is_active: true,
|
||||
});
|
||||
// redirect to login after creation
|
||||
|
||||
if (error) {
|
||||
return res.render('pages/setup', { error: 'Failed to create admin: ' + error.message });
|
||||
}
|
||||
|
||||
res.redirect('/login');
|
||||
});
|
||||
}));
|
||||
|
||||
module.exports = router;
|
||||
|
|
|
|||
|
|
@ -154,48 +154,6 @@ app.get('/logout', (req, res) => {
|
|||
res.redirect('/login');
|
||||
});
|
||||
|
||||
app.get('/setup', asyncHandler(async (req, res) => {
|
||||
// Check if any user exists
|
||||
const { count } = await supabase
|
||||
.from('portal_users')
|
||||
.select('*', { count: 'exact', head: true });
|
||||
|
||||
if (count > 0) {
|
||||
return res.redirect('/login');
|
||||
}
|
||||
|
||||
res.render('pages/setup', { error: null });
|
||||
}));
|
||||
|
||||
app.post('/setup', asyncHandler(async (req, res) => {
|
||||
const { count } = await supabase
|
||||
.from('portal_users')
|
||||
.select('*', { count: 'exact', head: true });
|
||||
|
||||
if (count > 0) {
|
||||
return res.redirect('/login');
|
||||
}
|
||||
|
||||
const { username, password } = req.body;
|
||||
if (!username || !password || password.length < 6) {
|
||||
return res.render('pages/setup', { error: 'Username required and password must be at least 6 characters' });
|
||||
}
|
||||
|
||||
const hash = await bcrypt.hash(password, 10);
|
||||
const { error } = await supabase.from('portal_users').insert({
|
||||
username,
|
||||
password_hash: hash,
|
||||
role: 'admin',
|
||||
is_active: true,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
return res.render('pages/setup', { error: 'Failed to create admin. ' + error.message });
|
||||
}
|
||||
|
||||
res.redirect('/login');
|
||||
}));
|
||||
|
||||
// ============================================================
|
||||
// API ROUTES (for React dashboard + WhatsApp parser)
|
||||
// ============================================================
|
||||
|
|
@ -240,6 +198,7 @@ app.get('/api/stats', requireAuth, asyncHandler(async (req, res) => {
|
|||
// ============================================================
|
||||
|
||||
app.use('/', require('./routes/dashboard'));
|
||||
app.use('/setup', require('./routes/setup'));
|
||||
app.use('/loads', require('./routes/loads'));
|
||||
app.use('/shippers', require('./routes/shippers'));
|
||||
app.use('/vehicles', require('./routes/vehicles'));
|
||||
|
|
|
|||
Loading…
Reference in a new issue