feat(account, order, plan, profile, redis): enhance functionality and security

- Updated CORS settings for frontend compatibility.
- Integrated Redis URL configuration.
- Improved login response structure in account service.
- Added role-based authorization for order and plan management.
- Enhanced error handling and logging in profile and plan services.
- Updated Swagger documentation for clarity on order statuses.
- Configured Redis connection for better performance.
This commit is contained in:
abumahid
2026-04-26 19:14:37 +06:00
parent 2d54031c33
commit 61fd639faf
12 changed files with 54 additions and 19 deletions
Vendored
+1 -1
View File
@@ -13,7 +13,7 @@ const swaggerSpec = swaggerJSDoc(swaggerOptions);
app.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec)); app.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec));
// middleware // middleware
app.use(cors({ app.use(cors({
origin: ["http://localhost:3000"], origin: ["http://localhost:5173"],
methods: ["GET", "POST", "PATCH", "DELETE", "PUT"], methods: ["GET", "POST", "PATCH", "DELETE", "PUT"],
credentials: true credentials: true
})); }));
+1
View File
@@ -22,4 +22,5 @@ export const configs = {
cloud_api_key: process.env.CLOUD_API_KEY, cloud_api_key: process.env.CLOUD_API_KEY,
cloud_api_secret: process.env.CLOUD_API_SECRET, cloud_api_secret: process.env.CLOUD_API_SECRET,
}, },
redis_url: process.env.REDIS_URL,
}; };
+2 -4
View File
@@ -32,7 +32,7 @@ const verify_account_using_link = catchAsync(async (req, res) => {
const login_user = catchAsync(async (req, res) => { const login_user = catchAsync(async (req, res) => {
const result = await account_services.login_user_into_db(req); const result = await account_services.login_user_into_db(req);
// set access token into cookie // set access token into cookie
res.cookie("access_token", result, { res.cookie("access_token", result.accessToken, {
secure: configs.env === "production", secure: configs.env === "production",
httpOnly: true, httpOnly: true,
}); });
@@ -40,9 +40,7 @@ const login_user = catchAsync(async (req, res) => {
statusCode: 200, statusCode: 200,
success: true, success: true,
message: "User logged in successfully", message: "User logged in successfully",
data: { data: result,
accessToken: result,
},
}); });
}); });
const get_user_account = catchAsync(async (req, res) => { const get_user_account = catchAsync(async (req, res) => {
+24 -1
View File
@@ -60,6 +60,10 @@ const create_account_into_db = async (req) => {
subject: "Welcome to Quick Launch - Verification OTP", subject: "Welcome to Quick Launch - Verification OTP",
email: payload.email, email: payload.email,
textBody: "You can use otp or verification link for verifying your account" textBody: "You can use otp or verification link for verifying your account"
}, {
attempts: 1,
removeOnComplete: true,
removeOnFail: true,
}); });
return null; return null;
}; };
@@ -143,6 +147,15 @@ const login_user_into_db = async (req) => {
where: { where: {
email: payload.email, email: payload.email,
}, },
select: {
id: true,
email: true,
role: true,
isAccountVerified: true,
isDeleted: true,
password: true,
profile: true,
},
}); });
// check if account exists // check if account exists
if (!account) { if (!account) {
@@ -167,7 +180,17 @@ const login_user_into_db = async (req) => {
role: account.role, role: account.role,
accountId: account.id, accountId: account.id,
}, configs.jwt.access_token, configs.jwt.access_expires); }, configs.jwt.access_token, configs.jwt.access_expires);
return accessToken; const finalOutputData = {
id: account.id,
email: account.email,
role: account.role,
shopName: account?.profile?.shopName,
shopLogo: account?.profile?.shopLogo,
};
return {
accessToken,
profile: finalOutputData
};
}; };
const get_user_account_from_db = async (req) => { const get_user_account_from_db = async (req) => {
const user = req?.user; const user = req?.user;
+4
View File
@@ -147,6 +147,10 @@ const update_order_into_db = async (req) => {
const delete_order_from_db = async (req) => { const delete_order_from_db = async (req) => {
// define your own login here // define your own login here
const { id } = req.params; const { id } = req.params;
const user = req.user;
if (user?.role !== "ADMIN") {
throw new AppError("You are not authorized to perform this action", 403);
}
const result = await prisma.order.delete({ where: { id } }); const result = await prisma.order.delete({ where: { id } });
return result; return result;
}; };
+6 -2
View File
@@ -3,7 +3,11 @@ export const orderSwaggerDocs = {
post: { post: {
tags: ["order"], tags: ["order"],
summary: "Create new order", summary: "Create new order",
description: "", description: ` INITIATED
CONFIRMED
ONGOING
DELIVERED
CANCELLED`,
requestBody: { requestBody: {
required: true, required: true,
content: { content: {
@@ -115,7 +119,7 @@ export const orderSwaggerDocs = {
}, },
patch: { patch: {
tags: ["order"], tags: ["order"],
summary: "Update order", summary: "Update order -(Admin route)",
description: "", description: "",
parameters: [ parameters: [
{ {
+4 -3
View File
@@ -1,11 +1,12 @@
import { Router } from "express"; import { Router } from "express";
import auth from "../../middlewares/auth.js";
import RequestValidator from "../../middlewares/request_validator.js"; import RequestValidator from "../../middlewares/request_validator.js";
import { plan_controller } from "./plan.controller.js"; import { plan_controller } from "./plan.controller.js";
import { plan_validations } from "./plan.validation.js"; import { plan_validations } from "./plan.validation.js";
const router = Router(); const router = Router();
router.get("/", plan_controller.get_all_plan); router.get("/", plan_controller.get_all_plan);
router.post("/", RequestValidator(plan_validations.create_plan), plan_controller.create_plan); router.post("/", RequestValidator(plan_validations.create_plan), auth("ADMIN"), plan_controller.create_plan);
router.get("/:id", plan_controller.get_single_plan); router.get("/:id", plan_controller.get_single_plan);
router.patch("/:id", RequestValidator(plan_validations.update_plan), plan_controller.update_plan); router.patch("/:id", RequestValidator(plan_validations.update_plan), auth("ADMIN"), plan_controller.update_plan);
router.delete("/:id", plan_controller.delete_plan); router.delete("/:id", auth("ADMIN"), plan_controller.delete_plan);
export default router; export default router;
+1 -1
View File
@@ -17,7 +17,7 @@ const get_single_plan_from_db = async (req) => {
}; };
const create_plan_into_db = async (req) => { const create_plan_into_db = async (req) => {
// define your own login here // define your own login here
const user = req.user; const user = req?.user;
if (user?.role !== "ADMIN") { if (user?.role !== "ADMIN") {
throw new AppError("You dont have permission to create plan information.!!!", 401); throw new AppError("You dont have permission to create plan information.!!!", 401);
} }
+1
View File
@@ -4,6 +4,7 @@ const update_profile_into_db = async (req) => {
const user = req?.user; const user = req?.user;
const payload = req?.body; const payload = req?.body;
const file = req?.file; const file = req?.file;
console.log(payload);
// check file and upload to cloud // check file and upload to cloud
if (file) { if (file) {
const cloudRes = await uploadCloud(file); const cloudRes = await uploadCloud(file);
+7 -4
View File
@@ -1,4 +1,7 @@
export const redisConnection = { import { Redis } from "ioredis";
host: "127.0.0.1", import { configs } from "../configs/index.js";
port: 6379, export const redisConnection = new Redis(configs.redis_url, {
}; tls: {},
maxRetriesPerRequest: null,
enableReadyCheck: false,
});
+2 -2
View File
@@ -24,8 +24,8 @@ export const swaggerOptions = {
...supportSwaggerDocs, ...supportSwaggerDocs,
}, },
servers: configs.env === "production" servers: configs.env === "production"
? [{ url: "https://live-url.com" }, { url: "http://localhost:5000" }] ? [{ url: "https://quicklunch-server.onrender.com" }, { url: "http://localhost:5000" }]
: [{ url: "http://localhost:5000" }, { url: "https://live-url.com" }], : [{ url: "http://localhost:5000" }, { url: "https://quicklunch-server.onrender.com" }],
components: { components: {
securitySchemes: { securitySchemes: {
AuthorizationToken: { AuthorizationToken: {
+1 -1
View File
@@ -3,6 +3,6 @@ import { configs } from "../configs/index.js";
export const redisConnection = new Redis(configs.redis_url as string, { export const redisConnection = new Redis(configs.redis_url as string, {
tls: {}, tls: {},
maxRetriesPerRequest: 1, maxRetriesPerRequest: null,
enableReadyCheck: false, enableReadyCheck: false,
}); });