121 lines
3.5 KiB
JavaScript
121 lines
3.5 KiB
JavaScript
const express = require('express');
|
|
const mongoose = require('mongoose');
|
|
const session = require('express-session');
|
|
const MongoStore = require('connect-mongo');
|
|
const path = require('path');
|
|
const helmet = require('helmet');
|
|
const compression = require('compression');
|
|
const cors = require('cors');
|
|
const morgan = require('morgan');
|
|
const rateLimit = require('express-rate-limit');
|
|
require('dotenv').config();
|
|
|
|
const app = express();
|
|
|
|
// Security middleware
|
|
app.use(helmet({
|
|
contentSecurityPolicy: {
|
|
directives: {
|
|
defaultSrc: ["'self'"],
|
|
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com", "https://cdnjs.cloudflare.com"],
|
|
fontSrc: ["'self'", "https://fonts.gstatic.com"],
|
|
scriptSrc: ["'self'", "'unsafe-inline'", "https://cdnjs.cloudflare.com"],
|
|
imgSrc: ["'self'", "data:", "https:"],
|
|
connectSrc: ["'self'", "ws:", "wss:"]
|
|
}
|
|
}
|
|
}));
|
|
|
|
// Rate limiting
|
|
const limiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 100 // limit each IP to 100 requests per windowMs
|
|
});
|
|
app.use('/api/', limiter);
|
|
|
|
// Middleware
|
|
app.use(compression());
|
|
app.use(cors());
|
|
app.use(morgan('combined'));
|
|
app.use(express.json({ limit: '10mb' }));
|
|
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
|
|
// Static files
|
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
app.use('/uploads', express.static(path.join(__dirname, 'public/uploads')));
|
|
|
|
// View engine
|
|
app.set('view engine', 'ejs');
|
|
app.set('views', path.join(__dirname, 'views'));
|
|
|
|
// Database connection
|
|
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/smartsoltech', {
|
|
useNewUrlParser: true,
|
|
useUnifiedTopology: true,
|
|
})
|
|
.then(() => console.log('✓ MongoDB connected'))
|
|
.catch(err => console.error('✗ MongoDB connection error:', err));
|
|
|
|
// Session configuration
|
|
app.use(session({
|
|
secret: process.env.SESSION_SECRET || 'your-secret-key',
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
store: MongoStore.create({
|
|
mongoUrl: process.env.MONGODB_URI || 'mongodb://localhost:27017/smartsoltech',
|
|
touchAfter: 24 * 3600 // lazy session update
|
|
}),
|
|
cookie: {
|
|
secure: process.env.NODE_ENV === 'production',
|
|
httpOnly: true,
|
|
maxAge: 1000 * 60 * 60 * 24 * 7 // 7 days
|
|
}
|
|
}));
|
|
|
|
// Routes
|
|
app.use('/', require('./routes/index'));
|
|
app.use('/api/auth', require('./routes/auth'));
|
|
app.use('/api/portfolio', require('./routes/portfolio'));
|
|
app.use('/api/services', require('./routes/services'));
|
|
app.use('/api/calculator', require('./routes/calculator'));
|
|
app.use('/api/contact', require('./routes/contact'));
|
|
app.use('/api/media', require('./routes/media'));
|
|
app.use('/admin', require('./routes/admin'));
|
|
|
|
// PWA Service Worker
|
|
app.get('/sw.js', (req, res) => {
|
|
res.sendFile(path.join(__dirname, 'public', 'sw.js'));
|
|
});
|
|
|
|
// PWA Manifest
|
|
app.get('/manifest.json', (req, res) => {
|
|
res.sendFile(path.join(__dirname, 'public', 'manifest.json'));
|
|
});
|
|
|
|
// Error handling middleware
|
|
app.use((err, req, res, next) => {
|
|
console.error(err.stack);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: process.env.NODE_ENV === 'production'
|
|
? 'Something went wrong!'
|
|
: err.message
|
|
});
|
|
});
|
|
|
|
// 404 handler
|
|
app.use((req, res) => {
|
|
res.status(404).render('404', {
|
|
title: '404 - Страница не найдена',
|
|
message: 'Запрашиваемая страница не найдена'
|
|
});
|
|
});
|
|
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`🚀 Server running on port ${PORT}`);
|
|
console.log(`🌐 Visit: http://localhost:${PORT}`);
|
|
});
|
|
|
|
module.exports = app; |