90 lines
3.1 KiB
JavaScript
90 lines
3.1 KiB
JavaScript
import express from 'express';
|
|
import cookieParser from 'cookie-parser';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname, join } from 'path';
|
|
import ejsLayouts from 'express-ejs-layouts';
|
|
import logger from '../utils/logger.js';
|
|
import { requireAuth, handleLogin, handleLogout } from './auth.js';
|
|
import { csrfMiddleware, validateCsrf, validateCsrfFromBody } from './csrf.js';
|
|
import { asyncHandler, globalErrorHandler } from './errorHandler.js';
|
|
import dashboardRouter from './routes/dashboard.js';
|
|
import catalogRouter from './routes/catalog.js';
|
|
import catalogProductsRouter from './routes/catalogProducts.js';
|
|
import usersRouter from './routes/users.js';
|
|
import productsRouter from './routes/products.js';
|
|
import walletsRouter from './routes/wallets.js';
|
|
import purchasesRouter from './routes/purchases.js';
|
|
import auditRouter from './routes/audit.js';
|
|
import settingsRouter from './routes/settings.js';
|
|
import categoriesRouter from './routes/categories.js';
|
|
import paymentWalletsRouter from './routes/paymentWallets.js';
|
|
import locationsRouter from './routes/locations.js';
|
|
import seedRouter from './routes/seed.js';
|
|
import localesRouter from './routes/locales.js';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const app = express();
|
|
|
|
// Configure EJS as view engine with layouts
|
|
app.set('view engine', 'ejs');
|
|
app.set('views', join(__dirname, 'views'));
|
|
app.use(ejsLayouts);
|
|
app.set('layout', 'layout');
|
|
|
|
app.use(cookieParser());
|
|
app.use(express.urlencoded({ extended: true }));
|
|
app.use(express.json());
|
|
// Serve static assets from public directory
|
|
app.use(express.static(join(__dirname, 'public')));
|
|
|
|
app.get('/health', (req, res) => {
|
|
res.json({ status: 'ok', uptime: process.uptime() });
|
|
});
|
|
|
|
app.get('/login', (req, res) => {
|
|
res.render('auth-login', { error: null, layout: false, pageTitle: 'Login' });
|
|
});
|
|
|
|
app.post('/login', handleLogin);
|
|
app.get('/logout', handleLogout);
|
|
|
|
// CSRF token for all authenticated views
|
|
app.use(csrfMiddleware);
|
|
app.use(requireAuth);
|
|
|
|
// Apply CSRF validation to all state-changing routes
|
|
app.use(validateCsrf);
|
|
|
|
// Protect uploads behind auth with MIME hardening
|
|
app.use('/uploads', express.static(join(__dirname, '..', '..', 'uploads'), {
|
|
setHeaders: (res, path) => {
|
|
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
res.setHeader('Content-Disposition', 'attachment');
|
|
}
|
|
}));
|
|
|
|
app.use('/', dashboardRouter);
|
|
app.use('/catalog', catalogRouter);
|
|
app.use('/catalog', catalogProductsRouter);
|
|
app.use('/users', usersRouter);
|
|
app.use('/products', productsRouter);
|
|
app.use('/wallets', walletsRouter);
|
|
app.use('/purchases', purchasesRouter);
|
|
app.use('/audit', auditRouter);
|
|
app.use('/settings', settingsRouter);
|
|
app.use('/categories', categoriesRouter);
|
|
app.use('/locations', locationsRouter);
|
|
app.use('/payment-wallets', paymentWalletsRouter);
|
|
app.use('/seed', seedRouter);
|
|
app.use('/locales', localesRouter);
|
|
|
|
// Global error handler
|
|
app.use(globalErrorHandler);
|
|
|
|
export function startAdminPanel() {
|
|
const port = parseInt(process.env.ADMIN_PORT || '3001', 10);
|
|
app.listen(port, () => {
|
|
logger.info({ port }, 'Admin panel started');
|
|
});
|
|
}
|