const express = require('express'); const http = require('http'); const { Server } = require('socket.io'); const cors = require('cors'); require('dotenv').config(); const app = express(); const server = http.createServer(app); const io = new Server(server, { cors: { origin: '*', methods: ['GET', 'POST'] } }); const authRoutes = require('./routes/auth'); const channelRoutes = require('./routes/channels'); app.use(cors()); app.use(express.json()); app.use('/api/auth', authRoutes); app.use('/api/channels', channelRoutes); app.get('/', (req, res) => { res.send('Secure Chat Backend Running'); }); const redisClient = require('./redis'); const db = require('./db'); io.on('connection', (socket) => { console.log('User connected:', socket.id); socket.on('join_channel', async (channelId) => { socket.join(channelId); console.log(`User ${socket.id} joined channel ${channelId}`); // Load recent messages try { const result = await db.query( `SELECT m.*, u.username, u.public_signing_key FROM messages m JOIN users u ON m.sender_id = u.id WHERE m.channel_id = $1 ORDER BY m.created_at DESC LIMIT 50`, [channelId] ); socket.emit('recent_messages', result.rows.reverse()); } catch (err) { console.error('Error fetching messages:', err); } }); socket.on('send_message', async (data) => { // data: { channelId, senderId, ciphertext, nonce, signature, keyVersion } const { channelId, senderId, ciphertext, nonce, signature, keyVersion } = data; try { // Store in DB const result = await db.query( `INSERT INTO messages (channel_id, sender_id, ciphertext, nonce, signature, key_version) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id, created_at`, [channelId, senderId, ciphertext, nonce, signature, keyVersion] ); const message = { id: result.rows[0].id, created_at: result.rows[0].created_at, ...data }; // Get username and signing key for display/verification const userRes = await db.query('SELECT username, public_signing_key FROM users WHERE id = $1', [senderId]); if (userRes.rows.length > 0) { message.username = userRes.rows[0].username; message.public_signing_key = userRes.rows[0].public_signing_key; } // Broadcast to channel io.to(channelId).emit('new_message', message); } catch (err) { console.error('Error saving message:', err); } }); socket.on('typing', (data) => { socket.to(data.channelId).emit('user_typing', { username: data.username }); }); socket.on('disconnect', () => { console.log('User disconnected:', socket.id); }); }); const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });