From e8d874132e4224e8fc4c18d73b74f88965efed06 Mon Sep 17 00:00:00 2001 From: Aharshi3614 Date: Tue, 23 Jun 2026 07:53:01 +0530 Subject: [PATCH 1/3] feat: add default admin user seeding on first server start --- backend/.env.example | 6 +++++- backend/seeders/adminSeeder.js | 26 ++++++++++++++++++++++++++ backend/server.js | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 backend/seeders/adminSeeder.js diff --git a/backend/.env.example b/backend/.env.example index 8d082aa..76538e3 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -15,4 +15,8 @@ URL_VECTORIZER_PATH=url_vectorizer.pkl GOOGLE_CLIENT_ID=your_google_client_id_here # MongoDB (used for scan history / analytics dashboard) -MONGODB_URI=mongodb+srv://:@/?retryWrites=true&w=majority \ No newline at end of file +MONGODB_URI=mongodb+srv://:@/?retryWrites=true&w=majority + +# Default Admin +ADMIN_EMAIL=admin@example.com +ADMIN_PASSWORD=admin123 \ No newline at end of file diff --git a/backend/seeders/adminSeeder.js b/backend/seeders/adminSeeder.js new file mode 100644 index 0000000..88cabd7 --- /dev/null +++ b/backend/seeders/adminSeeder.js @@ -0,0 +1,26 @@ +const User = require('../models/User'); + +const seedAdminUser = async () => { + try{ + const adminExists = await User.findOne({ role: 'admin' }); + if(!adminExists){ + const email = process.env.ADMIN_EMAIL || 'admin@example.com'; + const password = process.env.ADMIN_PASSWORD || 'admin123'; + + await User.create({ + email, + password, + role: 'admin', + name: 'Admin' + }); + + conso;e.log('Admin user created successfully'); + cnsole.log(`Email: ${email}`); + console.log(`Password: ${password}`); + } + }catch(error){ + console.error('Error seeding admin user:', error); + } +}; + +module.exports = seedAdminUser; \ No newline at end of file diff --git a/backend/server.js b/backend/server.js index da7b7bc..eb4954c 100644 --- a/backend/server.js +++ b/backend/server.js @@ -2,6 +2,7 @@ require("dotenv").config(); const dns = require("dns"); dns.setServers(["8.8.8.8", "1.1.1.1"]); // ensure SRV records resolve on all networks const express = require("express"); +const seedAdminUser = require("./seeders/adminSeeder"); const { getHealthStatus } = require('./utils/healthCheck'); const cors = require("cors"); const axios = require("axios"); @@ -19,6 +20,7 @@ const app = express(); mongoose .connect(process.env.MONGODB_URI) .then(() => console.log("✅ MongoDB connected")) + seedAdminUser() .catch((err) => console.error("❌ MongoDB connection error:", err)); app.use(cors()); From 4f5f85a197e55a4a1de7166f300300d559a0c137 Mon Sep 17 00:00:00 2001 From: Aharshi3614 Date: Tue, 23 Jun 2026 08:36:40 +0530 Subject: [PATCH 2/3] fix: remove duplicate routes, clean up API versioning --- backend/server.js | 16 ++++- docs/API.md | 146 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 docs/API.md diff --git a/backend/server.js b/backend/server.js index eb4954c..e2dac81 100644 --- a/backend/server.js +++ b/backend/server.js @@ -19,8 +19,10 @@ const app = express(); // Connect to MongoDB Atlas mongoose .connect(process.env.MONGODB_URI) - .then(() => console.log("✅ MongoDB connected")) - seedAdminUser() + .then(() => { + console.log("✅ MongoDB connected"); + seedAdminUser(); // ✅ Inside .then() + }) .catch((err) => console.error("❌ MongoDB connection error:", err)); app.use(cors()); @@ -31,9 +33,17 @@ const authRoutes = require("./routes/authRoutes"); const historyRoutes = require("./routes/historyRoutes"); const analyticsRoutes = require("./routes/analyticsRoutes"); const chatRoutes = require("./routes/chatRoutes"); + +// Versioned routes (v1) +app.use("/api/v1/auth", authRoutes); +app.use("/api/v1/history", historyRoutes); +app.use("/api/v1/analytics", analyticsRoutes); +app.use("/api/v1/chat", chatRoutes); + +// Keep old routes for backward compatibility app.use("/api/auth", authRoutes); app.use("/api/history", historyRoutes); -app.use("/analytics", analyticsRoutes); +app.use("/api/analytics", analyticsRoutes); app.use("/api/chat", chatRoutes); const { protect } = require("./middleware/authMiddleware"); diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..e649661 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,146 @@ +\# Spam Detection System - API Documentation + + + +\## Base URL + +http://localhost:3000/api/v1 + + + +\## Authentication + +All protected endpoints require a Bearer token: + +Authorization: Bearer + + + +\## Auth Routes + + + +| Method | Endpoint | Description | Auth | + +|--------|----------|-------------|------| + +| POST | `/auth/register` | Register new user | ❌ | + +| POST | `/auth/login` | Login user | ❌ | + +| GET | `/auth/profile` | Get user profile | ✅ | + + + +\--- + + + +\## Prediction Routes + + + +| Method | Endpoint | Description | Auth | + +|--------|----------|-------------|------| + +| POST | `/predict` | Predict spam/ham | ✅ | + +| POST | `/bulk-predict` | Bulk spam detection | ✅ | + +| POST | `/feedback` | Submit feedback | ✅ | + +| POST | `/analyze-email-header` | Analyze email headers | ✅ | + +| POST | `/bulk-predict/export` | Export predictions as CSV | ✅ | + + + +\--- + + + +\## Analytics Routes + + + +| Method | Endpoint | Description | Auth | + +|--------|----------|-------------|------| + +| GET | `/analytics/page-visits` | Page visit metrics | ✅ | + +| GET | `/analytics/visits-by-role` | Visits by role | ✅ | + + + +\--- + + + +\## Email Integration Routes + + + +| Method | Endpoint | Description | Auth | + +|--------|----------|-------------|------| + +| GET | `/gmail/auth-url` | Get Gmail auth URL | ✅ | + +| GET | `/gmail/emails` | Get Gmail emails | ✅ | + +| GET | `/outlook/auth-url` | Get Outlook auth URL | ✅ | + +| GET | `/outlook/emails` | Get Outlook emails | ✅ | + +| POST | `/scan-emails` | Scan connected emails | ✅ | + + + +\--- + + + +\## Public Routes + + + +| Method | Endpoint | Description | Auth | + +|--------|----------|-------------|------| + +| GET | `/health` | Health check | ❌ | + +| GET | `/api/wordcloud` | Word cloud data | ❌ | + +| GET | `/importance` | Feature importance | ❌ | + + + +\--- + + + +\## Response Format + + + +\### Success Response + +```json + +{ + + "success": true, + + "data": { ... } + +} + +``` + + + + + From be2d0917f0becfa6bf264262ba54052df554c6c6 Mon Sep 17 00:00:00 2001 From: Aharshi3614 Date: Tue, 23 Jun 2026 09:54:43 +0530 Subject: [PATCH 3/3] feat: add request ID to logs for request tracking --- backend/package-lock.json | 16 +++++++++++++++- backend/package.json | 3 ++- backend/server.js | 27 ++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 54a3d63..1760810 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -22,7 +22,8 @@ "jsonwebtoken": "^9.0.3", "mongoose": "^9.6.3", "multer": "^2.2.0", - "nodemon": "^3.1.14" + "nodemon": "^3.1.14", + "uuid": "^14.0.1" } }, "node_modules/@mongodb-js/saslprep": { @@ -3224,6 +3225,19 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/validator": { "version": "13.15.35", "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz", diff --git a/backend/package.json b/backend/package.json index 61879fd..e4fedef 100644 --- a/backend/package.json +++ b/backend/package.json @@ -24,6 +24,7 @@ "jsonwebtoken": "^9.0.3", "mongoose": "^9.6.3", "multer": "^2.2.0", - "nodemon": "^3.1.14" + "nodemon": "^3.1.14", + "uuid": "^14.0.1" } } diff --git a/backend/server.js b/backend/server.js index e2dac81..36a1f9d 100644 --- a/backend/server.js +++ b/backend/server.js @@ -5,6 +5,7 @@ const express = require("express"); const seedAdminUser = require("./seeders/adminSeeder"); const { getHealthStatus } = require('./utils/healthCheck'); const cors = require("cors"); +const { v4: uuidv4 } = require('uuid'); const axios = require("axios"); const mongoose = require("mongoose"); @@ -28,6 +29,30 @@ mongoose app.use(cors()); app.use(express.json()); +// ===== REQUEST ID MIDDLEWARE ===== +app.use((req, res, next) => { + // Generate a unique request ID + const requestId = uuidv4().substring(0, 8); // Shorten the UUID for easier logging + req.requestId = requestId; + + //Add to response headers + res.setHeader('X-Request-ID', requestId); + + // Log the request with the request ID + console.log(`[${requestId}] ${req.method} ${req.originalUrl}`); + + //Track time + const startTime = Date.now(); + + //Log when response is finished + res.on('finish', () => { + const duration = Date.now() - start; + console.log(`[${requestId}] ⬅️ ${req.method} ${req.originalUrl} completed in ${duration}ms (${res.statusCode})`); + }); + + next(); +}); + // Auth routes , History routes const authRoutes = require("./routes/authRoutes"); const historyRoutes = require("./routes/historyRoutes"); @@ -135,7 +160,7 @@ app.post("/predict", protect, async (req, res) => { res.json(response.data); } catch (error) { - console.error(error.message); + console.error(`[${req.requestId}]`,error.message); res.status(500).json({ error: "Something went wrong" }); } });