Files
telegram-shop/src/admin/server.js

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');
});
}