Skip to content
Open
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
6 changes: 5 additions & 1 deletion backend/routes/authRoute.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import express from 'express';
import { signUp ,signIn, google, refreshToken } from '../controllers/authController.js';
import { validateSignUp } from '../utils/validator.js';
import { authLimiter } from '../utils/rateLimiter.js';

const router = express.Router()

router.post('/signup',signUp)
router.use(authLimiter);
router.post('/signup',validateSignUp,signUp)
router.post('/signin',signIn)
router.post('/google',google)
router.post('/refreshToken',refreshToken)
Expand Down
37 changes: 23 additions & 14 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,61 @@ import vendorRoute from './routes/venderRoute.js'
import cors from 'cors'
import cookieParser from "cookie-parser";
import { cloudinaryConfig } from "./utils/cloudinaryConfig.js";

import morgan from 'morgan'; // NEW: Import morgan for request logging
import { specs, swaggerUi } from './utils/swagger.js';

const App = express();


App.use(express.json());
App.use(cookieParser())
App.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
// NEW: Added Morgan logging middleware
// This will log every incoming request (method, status, response time) to the console
// only when the application is running in a development environment.
if (process.env.NODE_ENV === 'development') {
App.use(morgan('dev'));
}

App.use(cookieParser())

dotenv.config();

// NEW: Environment Variable Validation
const requiredEnvs = ['mongo_uri', 'ACCESS_TOKEN', 'REFRESH_TOKEN'];
requiredEnvs.forEach((name) => {
if (!process.env[name]) {
console.error(`Error: Environment variable ${name} is missing.`);
process.exit(1);
}
});

const port = 3000;

mongoose
.connect(process.env.mongo_uri)
.then(console.log("connected"))
.catch((error) => console.error(error));



App.listen(port, () => {
console.log("server listening !");
});

const allowedOrigins = ['https://rent-a-ride-two.vercel.app', 'http://localhost:5173']; // Add allowed origins here
const allowedOrigins = ['https://rent-a-ride-two.vercel.app', 'http://localhost:5173'];

App.use(
cors({
origin: allowedOrigins,
methods:['GET', 'PUT', 'POST' ,'PATCH','DELETE'],
credentials: true, // Enables the Access-Control-Allow-Credentials header
credentials: true,
})
);


App.use('*', cloudinaryConfig);

// App.get('/*', (req, res) => res.sendFile(resolve(__dirname, '../public/index.html')));


App.use("/api/user", userRoute);
App.use("/api/auth", authRoute);
App.use("/api/admin",adminRoute);
App.use("/api/vendor",vendorRoute)



App.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
const message = err.message || "internal server error";
Expand All @@ -62,4 +71,4 @@ App.use((err, req, res, next) => {
message,
statusCode,
});
});
});
Empty file added backend/utils/rateLimiter.js
Empty file.
17 changes: 17 additions & 0 deletions backend/utils/swagger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import swaggerJsdoc from 'swagger-jsdoc';
import swaggerUi from 'swagger-ui-express';

const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'Rent-a-Ride API Documentation',
version: '1.0.0',
description: 'API for car rental platform',
},
},
apis: ['./routes/*.js'], // Points to your route files for docs
};

const specs = swaggerJsdoc(options);
export { specs, swaggerUi };
7 changes: 7 additions & 0 deletions backend/utils/validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const validateSignUp = (req, res, next) => {
const { username, email, password } = req.body;
if (!username || username.length < 3) return res.status(400).json({ message: "Username must be 3+ chars" });
if (!email.includes('@')) return res.status(400).json({ message: "Invalid email format" });
if (!password || password.length < 6) return res.status(400).json({ message: "Password must be 6+ chars" });
next();
};
25 changes: 12 additions & 13 deletions backend/utils/verifyUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import User from "../models/userModel.js";
import { refreshToken } from "../controllers/authController.js";

export const verifyToken = async (req, res, next) => {
// const accessToken = req.cookies.access_token;
// const refreshToken = req.cookies.refresh_token;
// Check for the authorization header
if (!req.headers.authorization) {
return next(errorHandler(403, "bad request no header provided"));
}

// Extract tokens from the Authorization header
const refreshToken = req.headers.authorization.split(" ")[1].split(",")[0];
const accessToken = req.headers.authorization.split(" ")[1].split(",")[1];

if (!accessToken) {
// Logic for when only a refresh token is present
if (!refreshToken) {
// res.clearCookie('access_token',"refresh_token")
return next(errorHandler(401, "You are not authenticated"));
}

Expand Down Expand Up @@ -45,28 +45,27 @@ export const verifyToken = async (req, res, next) => {
{ refreshToken: newRefreshToken }
);

req.user = decoded.id; //setting req.user so that next middleware in this cycle can acess it
req.user = decoded.id;
next();
} catch (error) {
console.log(error);
next(error);
}
} else {
// Logic for verifying an existing access token
try {
const decoded = jwt.verify(accessToken, process.env.ACCESS_TOKEN);
req.user = decoded.id; //setting req.user so that next middleware in this cycle can acess it
req.user = decoded.id;
next();
} catch (error) {
// START OF IMPROVED ERROR HANDLING
if (error.name === "TokenExpiredError") {
if (!refreshToken) {
return next(errorHandler(401, "You are not authenticated"));
}

// Access token expired, try to refresh it
//try to refresh it
// Explicitly tell the frontend the token expired so it can call the refresh endpoint
return next(errorHandler(401, "Access token expired"));
} else {
next(errorHandler(403, "Token is not valid"));
return next(errorHandler(403, "Token is not valid"));
}
// END OF IMPROVED ERROR HANDLING
}
}
};
};
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
"datauri": "^4.1.0",
"dotenv": "^16.4.5",
"express": "^4.18.2",
"express-rate-limit": "^8.2.1",
"framer-motion": "^11.1.7",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.2.0",
"morgan": "^1.10.1",
"multer": "^1.4.5-lts.1",
"nodemailer": "^6.9.13",
"nodemon": "^3.1.0",
"razorpay": "^2.9.3",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1",
"tailwind-merge": "^2.3.0",
"uuid": "^9.0.1"
}
Expand Down