Conversation
…th enhanced security features
Ibnekhalid
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
| }); | ||
| }; | ||
| router.post('/api/bot-chat', async (req, res) => { | ||
| router.post('/api/bot-chat', checkMessageLimit, async (req, res) => { |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we should introduce a rate-limiting middleware to the Express application. The express-rate-limit package is a well-known library for this purpose. We will configure a rate limiter to allow a maximum of 100 requests per 15 minutes and apply it to the /api/bot-chat route handler.
- Install the
express-rate-limitpackage. - Import the
express-rate-limitpackage in theroutes/main.jsfile. - Configure the rate limiter with appropriate settings.
- Apply the rate limiter to the
/api/bot-chatroute handler.
| @@ -6,3 +6,3 @@ | ||
| import { checkMessageLimit } from "./checkMessageLimit.js"; | ||
|
|
||
| import rateLimit from 'express-rate-limit'; | ||
| dotenv.config(); | ||
| @@ -12,2 +12,8 @@ | ||
| let COOKIE_EXPIRE_TIME = 1000 * 60 * 60 * 24 * 7; // 7 days in milliseconds | ||
|
|
||
| const limiter = rateLimit({ | ||
| windowMs: 15 * 60 * 1000, // 15 minutes | ||
| max: 100, // limit each IP to 100 requests per windowMs | ||
| }); | ||
|
|
||
| router.use(express.json()); | ||
| @@ -228,3 +234,3 @@ | ||
| }; | ||
| router.post('/api/bot-chat', checkMessageLimit, async (req, res) => { | ||
| router.post('/api/bot-chat', limiter, checkMessageLimit, async (req, res) => { | ||
| const userMessage = req.body.message; |
| @@ -25,3 +25,4 @@ | ||
| "pg": "^8.13.1", | ||
| "mbkauthe": "latest" | ||
| "mbkauthe": "latest", | ||
| "express-rate-limit": "^7.5.0" | ||
| }, |
| Package | Version | Security advisories |
| express-rate-limit (npm) | 7.5.0 | None |
| @@ -249,7 +253,6 @@ router.post('/api/bot-chat', async (req, res) => { | |||
| return res.status(500).json({ message: "Failed to fetch chat history.", error: dbError.message }); | |||
| } | |||
|
|
|||
|
|
|||
| conversationHistory.push({ role: "user", parts: [{ text: userMessage }] }); | |||
|
|
|||
| let aiResponseText; | |||
| @@ -271,13 +274,12 @@ router.post('/api/bot-chat', async (req, res) => { | |||
| return res.status(500).json({ error: "Deepseek API key not configured." }); | |||
| } | |||
| try { | |||
| // Transform conversation history to Deepseek format before calling Deepseek API | |||
| const deepseekFormattedHistory = transformGeminiToDeepseekHistory(conversationHistory); | |||
| aiResponseText = await Deepseek(deepseekApiKey, models_name, deepseekFormattedHistory, temperature); | |||
| } catch (deepseekError) { // Catch errors from Deepseek function | |||
| } catch (deepseekError) { | |||
| return res.status(500).json({ message: "Error processing Deepseek API.", error: deepseekError.message }); | |||
| } | |||
| } else { // Default to Gemini if models_name is not "deepseek-chat" or any other model you want to add later | |||
| } else { | |||
| let geminiApiKey; | |||
| geminiApiKey = process.env.GEMINI_API_KEY_maaz_waheed; | |||
|
|
|||
| @@ -286,16 +288,15 @@ router.post('/api/bot-chat', async (req, res) => { | |||
| } | |||
| try { | |||
| aiResponseText = await gemini(geminiApiKey, models_name, conversationHistory, temperature); | |||
| } catch (geminiError) { // Catch errors from gemini function | |||
| } catch (geminiError) { | |||
| return res.status(500).json({ message: "Error processing Gemini API.", error: geminiError.message }); | |||
| } | |||
| } | |||
|
|
|||
|
|
|||
| if (aiResponseText) { | |||
| conversationHistory.push({ role: "model", parts: [{ text: aiResponseText }] }); | |||
|
|
|||
| try { // Wrap database updates/inserts in try-catch | |||
| try { | |||
| if (chatId) { | |||
| await pool.query( | |||
| `UPDATE Ai_history | |||
| @@ -314,19 +315,16 @@ router.post('/api/bot-chat', async (req, res) => { | |||
| ); | |||
| req.newChatId = insertResult.rows[0].id; | |||
| } | |||
| } catch (dbError) { // Catch errors from database operations (pool.query) | |||
| } catch (dbError) { | |||
| console.error("Error updating/inserting chat history:", dbError); | |||
| return res.status(500).json({ message: "Failed to save chat history.", error: dbError.message }); | |||
| } | |||
|
|
|||
|
|
|||
| res.json({ aiResponse: aiResponseText, newChatId: req.newChatId }); | |||
| } else { | |||
| res.status(500).json({ message: "AI API returned empty response." }); | |||
| } | |||
|
|
|||
| } | |||
| ); | |||
| }); | |||
|
|
|||
| router.post('/api/chat/clear-history/:chatId', async (req, res) => { | |||
| const chatId = req.params.chatId; | |||
| @@ -345,27 +343,49 @@ router.post('/api/chat/clear-history/:chatId', async (req, res) => { | |||
| async function fetchUserSettings(username) { | |||
| try { | |||
| const settingsResult = await pool.query( | |||
| 'SELECT theme, font_size, ai_model, temperature FROM user_settings WHERE username = $1', | |||
| 'SELECT theme, font_size, ai_model, temperature, daily_message_limit FROM user_settings WHERE username = $1', | |||
| [username] | |||
| ); | |||
|
|
|||
| // Fetch today's message count for the user | |||
| const today = new Date().toISOString().split("T")[0]; // Get current date in YYYY-MM-DD format | |||
| const messageLog = await pool.query( | |||
| 'SELECT message_count FROM user_message_logs WHERE username = $1 AND date = $2', | |||
| [username, today] | |||
| ); | |||
|
|
|||
| const messageCount = messageLog.rows[0]?.message_count || 0; // Default to 0 if no record exists | |||
|
|
|||
| if (settingsResult.rows.length > 0) { | |||
| return settingsResult.rows[0]; | |||
| const settings = settingsResult.rows[0]; | |||
| return { | |||
| theme: settings.theme || 'dark', | |||
| font_size: settings.font_size || 16, | |||
| ai_model: settings.ai_model || 'default', | |||
| temperature: settings.temperature || 1.0, | |||
| dailyLimit: settings.daily_message_limit || 100, // Default daily limit | |||
| messageCount: messageCount // Messages used today | |||
| }; | |||
| } else { | |||
| // Default settings if no settings found for the user | |||
| return { | |||
| theme: 'dark', | |||
| font_size: 16, | |||
| ai_model: 'default', | |||
| temperature: 1.0 | |||
| temperature: 1.0, | |||
| dailyLimit: 100, // Default daily limit | |||
| messageCount: messageCount // Messages used today | |||
| }; | |||
| } | |||
| } catch (error) { | |||
Check failure
Code scanning / CodeQL
Missing rate limiting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 12 months ago
To fix the problem, we need to introduce rate limiting to the route handler that performs database access. The best way to achieve this is by using the express-rate-limit middleware. This middleware allows us to limit the number of requests a client can make to the server within a specified time window.
We will:
- Install the
express-rate-limitpackage. - Import the
express-rate-limitpackage in theroutes/main.jsfile. - Set up a rate limiter with appropriate configuration.
- Apply the rate limiter to the specific route handler that performs database access.
| @@ -6,2 +6,3 @@ | ||
| import { checkMessageLimit } from "./checkMessageLimit.js"; | ||
| import rateLimit from 'express-rate-limit'; | ||
|
|
||
| @@ -12,2 +13,6 @@ | ||
| let COOKIE_EXPIRE_TIME = 1000 * 60 * 60 * 24 * 7; // 7 days in milliseconds | ||
| const limiter = rateLimit({ | ||
| windowMs: 15 * 60 * 1000, // 15 minutes | ||
| max: 100, // limit each IP to 100 requests per windowMs | ||
| }); | ||
| router.use(express.json()); | ||
| @@ -228,3 +233,3 @@ | ||
| }; | ||
| router.post('/api/bot-chat', checkMessageLimit, async (req, res) => { | ||
| router.post('/api/bot-chat', limiter, checkMessageLimit, async (req, res) => { | ||
| const userMessage = req.body.message; |
| @@ -25,3 +25,4 @@ | ||
| "pg": "^8.13.1", | ||
| "mbkauthe": "latest" | ||
| "mbkauthe": "latest", | ||
| "express-rate-limit": "^7.5.0" | ||
| }, |
| Package | Version | Security advisories |
| express-rate-limit (npm) | 7.5.0 | None |
No description provided.