Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ GOOGLE_CLIENT_ID=your_google_client_id_here
# MongoDB (used for scan history / analytics dashboard)
MONGODB_URI=mongodb+srv://<user>:<password>@<cluster>/<db>?retryWrites=true&w=majority

# Default Admin
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=admin123
# IMAP scheduled scanning (issue #186) — used to encrypt stored inbox credentials at rest.
# Generate with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
IMAP_ENCRYPTION_KEY=
# Where the sqlite store for IMAP connections/scan history lives (defaults to backend/imap_connections.db)
IMAP_DB_PATH=
IMAP_DB_PATH=
16 changes: 15 additions & 1 deletion backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
26 changes: 26 additions & 0 deletions backend/seeders/adminSeeder.js
Original file line number Diff line number Diff line change
@@ -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;
43 changes: 40 additions & 3 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ const validateEnv = require('./utils/validateEnv');
validateEnv(); // Validate environment variables
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 { v4: uuidv4 } = require('uuid');
const axios = require("axios");
const mongoose = require("mongoose");

Expand All @@ -21,7 +23,10 @@ const app = express();
// Connect to MongoDB Atlas
mongoose
.connect(process.env.MONGODB_URI)
.then(() => console.log("✅ MongoDB connected"))
.then(() => {
console.log("✅ MongoDB connected");
seedAdminUser(); // ✅ Inside .then()
})
.catch((err) => console.error("❌ MongoDB connection error:", err));

app.use(cors());
Expand All @@ -35,14 +40,46 @@ app.get('/health', (req, res) => {
});
});

// ===== 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");
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");
Expand Down Expand Up @@ -134,7 +171,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" });
}
});
Expand Down
146 changes: 146 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
@@ -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 <your\_token>



\## 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

{

&#x20; "success": true,

&#x20; "data": { ... }

}

```





Loading