fix(auth+bugs): optional auth bypass, login routes, conform column name, panel metadata fields, login page: index.js

This commit is contained in:
Zac Gaetano 2026-05-15 23:40:12 -04:00
parent ada5597f79
commit f745122ef0

View file

@ -6,7 +6,8 @@ import ConnectPgSimple from 'connect-pg-simple';
import pool from './db/pool.js'; import pool from './db/pool.js';
import { errorHandler } from './middleware/errors.js'; import { errorHandler } from './middleware/errors.js';
// Import routes // Routes
import authRouter from './routes/auth.js';
import assetsRouter from './routes/assets.js'; import assetsRouter from './routes/assets.js';
import projectsRouter from './routes/projects.js'; import projectsRouter from './routes/projects.js';
import binsRouter from './routes/bins.js'; import binsRouter from './routes/bins.js';
@ -17,14 +18,13 @@ import recordersRouter from './routes/recorders.js';
import settingsRouter from './routes/settings.js'; import settingsRouter from './routes/settings.js';
import amppRouter from './routes/ampp.js'; import amppRouter from './routes/ampp.js';
const app = express(); const app = express();
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
// Middleware // ── Middleware ────────────────────────────────────────────────────────────────
app.use(cors()); app.use(cors({ origin: true, credentials: true }));
app.use(express.json({ limit: '50mb' })); app.use(express.json({ limit: '50mb' }));
// Session store
const PgSession = ConnectPgSimple(session); const PgSession = ConnectPgSimple(session);
app.use( app.use(
@ -32,38 +32,44 @@ app.use(
store: new PgSession({ store: new PgSession({
pool, pool,
tableName: 'sessions', tableName: 'sessions',
// Prune expired sessions every hour
pruneSessionInterval: 3600,
}), }),
secret: process.env.SESSION_SECRET || 'your-secret-key', secret: process.env.SESSION_SECRET || 'change-me-in-production',
resave: false, resave: false,
saveUninitialized: false, saveUninitialized: false,
cookie: { cookie: {
secure: process.env.NODE_ENV === 'production', secure: process.env.NODE_ENV === 'production',
httpOnly: true, httpOnly: true,
maxAge: 1000 * 60 * 60 * 24, // 24 hours maxAge: 1000 * 60 * 60 * 24, // 24 h
}, },
}) })
); );
// Health check // ── Health (no auth) ──────────────────────────────────────────────────────────
app.get('/health', (req, res) => { app.get('/health', (_req, res) => res.json({ status: 'ok' }));
res.json({ status: 'ok' });
});
// API Routes // ── API Routes ────────────────────────────────────────────────────────────────
app.use('/api/v1/assets', assetsRouter); // Auth routes are always open (login/logout don't require a session)
app.use('/api/v1/projects', projectsRouter); app.use('/api/v1/auth', authRouter);
app.use('/api/v1/bins', binsRouter);
app.use('/api/v1/jobs', jobsRouter); // All other routes are gated by requireAuth (no-op unless AUTH_ENABLED=true)
app.use('/api/v1/capture', captureRouter); app.use('/api/v1/assets', assetsRouter);
app.use('/api/v1/upload', uploadRouter); app.use('/api/v1/projects', projectsRouter);
app.use('/api/v1/bins', binsRouter);
app.use('/api/v1/jobs', jobsRouter);
app.use('/api/v1/capture', captureRouter);
app.use('/api/v1/upload', uploadRouter);
app.use('/api/v1/recorders', recordersRouter); app.use('/api/v1/recorders', recordersRouter);
app.use('/api/v1/settings', settingsRouter); app.use('/api/v1/settings', settingsRouter);
app.use('/api/v1/ampp', amppRouter); app.use('/api/v1/ampp', amppRouter);
// Error handler // ── Error handler ─────────────────────────────────────────────────────────────
app.use(errorHandler); app.use(errorHandler);
// Start server // ── Start ────────────────────────────────────────────────────────────────────
app.listen(PORT, () => { app.listen(PORT, () => {
const authMode = process.env.AUTH_ENABLED === 'true' ? 'ENABLED' : 'DISABLED (set AUTH_ENABLED=true for production)';
console.log(`MAM API listening on port ${PORT}`); console.log(`MAM API listening on port ${PORT}`);
console.log(`Authentication: ${authMode}`);
}); });