From 8371b1fd740099506095a93de742614b24a911b5 Mon Sep 17 00:00:00 2001 From: Uday Raj Date: Sat, 1 Nov 2025 12:51:13 +0530 Subject: [PATCH] Refactor index.js for improved readability and validation; added checks for page and limit parameters in /leader endpoint. --- backend/index.js | 187 +++++++++++++++++++++++++++-------------------- 1 file changed, 106 insertions(+), 81 deletions(-) diff --git a/backend/index.js b/backend/index.js index 1de6042..77592f4 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,101 +1,126 @@ -const express = require('express'); -const mongoose = require('mongoose'); -const User = require('./UserSchema'); -const cors = require('cors'); +const express = require("express"); +const mongoose = require("mongoose"); +const User = require("./UserSchema"); +const cors = require("cors"); const app = express(); -require('dotenv').config(); +require("dotenv").config(); app.use(express.json()); app.use(cors()); +mongoose + .connect(process.env.MONGO_URL, { + useNewUrlParser: true, + useUnifiedTopology: true, + }) + .then(() => console.log("Connected to MongoDB")) + .catch((err) => console.error("Could not connect to MongoDB:", err)); - -mongoose.connect(process.env.MONGO_URL, { useNewUrlParser: true, useUnifiedTopology: true }) - .then(() => console.log('Connected to MongoDB')) - .catch(err => console.error('Could not connect to MongoDB:', err)); - -app.get('/', (req, res) => { - res.send('Leaderboard'); +app.get("/", (req, res) => { + res.send("Leaderboard"); }); // GET /leader?page=1&limit=10&search=kunal -app.get('/leader', async (req, res) => { - try { - const page = parseInt(req.query.page) || 1; - const limit = parseInt(req.query.limit) || 10; - const search = req.query.search || ''; - const regex = new RegExp(search, 'i'); // Case-insensitive - - const skip = (page - 1) * limit; - - const totalCount = await User.countDocuments({ username: regex }); - const data = await User.find({ username: regex }) - .sort({ count: -1 }) - .skip(skip) - .limit(limit); - - res.status(200).json({ - totalCount, - totalPages: Math.ceil(totalCount / limit), - currentPage: page, - data, - }); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Internal Server Error' }); +app.get("/leader", async (req, res) => { + try { + const pageParam = req.query.page; + if (pageParam !== undefined) { + const page = parseInt(pageParam, 10); + if (isNaN(page) || page < 1 || page !== Number(pageParam)) { + return res + .status(400) + .json({ error: "Page must be a positive integer" }); + } + if (page > 10000) { + return res.status(400).json({ error: "Page number is too large" }); + } } - }); + const page = pageParam ? parseInt(pageParam, 10) : 1; - app.get('/leader/summary', async (req, res) => { - try { - const totalUsers = await User.countDocuments(); - - const aggregation = await User.aggregate([ - { - $group: { - _id: null, - totalSearches: { $sum: "$count" } - } - } - ]); - - res.status(200).json({ - totalUsers, - totalSearches: aggregation[0]?.totalSearches || 0 - }); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Internal Server Error' }); + const limitParam = req.query.limit; + if (limitParam !== undefined) { + const limit = parseInt(limitParam, 10); + if (isNaN(limit) || limit < 1 || limit !== Number(limitParam)) { + return res + .status(400) + .json({ error: "Limit must be a positive integer" }); + } + if (limit > 100) { + return res.status(400).json({ error: "Limit cannot exceed 100" }); + } } - }); - - - + const limit = limitParam ? parseInt(limitParam, 10) : 10; + + const search = req.query.search || ""; + const regex = new RegExp(search, "i"); // Case-insensitive + + const skip = (page - 1) * limit; + + const totalCount = await User.countDocuments({ username: regex }); + const data = await User.find({ username: regex }) + .sort({ count: -1 }) + .skip(skip) + .limit(limit); + + res.status(200).json({ + totalCount, + totalPages: Math.ceil(totalCount / limit), + currentPage: page, + data, + }); + } catch (err) { + console.error(err); + res.status(500).json({ error: "Internal Server Error" }); + } +}); + +app.get("/leader/summary", async (req, res) => { + try { + const totalUsers = await User.countDocuments(); + + const aggregation = await User.aggregate([ + { + $group: { + _id: null, + totalSearches: { $sum: "$count" }, + }, + }, + ]); -app.post('/user', async (req, res) => { - try { - const { username } = req.body; // Destructure username from req.body - if (!username) { - return res.status(400).send('Username is required'); - } + res.status(200).json({ + totalUsers, + totalSearches: aggregation[0]?.totalSearches || 0, + }); + } catch (err) { + console.error(err); + res.status(500).json({ error: "Internal Server Error" }); + } +}); + +app.post("/user", async (req, res) => { + try { + const { username } = req.body; // Destructure username from req.body + if (!username) { + return res.status(400).send("Username is required"); + } - let user = await User.findOne({ username }); - if (user) { - user.count += 1; - await user.save(); - res.status(200).send('User count incremented'); - } else { - const newUser = new User({ username, count: 1}); - await newUser.save(); - res.status(201).send('User created successfully'); - } - } catch (err) { - console.log(err); - res.status(500).send('Error: ' + err.message); + let user = await User.findOne({ username }); + if (user) { + user.count += 1; + await user.save(); + res.status(200).send("User count incremented"); + } else { + const newUser = new User({ username, count: 1 }); + await newUser.save(); + res.status(201).send("User created successfully"); } + } catch (err) { + console.log(err); + res.status(500).send("Error: " + err.message); + } }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { - console.log('listening on 3000'); + console.log("listening on 3000"); });