general chat

This commit is contained in:
gprunet
2026-01-12 17:27:07 +01:00
parent e053d0faa7
commit f79e6bd9fc
7 changed files with 128 additions and 7 deletions
-4
View File
@@ -5,10 +5,6 @@ WORKDIR /app
COPY package*.json ./
RUN npm install
RUN npm install dotenv
RUN npm install pg
RUN npm install bcrypt
RUN npm install jsonwebtoken
COPY . .
+19 -1
View File
@@ -1,20 +1,38 @@
const express = require('express');
const http = require('http');
const cors = require('cors');
const {Server} = require('socket.io');
const authRouter = require('./routes/auth');
const chatRouter = require('./routes/global_chat');
const {waitForDb, createTables} = require('./db');
const setupSocketIO = require('./services/socket');
const app = express();
const server = http.createServer(app);
const io = new Server(server,
{
cors:
{
origin: "*",
methods: ["GET", "POST"]
}
});
app.use(cors());
app.use(express.json());
setupSocketIO(io);
async function startServer()
{
await waitForDb();
await createTables();
app.use('/api/auth', authRouter);
app.use('/api/global_chat', chatRouter);
app.get('/api', (req, res) => res.send('Backend running'));
app.listen(3001, () =>
server.listen(3001, () =>
{
console.log('Server ready and listening');
});
+7 -1
View File
@@ -1,6 +1,12 @@
{
"dependencies":
{
"express": "^4.18.2"
"express": "^4.18.2",
"pg": "^8.11.3",
"bcrypt": "^5.1.0",
"jsonwebtoken": "^9.0.2",
"dotenv": "^17.2.3",
"socket.io": "^4.6.1",
"cors": "^2.8.5"
}
}
+20
View File
@@ -0,0 +1,20 @@
const express = require('express');
const router = express.Router();
const chatService = require('../services/global_chat');
const authenticateToken = require('../middleware/auth');
router.get('/messages', authenticateToken, async(req, res) =>
{
try
{
const messages = await chatService.getRecentMessages(50);
res.json(messages);
}
catch(err)
{
console.error(err);
res.status(500).json({error: 'Server error'});
}
});
module.exports = router;
+4 -1
View File
@@ -21,7 +21,10 @@ async function login(username, password)
const token = jwt.sign
(
{userId: user.id},
{
userId: user.id,
username: username
},
process.env.JWT_SECRET,
{expiresIn: '1h'}
);
+31
View File
@@ -0,0 +1,31 @@
const {query} = require('../db');
async function saveMessage(userId, content)
{
const result = await query
(
'INSERT INTO messages (sender_id, content) VALUES ($1 ,$2) RETURNING *',
[userId, content]
);
return (result.rows[0]);
}
async function getRecentMessages(limit = 50)
{
const result = await query
(
`SELECT m.sender_id, m.content, m.created_at, u.username
FROM messages m
JOIN users u ON m.sender_id = u.id
ORDER BY m.created_at DESC
LIMIT $1`,
[limit]
);
return (result.rows.reverse());
}
module.exports =
{
saveMessage,
getRecentMessages
};
+47
View File
@@ -0,0 +1,47 @@
const jwt = require('jsonwebtoken');
const chatService = require('./global_chat');
function setupSocketIO(io)
{
io.use((socket, next) =>
{
const token = socket.handshake.auth.token;
if (!token)
return (next(new Error('Authentication error')));
try
{
const decoded = jwt.verify(token, process.env.JWT_SECRET);
socket.user = decoded;
next();
}
catch(err)
{
next(new Error('Authentication error'));
}
});
io.on('connection', (socket) =>
{
console.log(`User connected: ${socket.user.username}`);
socket.join('general-chat');
socket.on('chat-message', async(data) =>
{
const message = await chatService.saveMessage(socket.user.userId, data.content);
io.to('general-chat').emit('chat-message',
{
id:message.id,
username: socket.user.username,
content: message.content,
created_at: message.created_at
});
});
socket.on('disconnect', () =>
{
console.log(`User disconnected: ${socket.user.username}`);
});
});
}
module.exports = setupSocketIO;