Skip to content

Commit

Permalink
feat: add protect route
Browse files Browse the repository at this point in the history
  • Loading branch information
lcaohoanq committed Jul 3, 2024
1 parent c4161a8 commit 1df469c
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 58 deletions.
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ app.get("/", (req: Request, res: Response) => {
res.send("Hello Developer");
});

app.use(protectRouter);
app.all("*", protectRouter);

app.use("/pass", passwordRouter);
app.use("/user", usersRouter);
Expand Down
2 changes: 2 additions & 0 deletions src/modules/password/pass.routes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Router } from "express";
import { wrapAsync } from "~/utils/handler";
import { accessTokenValidator } from "../user/user.middlewares";
import { registerPassword } from "./pass.controllers";
import { registerPasswordValidator } from "./pass.middleware";

const passwordRouter = Router();
passwordRouter.post(
"/updatePass",
accessTokenValidator,
registerPasswordValidator,
wrapAsync(registerPassword),
);
Expand Down
91 changes: 61 additions & 30 deletions src/modules/protectRouting/mapRouteWithRole.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
"login": {
"api": "/admin/login",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"createEmployee": {
"api": "/admin/createEmployee",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
},
":id": {
"api": "/admin/:id",
"method": "patch",
"role": "admin"
"role": 0,
"access_token": true
}
}
},
Expand All @@ -25,26 +28,31 @@
"/": {
"api": "/",
"method": "get",
"role": "admin"
"role": 0,
"access_token": false
},
"verify": {
"api": "/captcha/verify",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
}
}
},
{
"module": "employee",
"route": ""
"route": "",
"role": 0,
"access_token": false
},
{
"module": "menu",
"route": {
":language": {
"api": "/menu/:language",
"method": "get",
"role": "admin"
"role": 0,
"access_token": false
}
}
},
Expand All @@ -54,32 +62,38 @@
"google": {
"api": "/oauth/google",
"method": "get",
"role": "admin"
"role": 0,
"access_token": false
},
"google/callback": {
"api": "/oauth/google/callback",
"method": "get",
"role": "admin"
"role": 0,
"access_token": false
},
"facebook": {
"api": "/oauth/facebook",
"method": "get",
"role": "admin"
"role": 0,
"access_token": false
},
"facebook/callback": {
"api": "/oauth/facebook/callback",
"method": "get",
"role": "admin"
"role": 0,
"access_token": false
},
"login-success": {
"api": "/oauth/login-success",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"login-fail": {
"api": "/oauth/login-fail",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
}
}
},
Expand All @@ -89,12 +103,14 @@
"send-otp-phone": {
"api": "/otp/send-otp-phone",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
},
"send-otp-email": {
"api": "/otp/send-otp-email",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
}
}
},
Expand All @@ -104,7 +120,8 @@
"updatePass": {
"api": "/pass/updatePass",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
}
}
},
Expand All @@ -118,74 +135,88 @@
"register": {
"api": "/user/register",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"login": {
"api": "/user/login",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"forgot-password": {
"api": "/user/forgot-password",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"verify-otp": {
"api": "/user/verify-otp",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"reset-password": {
"api": "/user/reset-password",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"send-verify-account-otp": {
"api": "/user/send-verify-account-otp",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
},
"verify-account": {
"api": "/user/verify-account",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
},
"change-password": {
"api": "/user/change-password",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
},
"me": [
{
"api": "/user/me",
"method": "get",
"role": "admin"
"role": 0,
"access_token": true
},
{
"api": "/user/me",
"method": "patch",
"role": "admin"
"role": 0,
"access_token": true
}
],
"search": {
"api": "/user/search",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
},
"logout": {
"api": "/user/logout",
"method": "post",
"role": "admin"
"role": 0,
"access_token": true
},
"refresh-token": {
"api": "/user/refresh-token",
"method": "post",
"role": "admin"
"role": 0,
"access_token": false
},
"list-account": {
"api": "/user/list-account",
"method": "get",
"role": "admin"
"role": 0,
"access_token": false
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/modules/protectRouting/protect.messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const PROTECT_MESSAGES = {
ROLE_ADMIN: "You are admin",
ROLE_CUSTOMER: "You are customer",
ROLE_EMPLOYEE: "You are employee",
UNAUTHORIZED: "Unauthorized",
MISSING_ACCESS_TOKEN: "Missing access token",
} as const;
53 changes: 40 additions & 13 deletions src/modules/protectRouting/protect.routes.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,47 @@
import { Router } from "express";
import { wrapAsync } from "~/utils/handler";
import { NextFunction, Request, Response, Router } from "express";
import { accessTokenValidator } from "../user/user.middlewares";
const routes: Module[] = require("./mapRouteWithRole.json");

const protectRouter = Router();

protectRouter.post("/protect", (req, res) => {
let msg = "You are not authorized";
const { role } = req.body;
if (role === 0) {
return res.status(200).send("You are admin");
} else if (role === 1) {
return res.status(200).send("You are customer");
} else if (role === 2) {
return res.status(200).send("You are employee");
} else {
return res.status(401).json({ message: msg });
// Interface for a Route object within a module
interface Route {
api: string;
method: string;
role: number;
access_token: boolean;
}

// Interface for a Module object with nested routes
interface Module {
module: string;
route: { [key: string]: Route };
}

const openRoutes: string[] = [];

// Filter routes where access_token is false
routes.forEach((module: Module) => {
for (const key in module.route) {
if (!module.route[key].access_token) {
openRoutes.push(module.route[key].api);
}
}
});

protectRouter.use((req: Request, res: Response, next: NextFunction) => {
const url = req.path;

console.log("size: " + openRoutes.length);

openRoutes.forEach((route) => console.log(route));

console.log(openRoutes.includes(url));

if (openRoutes.includes(url)) {
return next();
}
accessTokenValidator(req, res, next);
});

export default protectRouter;
6 changes: 3 additions & 3 deletions src/modules/user/user.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { StatusCodes } from "http-status-codes";
import { pick } from "lodash";
import { ObjectId } from "mongodb";
import { HTTP_STATUS } from "~/constants/httpStatus";
import { UserList } from "~/constants/user.type";
import decrypt, { encrypt } from "~/utils/crypto";
import adminService from "../admin/admin.services";
import { OTP_MESSAGES } from "../otp/otp.messages";
import { UserRole } from "./user.enum";
import { USER_MESSAGES } from "./user.messages";
import {
ListAccountQuery,
Expand All @@ -20,9 +23,6 @@ import {
} from "./user.requests";
import User from "./user.schema";
import usersService from "./user.services";
import adminService from "../admin/admin.services";
import { UserList } from "~/constants/user.type";
import { UserRole } from "./user.enum";

export const registerController = async (
req: Request<ParamsDictionary, any, RegisterReqBody>,
Expand Down
4 changes: 2 additions & 2 deletions src/modules/user/user.middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "dotenv/config";
import { NextFunction, Request, Response } from "express";
import { ParamsDictionary } from "express-serve-static-core";
import { ParamSchema, checkSchema } from "express-validator";
import { StatusCodes } from "http-status-codes";
import { JsonWebTokenError } from "jsonwebtoken";
import { capitalize, escape } from "lodash";
import { ObjectId } from "mongodb";
Expand All @@ -12,6 +13,7 @@ import { ErrorEntity, ErrorWithStatus } from "~/errors/errors.entityError";
import { USER_MESSAGES } from "~/modules/user/user.messages";
import { isDeveloperAgent } from "~/utils/agent";
import { encrypt, hashPassword } from "~/utils/crypto";
import { numberToEnum } from "~/utils/handler";
import { verifyToken } from "~/utils/jwt";
import { isValidPhoneNumberForCountry, validate } from "~/utils/validation";
import { OTP_STATUS } from "../otp/otp.enum";
Expand All @@ -20,8 +22,6 @@ import otpService from "../otp/otp.services";
import { NoticeUser, UserRole, UserVerifyStatus } from "./user.enum";
import { LoginRequestBody, TokenPayload } from "./user.requests";
import usersService from "./user.services";
import { StatusCodes } from "http-status-codes";
import { numberToEnum } from "~/utils/handler";

//! Prevent db injection, XSS attack
export const paramSchema: ParamSchema = {
Expand Down
Loading

0 comments on commit 1df469c

Please sign in to comment.