signup signIn forgetPassword aPI updated

This commit is contained in:
2025-08-29 10:29:25 +05:30
parent 7373e0dbe8
commit c473c5b7a0
18 changed files with 2328 additions and 17 deletions

10
.env
View File

@@ -5,3 +5,13 @@ MONGO_AUTH_DB=admin
API_PORT=9696
SOCKET_PORT=8002
JWT_SECRET="Schema_Studio"
REFRESH_JWT_SECRET="Schema_Studio"
REDIS_ENV= true
REDIS_LOCAL =127.0.0.1
REDIS_PORT=6379
EMAIL_USER=nivetha@hexrfactory.com
EMAIL_PASS=tikq fjry hzgr ootn
CLIENT_URL=http://192.168.0.104:9696

1419
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,13 +12,16 @@
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^3.0.2",
"body-parser": "^2.2.0",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^5.1.0",
"fs": "^0.0.1-security",
"ioredis": "^5.7.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.16.3",
"nodemailer": "^7.0.5",
"nodemon": "^3.1.10",
"path": "^0.12.7",
"socket.io": "^4.8.1"
@@ -27,6 +30,7 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.3",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^24.0.14"
"@types/node": "^24.0.14",
"@types/nodemailer": "^7.0.1"
}
}

View File

@@ -4,7 +4,8 @@ import dotenv from "dotenv";
import projectRoutes from "./routes/projectRoutes";
import collectionNodeRoutes from "./routes/collectionRoutes";
import edgeRoutes from "./routes/edgeRoutes";
dotenv.config({ quiet: true });
import authRoutes from "./routes/authRoutes";
dotenv.config();
const app = express();
app.use(cors());
@@ -13,6 +14,7 @@ app.use(
express.urlencoded({ limit: "50mb", extended: true, parameterLimit: 50000 })
);
app.use("/api/v1", authRoutes);
app.use("/api/v1", projectRoutes);
app.use("/api/v1", collectionNodeRoutes);
app.use("/api/v1", edgeRoutes);

View File

@@ -0,0 +1,157 @@
import { Request, Response } from "express";
import {
forgetPassword,
signinService,
signupService,
} from "../../shared/services/AuthService";
export const signupController = async (
req: Request,
res: Response
): Promise<void> => {
try {
const { userName, email, password, confirmPassword } = req.body;
if (!userName || !email || !password || !confirmPassword) {
res.status(400).json({
message: "All fields are required",
});
return;
}
const data = {
userName,
email,
password,
confirmPassword,
};
const result = await signupService(data);
switch (result.status) {
case "User Already exists":
res.status(403).json({
message: "User Already exists",
});
break;
case "Passwords do not match":
res.status(200).json({
message: "Passwords do not match",
});
break;
case "Signup unsuccessfull":
res.status(200).json({
message: "Signup unsuccessfull",
});
break;
case "Success":
res.status(200).json({
message: "Signup Successfull",
});
break;
default:
res.status(500).json({
message: "Internal server error",
});
break;
}
} catch (error) {
res.status(500).json({
message: "Unknown error",
});
}
};
export const signinController = async (
req: Request,
res: Response
): Promise<void> => {
try {
const { email, password } = req.body;
if (!email || !password) {
res.status(400).json({
message: "All fields are required",
});
return;
}
const data = {
email,
password,
};
const result = await signinService(data);
console.log("result: ", result);
switch (result.status) {
case "User not found!!! Kindly Signup":
res.status(403).json({
message: "User not found!!! Kindly Signup",
});
break;
case "Password is invalid...Check the credentials":
res.status(200).json({
message: "Password is invalid...Check the credentials",
});
break;
case "Success":
res.status(200).json({
message: "Signup Successfull",
data: result.data,
});
break;
default:
res.status(500).json({
message: "Internal server error",
});
break;
}
} catch (error) {
res.status(500).json({
message: "Unknown error",
});
}
};
export const forgetPasswordController = async (
req: Request,
res: Response
): Promise<void> => {
try {
const { email } = req.body;
if (!email) {
res.status(400).json({
message: "All fields are required",
});
return;
}
const data = {
email,
};
const result = await forgetPassword(data);
console.log("result: ", result);
switch (result.status) {
case "User not found!!! Kindly Signup":
res.status(403).json({
message: "User not found!!! Kindly Signup",
});
break;
case "Password is invalid...Check the credentials":
res.status(200).json({
message: "Password is invalid...Check the credentials",
});
break;
case "Success":
res.status(200).json({
message: "Signup Successfull",
// data: result.data,
});
break;
default:
res.status(500).json({
message: "Internal server error",
});
break;
}
} catch (error) {
res.status(500).json({
message: "Unknown error",
});
}
};

View File

@@ -14,7 +14,7 @@ export const projectCreationController = async (
organization,
useableLanguage,
projectName,
userName,
userId,
apiType,
application,
architecture,
@@ -24,7 +24,7 @@ export const projectCreationController = async (
!organization ||
!useableLanguage ||
!projectName ||
!userName ||
!userId ||
!apiType ||
!architecture|| !application
) {
@@ -38,7 +38,7 @@ export const projectCreationController = async (
projectName,
useableLanguage,
description,application,
userName,
userId,
apiType,
architecture,
};

View File

@@ -0,0 +1,9 @@
import express from "express";
import { forgetPasswordController, signinController, signupController } from "../controller/authController";
const authRoutes = express.Router();
authRoutes.post("/signup", signupController);
authRoutes.post("/signIn", signinController);
authRoutes.post("/forget", forgetPasswordController);
export default authRoutes;

View File

@@ -5,7 +5,7 @@ interface ConnectionCache {
}
const connections: ConnectionCache = {};
dotenv.config({ quiet: true });
dotenv.config();
const MainModel = <T>(
db: string,
modelName: string,

View File

@@ -0,0 +1,21 @@
import Redis from "ioredis";
import * as dotenv from "dotenv";
dotenv.config({quiet:true});
const redis = new Redis({
host:
process.env.REDIS_ENV === "true"
? process.env.REDIS_DOCKER
: process.env.REDIS_LOCAL,
port: parseInt(process.env.REDIS_PORT || "6379"),
password: "",
db: 0,
});
redis.on("connect", () => {
console.log(`Connected to Redis to ${redis.options.port}`);
});
redis.on("error", (err: unknown) => {
console.error("Redis connection error:", err);
});
export default redis;

View File

@@ -0,0 +1,61 @@
import mongoose, { Document, Schema } from "mongoose";
import MainModel from "../connection/connection";
import { IProject } from "./projectmodel";
import { User } from "./userModel";
export interface ISharedUser {
userId: User["_id"];
accessLevel: "Viewer" | "Editor" | "Admin";
}
export interface IShare extends Document {
projectId: IProject["_id"];
sharedBy: mongoose.Types.ObjectId;
sharedWith: ISharedUser[];
description?: string;
isArchived: boolean;
createdAt: Date;
updatedAt: Date;
}
const shareSchema = new Schema<IShare>(
{
projectId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Project",
},
sharedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
sharedWith: [
{
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
accessLevel: {
type: String,
enum: ["Viewer", "Editor", "Admin"],
default: "Viewer",
},
},
],
description: {
type: String,
},
isArchived: {
type: Boolean,
default: false,
},
},
{
timestamps: true,
}
);
const shareModel = (db: any) => {
return MainModel(db, "Share", shareSchema, "Share");
};
export default shareModel;

View File

@@ -0,0 +1,22 @@
import { Schema, Document } from "mongoose";
import MainModel from "../connection/connection";
import { User } from "./userModel";
export interface IUserToken extends Document {
userId: User["_id"];
isArchive: boolean;
refreshToken: string;
resetTokenExpiry?: Date;
resetToken: string;
}
const tokenSchema: Schema = new Schema({
userId: { type: Schema.Types.ObjectId, ref: "User" },
isArchive: { type: Boolean, default: false },
refreshToken: { type: String },
resetToken: { type: String },
resetTokenExpiry: { type: Date },
});
const tokenModel = (db: any) => {
return MainModel(db, "Token", tokenSchema, "Token");
};
export default tokenModel;

View File

@@ -0,0 +1,25 @@
import { Schema, Document } from "mongoose";
import MainModel from "../connection/connection";
import { User } from "./userModel";
export interface IUserData extends Document {
userId: User["_id"];
isArchive: boolean;
profilePicture: string;
recentlyViewed: string[];
}
const userDataSchema: Schema = new Schema({
userId: { type: Schema.Types.ObjectId, ref: "User" },
isArchive: { type: Boolean, default: false },
recentlyViewed: {
type: [String],
default: [],
},
profilePicture: {
type: String,
},
});
const userDataModel = (db: any) => {
return MainModel(db, "userData", userDataSchema, "userData");
};
export default userDataModel;

View File

@@ -0,0 +1,36 @@
import { Schema, Document } from "mongoose";
import MainModel from "../connection/connection";
export interface User extends Document {
userName: string;
email: string;
password: string;
isArchive: boolean;
visitorBrowserId: string;
role: string;
}
const UserSchema: Schema = new Schema({
userName: {
type: String,
required: true,
},
role: {
type: String,
default: "User",
enum: ["User", "Admin"],
},
email: {
type: String,
required: true,
},
password: {
type: String,
min: 8,
},
isArchive: { type: Boolean, default: false },
visitorBrowserId: { type: String },
});
const userModel = (db: any) => {
return MainModel(db, "Users", UserSchema, "Users");
};
export default userModel;

View File

@@ -0,0 +1,229 @@
import redis from "../connection/redis";
import tokenModel from "../model/tokenModel";
import nodemailer from "nodemailer";
import userModel from "../model/userModel";
import { hashGenerate, hashValidator } from "../utils/hashing";
import { tokenGenerator, tokenRefreshGenerator } from "../utils/token";
import { text } from "body-parser";
interface Iresponse {
status: string;
data?: any;
}
interface Isignup {
userName: string;
email: string;
password: string;
confirmPassword: string;
}
interface Isignin {
email: string;
password: string;
}
interface IforGotPassword {
email: string;
}
export async function existingUserData(email: string, organization: string) {
const existingData = await userModel(organization).findOne({
email: email,
isArchive: false,
});
return existingData;
}
export const signupService = async (data: Isignup): Promise<Iresponse> => {
const { userName, email, password, confirmPassword } = data;
try {
const mailCaseChange = email.toLocaleLowerCase();
const organization = email.split("@")[1].split(".")[0];
const mailExistance = await existingUserData(mailCaseChange, organization);
if (mailExistance !== null) return { status: "User Already exists" };
if (password !== confirmPassword) {
return { status: "Passwords do not match" };
}
let role;
const passwordHashed = await hashGenerate(password);
const userCount = await userModel(organization).countDocuments({});
role = userCount === 0 ? "Admin" : "User";
const newUser = await userModel(organization).create({
userName,
email: mailCaseChange,
password: passwordHashed,
role,
});
if (!newUser) return { status: "Signup unsuccessfull" };
return { status: "Success" };
} catch (error: unknown) {
if (error instanceof Error) {
return {
status: error.message,
};
} else {
return {
status: "An unexpected error occurred",
};
}
}
};
export const signinService = async (data: Isignin): Promise<Iresponse> => {
const { email, password } = data;
try {
const mailCaseChange = email.toLocaleLowerCase();
const organization = email.split("@")[1].split(".")[0];
const mailExistance = await existingUserData(mailCaseChange, organization);
if (mailExistance == null)
return { status: "User not found!!! Kindly Signup" };
const comparePassword = await hashValidator(
password,
mailExistance.password
);
if (!comparePassword)
return { status: "Password is invalid...Check the credentials" };
const tokenValidation = tokenGenerator(
mailExistance.email,
mailExistance.role,
mailExistance._id,
organization
);
const refreshTokenvalidation = tokenRefreshGenerator(
mailExistance.email,
mailExistance.role,
mailExistance._id,
organization
);
const existingToken = await tokenModel(organization).findOne({
userId: mailExistance._id,
isArchive: false,
});
let finalResult;
if (!existingToken) {
const tokenSave = await tokenModel(organization).create({
userId: mailExistance._id,
isArchive: false,
refreshToken: refreshTokenvalidation,
});
// await redis.setex(
// `user:${mailExistance.Email}`,
// 3600,
// JSON.stringify(tokenSave)
// );
finalResult = {
message: "login successfull",
email: mailExistance.email,
name: mailExistance.userName,
userId: mailExistance._id,
token: tokenValidation,
refreshToken: refreshTokenvalidation,
};
} else {
finalResult = {
message: "login successfull",
email: mailExistance.email,
name: mailExistance.userName,
userId: mailExistance._id,
token: tokenValidation,
refreshToken: existingToken.refreshToken,
};
}
return { status: "Success", data: finalResult };
} catch (error: unknown) {
if (error instanceof Error) {
return {
status: error.message,
};
} else {
return {
status: "An unexpected error occurred",
};
}
}
};
export const forgetPassword = async ({
email,
}: IforGotPassword): Promise<{ status: string }> => {
try {
console.log("hi forgetpassword");
const mailCaseChange = email.toLocaleLowerCase();
const organization = email.split("@")[1].split(".")[0];
const Existing_User = await existingUserData(mailCaseChange, organization);
console.log("Existing_User: ", Existing_User);
if (Existing_User) {
console.log("if");
// if (Existing_User.lastPasswordReset) {
// console.log("if2");
// const lastPasswordReset = Existing_User.lastPasswordReset;
// const now = Date.now();
// const timeDiff = now - lastPasswordReset;
// const diffInHours = Math.floor(timeDiff / (1000 * 60 * 60));
// if (diffInHours < 24)
// return {
// status: "You can only reset your password once every 24 hours.",
// };
// }
console.log("process.env.EMAIL_USER: ", process.env.EMAIL_USER);
console.log("process.env.EMAIL_PASS: ", process.env.EMAIL_PASS);
const transport = nodemailer.createTransport({
service: "gmail",
secure: true,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
// const resetToken = tokenGenerator(
// email,
// Existing_User.Role as string,
// Existing_User._id as string,
// organization
// );
// const userTokenData = await tokenModel(organization).findOne({
// userId: Existing_User._id,
// isArchive: false,
// });
// if (!userTokenData) {
// await tokenModel(organization).create({
// // Email: Existing_User.Email,
// userId: Existing_User._id,
// resetToken: resetToken,
// resetTokenExpiry: Date.now(),
// });
// } else {
// userTokenData.resetToken = resetToken;
// userTokenData.resetTokenExpiry = new Date();
// await userTokenData.save();
// }
const Receiver = {
from: process.env.EMAIL_USER,
to: email,
subject: "Password Reset Request",
// text: "test mail",
text: `Click the below link to generate the new password \n ${
process.env.CLIENT_URL
}/reset-password/${tokenGenerator(
email,
Existing_User.Role as string,
Existing_User._id as string,
organization
)}`,
};
await transport.sendMail(Receiver);
return { status: "Success" };
} else {
return { status: "Email not found" };
}
} catch (error: unknown) {
if (error instanceof Error) {
return {
status: error.message,
};
} else {
return {
status: "An unexpected error occurred",
};
}
}
};

View File

@@ -2,6 +2,9 @@ import MVCarcModel from "../../shared/model/mvcModel";
import ProjectType from "../../shared/model/projectmodel";
import collectionsModel from "../model/collectionModel";
import edgeModel from "../model/edgeModel";
import shareModel from "../model/shareModel";
import userDataModel from "../model/userDataModel";
import userModel from "../model/userModel";
interface Iresponse {
status: string;
data?: any;
@@ -10,16 +13,22 @@ interface IProject {
useableLanguage: string;
organization: string;
projectName: string;
userName: string;
userId: string;
apiType: string;
application: string;
architecture: string;
description: string;
}
interface IProjectView {
organization: string;
userId: string;
projectId: string;
}
interface IProjectstructure {
projectId: string;
organization: string;
}
export const projectCreationService = async (
data: IProject
): Promise<Iresponse> => {
@@ -28,7 +37,7 @@ export const projectCreationService = async (
projectName,
useableLanguage,
description,
userName,
userId,
apiType,
application,
architecture,
@@ -36,7 +45,7 @@ export const projectCreationService = async (
try {
const existingProject = await ProjectType(organization).findOne({
projectName: projectName,
createdBy: userName,
createdBy: userId,
isArchive: false,
});
if (existingProject) {
@@ -45,7 +54,7 @@ export const projectCreationService = async (
if (architecture.toLowerCase() === "mvc") {
const newProject = await ProjectType(organization).create({
projectName,
createdBy: userName,
createdBy: userId,
useableLanguage,
architecture,
apiType: apiType,
@@ -60,7 +69,7 @@ export const projectCreationService = async (
if (!existingProjectinMVC) {
const MVCCreation = await MVCarcModel(organization).create({
projectId: newProject._id,
createdBy: userName,
createdBy: userId,
controllers: true,
routes: true,
models: true,
@@ -153,7 +162,7 @@ export const GetNodesInProject = async (
const edgeNodes = await edgeModel(organization)
.find({ projectId: projectId, isArchive: false })
.select("cardinality from to");
if(!edgeNodes) return {status:'No edge Nodes present',data:[]}
if (!edgeNodes) return { status: "No edge Nodes present", data: [] };
if (!collectionNodesdata)
return { status: "No collection Nodes present", data: [] };
else {
@@ -166,7 +175,6 @@ export const GetNodesInProject = async (
const { isArchive, ...rest } = attr.toObject();
return { ...rest, edgeNodes };
}),
}));
return { status: "Success", data: { collectionNodes, edgeNodes } };
}
@@ -183,3 +191,150 @@ export const GetNodesInProject = async (
}
}
};
const maxLength: number = 6;
export const ViewProjectService = async (
data: IProjectView
): Promise<Iresponse> => {
const { organization, projectId, userId } = data;
try {
const RecentUserDoc = await userDataModel(organization).findOne({
userId: userId,
isArchive: false,
});
const existingProject = await ProjectType(organization).findOne({
_id: projectId,
isArchive: false,
});
const newArr = RecentUserDoc?.recentlyViewed || [];
if (RecentUserDoc?.recentlyViewed.length === 0) {
newArr.push(projectId);
await RecentUserDoc.save();
} else {
const index = newArr.indexOf(projectId);
if (index !== -1) {
newArr.splice(index, 1);
}
newArr.unshift(projectId);
if (newArr.length > maxLength) {
newArr.pop();
}
}
await userDataModel(organization).findOneAndUpdate(
{ userId: userId, isArchive: false },
{ recentlyViewed: newArr },
{ new: true }
);
const projectData = await ProjectType(organization)
.findOne({
_id: projectId,
isArchive: false,
})
.populate({
path: "createdBy",
model: userModel(organization),
select: "userName",
})
.select("_id projectName createdBy");
return { status: "Success", data: projectData };
} catch (error: unknown) {
if (error instanceof Error) {
return {
status: error.message,
};
} else {
return {
status: "An unexpected error occurred",
};
}
}
};
export const DeleteProject = async (data: IProjectView) => {
try {
const { projectId, organization, userId } = data;
const ExistingUser = await userModel(organization).findOne({
_id: userId,
isArchive: false,
});
if (!ExistingUser) return { status: "User not found" };
let filter = {
_id: projectId,
createdBy: userId,
isArchive: false,
};
const existingProject = await ProjectType(organization).findOne(filter);
if (!existingProject) return { status: "Project not found" };
const updateProject = await ProjectType(organization).findOneAndUpdate(
filter,
{ isArchive: true },
{ new: true }
);
await shareModel(organization).updateMany(
{ projectId: projectId, isArchive: false },
{ isArchive: true }
);
if (updateProject) return { status: "Success" };
} catch (error: unknown) {
return { status: error };
}
};
// export const ViewProjectService = async (
// data: IProjectView
// ): Promise<Iresponse> => {
// const { organization, projectId, userId } = data;
// try {
// const RecentUserDoc = await userDataModel(organization).findOne({
// userId: userId,
// isArchive: false,
// });
// const existingProject = await ProjectType(organization).findOne({
// _id: projectId,
// isArchive: false,
// });
// const newArr = RecentUserDoc?.recentlyViewed || [];
// if (RecentUserDoc?.recentlyViewed.length === 0) {
// newArr.push(projectId);
// await RecentUserDoc.save();
// } else {
// const index = newArr.indexOf(projectId);
// if (index !== -1) {
// newArr.splice(index, 1);
// }
// newArr.unshift(projectId);
// if (newArr.length > maxLength) {
// newArr.pop();
// }
// }
// await userDataModel(organization).findOneAndUpdate(
// { userId: userId, isArchive: false },
// { recentlyViewed: newArr },
// { new: true }
// );
// const projectData = await ProjectType(organization)
// .findOne({
// _id: projectId,
// isArchive: false,
// })
// .populate({
// path: "createdBy",
// model: userModel(organization),
// select: "userName",
// })
// .select("_id projectName createdBy");
// return { status: "Success", data: projectData };
// } catch (error: unknown) {
// if (error instanceof Error) {
// return {
// status: error.message,
// };
// } else {
// return {
// status: "An unexpected error occurred",
// };
// }
// }
// };

View File

View File

@@ -0,0 +1,24 @@
import bcrypt from "bcryptjs";
const saltRounds = 10;
export const hashGenerate = async (Password: string) => {
try {
const salt = await bcrypt.genSalt(saltRounds);
const hash = await bcrypt.hash(Password, salt);
return hash;
} catch (error) {
return error;
}
};
export const hashValidator = async (
password: string,
hashedPassword: string
) => {
try {
const result = await bcrypt.compare(password, hashedPassword);
return result;
} catch (error) {
return false;
}
};

139
src/shared/utils/token.ts Normal file
View File

@@ -0,0 +1,139 @@
import { Request, Response, NextFunction } from "express";
import Jwt from "jsonwebtoken";
import dotenv from "dotenv";
import userModel from "../model/userModel";
dotenv.config();
export interface AuthenticatedRequest extends Request {
user?: {
email: string;
role: string;
userId: string;
organization: string;
};
}
const jwt_secret = process.env.JWT_SECRET as string;
const refresh_jwt_secret = process.env.REFRESH_JWT_SECRET as string;
const tokenGenerator = (
email: string,
role: string,
userId: string,
organization: string
) => {
const token = Jwt.sign(
{ email: email, role: role, userId: userId, organization: organization },
jwt_secret,
{
expiresIn: "3h",
}
);
return token;
};
const tokenRefreshGenerator = (
email: string,
role: string,
userId: string,
organization: string
) => {
const token = Jwt.sign(
{ email: email, role: role, userId: userId, organization: organization },
refresh_jwt_secret,
{
expiresIn: "7d",
}
);
return token;
};
const tokenValidator = async (
req: AuthenticatedRequest,
res: Response,
next: NextFunction
): Promise<void> => {
const token: string | undefined = req.headers.token as string | undefined;
const refresh_token = req.headers["refresh_token"] as string | undefined;
if (!token) {
res.status(403).json({
msg: "No token present",
});
return;
}
try {
const decoded = Jwt.verify(token, jwt_secret) as {
email: string;
role: string;
userId: string;
organization: string;
};
if (!decoded) {
res.status(403).json({
success: false,
status: 403,
message: "Invalid Token",
});
return;
}
req.user = decoded;
next();
} catch (err) {
if (!refresh_token) {
res.status(403).json({
success: false,
status: 403,
message: "No refresh token present",
});
return;
}
try {
const decodedRefresh = Jwt.verify(refresh_token, refresh_jwt_secret) as {
email: string;
role: string;
userId: string;
organization: string;
};
if (!decodedRefresh) {
res.status(403).json({
success: false,
status: 403,
message: "Invalid Token",
});
return;
}
const newAccessToken = tokenGenerator(
decodedRefresh.email,
decodedRefresh.role,
decodedRefresh.userId,
decodedRefresh.organization
);
res.setHeader("x-access-token", newAccessToken);
req.user = decodedRefresh;
return next();
} catch (err) {
const decodedAny = Jwt.decode(token || refresh_token) as {
email?: string;
role: string;
userId: string;
organization: string;
};
if (decodedAny?.email) {
const organization = decodedAny?.email.split("@")[1].split(".")[0];
const user = await userModel(organization).findOne({
email: decodedAny.email,
isArchieve: false,
});
if (user) {
user.visitorBrowserID = "";
await user.save();
}
}
res.status(403).json({
success: false,
status: 403,
message: "Invalid Token",
});
return;
}
}
};
export { tokenValidator, tokenGenerator, tokenRefreshGenerator };