File size: 3,431 Bytes
ffb4c35 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const { createServer } = require('http');
const { Server } = require('socket.io');
require('dotenv').config();
const authRoutes = require('./routes/auth');
const taskRoutes = require('./routes/tasks');
const userRoutes = require('./routes/users');
const documentRoutes = require('./routes/documents');
const analyticsRoutes = require('./routes/analytics');
const reportsRoutes = require('./routes/reports');
const { authenticateToken } = require('./middleware/auth');
const logger = require('./utils/logger');
const app = express();
const server = createServer(app);
const io = new Server(server, {
cors: {
origin: process.env.FRONTEND_URL || "http://localhost:3000",
methods: ["GET", "POST"]
}
});
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
// Middleware
app.use(helmet());
app.use(limiter);
app.use(cors({
origin: process.env.FRONTEND_URL || "http://localhost:3000",
credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// Logging
app.use(require('morgan')('combined', { stream: { write: message => logger.info(message.trim()) } }));
// Socket.io connection handling
io.use((socket, next) => {
const token = socket.handshake.auth.token;
if (!token) {
return next(new Error('Authentication error'));
}
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) return next(new Error('Authentication error'));
socket.userId = decoded.userId;
next();
});
});
io.on('connection', (socket) => {
logger.info(`User ${socket.userId} connected`);
socket.join(`user_${socket.userId}`);
socket.on('task:update', (data) => {
socket.to(`user_${data.assignee}`).emit('task:update', data);
});
socket.on('task:comment', (data) => {
socket.to(`user_${data.taskAssignee}`).emit('task:comment', data);
});
socket.on('disconnect', () => {
logger.info(`User ${socket.userId} disconnected`);
});
});
// Routes
app.use('/api/auth', authRoutes);
app.use('/api/tasks', authenticateToken, taskRoutes);
app.use('/api/users', authenticateToken, userRoutes);
app.use('/api/documents', authenticateToken, documentRoutes);
app.use('/api/analytics', authenticateToken, analyticsRoutes);
app.use('/api/reports', authenticateToken, reportsRoutes);
// Health check
app.get('/api/health', (req, res) => {
res.json({ status: 'OK', timestamp: new Date().toISOString() });
});
// Error handling middleware
app.use((err, req, res, next) => {
logger.error(err.stack);
res.status(500).json({ message: 'Something went wrong!' });
});
// 404 handler
app.use('*', (req, res) => {
res.status(404).json({ message: 'Route not found' });
});
// Database connection
mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/taskflow-pro', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
logger.info('Connected to MongoDB');
})
.catch((error) => {
logger.error('MongoDB connection error:', error);
process.exit(1);
});
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
logger.info(`Server running on port ${PORT}`);
});
module.exports = { app, io }; |