chore: add otp based login

This commit is contained in:
mahyargdz
2024-11-18 09:16:17 +03:30
parent 245051024b
commit d887cf67c1
16 changed files with 1266 additions and 713 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
DANAK_SERVER: "https://captain.run.danakcorp.com" DANAK_SERVER: "https://captain.run.danakcorp.com"
APP_TOKEN: 5a2526d13383aa8c4c3e6019352b96cf81e84b7b781e80c2b8012eaf5e2e69fd APP_TOKEN: 5a2526d13383aa8c4c3e6019352b96cf81e84b7b781e80c2b8012eaf5e2e69fd
CAPROVER_APP_NAME: ostandari CAPROVER_APP_NAME: ostandari
GITHUB_TOKEN: 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 GITHUB_TOKEN: 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
steps: steps:
- name: Check out repositorys - name: Check out repositorys
+18
View File
@@ -0,0 +1,18 @@
# Use the official Node.js image as a base
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN mkdir -p /app/.nuxt && chown -R node:node /app
USER node
EXPOSE 3000
CMD ["npm", "run", "dev"]
+18
View File
@@ -0,0 +1,18 @@
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
container_name: ostandari-dev
# working_dir: /app
volumes:
- .:/app
- /app/node_modules
ports:
- "3000:3000"
command: ["npm", "run", "dev"]
environment:
NODE_ENV: development
volumes:
mongo_data:
+41 -3
View File
@@ -29,6 +29,7 @@
"element-ui": "^2.15.1", "element-ui": "^2.15.1",
"express": "^4.17.1", "express": "^4.17.1",
"express-fileupload": "^1.2.1", "express-fileupload": "^1.2.1",
"express-rate-limit": "^7.4.1",
"express-validator": "^6.10.1", "express-validator": "^6.10.1",
"gsap": "^3.6.1", "gsap": "^3.6.1",
"jquery": "^3.7.1", "jquery": "^3.7.1",
@@ -39,6 +40,7 @@
"mongoose": "^5.12.5", "mongoose": "^5.12.5",
"mongoose-paginate-v2": "^1.3.18", "mongoose-paginate-v2": "^1.3.18",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"node-cache": "^5.1.2",
"nodemailer": "^6.6.0", "nodemailer": "^6.6.0",
"nodemon": "^3.1.2", "nodemon": "^3.1.2",
"nuxt": "^2.15.3", "nuxt": "^2.15.3",
@@ -7333,6 +7335,15 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
"license": "MIT",
"engines": {
"node": ">=0.8"
}
},
"node_modules/code-point-at": { "node_modules/code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -8840,9 +8851,9 @@
} }
}, },
"node_modules/elliptic": { "node_modules/elliptic": {
"version": "6.5.7", "version": "6.6.1",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz",
"integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bn.js": "^4.11.9", "bn.js": "^4.11.9",
@@ -9379,6 +9390,21 @@
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/express-rate-limit": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.1.tgz",
"integrity": "sha512-KS3efpnpIDVIXopMc65EMbWbUht7qvTCdtCR2dD/IZmi9MIkopYESwyRqLgv8Pfu589+KqDqOdzJWW7AHoACeg==",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/express-rate-limit"
},
"peerDependencies": {
"express": "4 || 5 || ^5.0.0-beta.1"
}
},
"node_modules/express-validator": { "node_modules/express-validator": {
"version": "6.15.0", "version": "6.15.0",
"resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.15.0.tgz", "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.15.0.tgz",
@@ -13547,6 +13573,18 @@
"devOptional": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/node-cache": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
"integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
"license": "MIT",
"dependencies": {
"clone": "2.x"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/node-fetch": { "node_modules/node-fetch": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+2
View File
@@ -32,6 +32,7 @@
"element-ui": "^2.15.1", "element-ui": "^2.15.1",
"express": "^4.17.1", "express": "^4.17.1",
"express-fileupload": "^1.2.1", "express-fileupload": "^1.2.1",
"express-rate-limit": "^7.4.1",
"express-validator": "^6.10.1", "express-validator": "^6.10.1",
"gsap": "^3.6.1", "gsap": "^3.6.1",
"jquery": "^3.7.1", "jquery": "^3.7.1",
@@ -42,6 +43,7 @@
"mongoose": "^5.12.5", "mongoose": "^5.12.5",
"mongoose-paginate-v2": "^1.3.18", "mongoose-paginate-v2": "^1.3.18",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"node-cache": "^5.1.2",
"nodemailer": "^6.6.0", "nodemailer": "^6.6.0",
"nodemon": "^3.1.2", "nodemon": "^3.1.2",
"nuxt": "^2.15.3", "nuxt": "^2.15.3",
+81
View File
@@ -0,0 +1,81 @@
const { validationResult, query } = require("express-validator");
const Logger = require("../models/Logger");
const { paginationOptions } = require("../plugins/pagination");
// get admin login logs with optional filtering and pagination
module.exports.getAdminLoginLogs = [
[
query("page")
.optional()
.isInt({ min: 1 })
.withMessage("Page must be a positive integer."),
query("limit")
.optional()
.isInt({ min: 1 })
.withMessage("Limit must be a positive integer."),
query("sort")
.optional()
.isIn(["asc", "desc"])
.withMessage('Sort must be either "asc" or "desc".'),
query("fromDate")
.optional()
.isISO8601()
.withMessage("From date must be a valid date."),
query("toDate")
.optional()
.isISO8601()
.withMessage("To date must be a valid date."),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty())
return res.status(422).json({ validation: errors.mapped() });
try {
const {
page = 1,
limit = 1000,
sort = "desc",
fromDate,
toDate,
} = req?.query;
const filters = {};
if (fromDate) filters.LastLogin = { $gte: new Date(fromDate) };
if (toDate)
filters.LastLogin = { ...filters.LastLogin, $lte: new Date(toDate) };
const options = paginationOptions({ page, limit, sort });
const logs = await Logger.find(filters)
.populate({ path: "user", select: { password: 0 } })
.sort({ updated_at: sort === "desc" ? -1 : 1 })
.skip(options.skip)
.limit(options.limit);
const totalLogs = await Logger.countDocuments(filters);
const totalPages = Math.ceil(totalLogs / options.limit);
return res.status(200).json({
logs: logs.map((log) => {
log.LastLogin = new Date(log.LastLogin).toLocaleString("fa-IR", {
timeZone: "Asia/Tehran",
// hour: "2-digit",
// minute: "2-digit",
// day: "2-digit",
// month: "2-digit",
// weekday: "short",
// year: "2-digit",
// timeZoneName: "long",
});
return log;
}),
page: options.page,
totalPages,
totalLogs,
});
} catch (error) {
console.error("Error fetching admin login logs:", error);
return res.status(500).json({ message: "Server error occurred." });
}
},
];
+176
View File
@@ -1,5 +1,6 @@
const User = require("../models/User"); const User = require("../models/User");
const { body, validationResult } = require("express-validator"); const { body, validationResult } = require("express-validator");
const { rateLimit } = require("express-rate-limit");
const bcrypt = require("bcryptjs"); const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken"); const jwt = require("jsonwebtoken");
const crypto = require("crypto"); const crypto = require("crypto");
@@ -17,6 +18,9 @@ const fs = require("fs");
const nodemailer = require("nodemailer"); const nodemailer = require("nodemailer");
const Category = require("../models/Category"); const Category = require("../models/Category");
const Logger = require("../models/Logger"); const Logger = require("../models/Logger");
const cacheService = require("../plugins/cache");
const { sms } = require("../plugins/sms");
////// variables ////// variables
const profileWidth = 500; const profileWidth = 500;
const profileHeight = 500; const profileHeight = 500;
@@ -25,11 +29,19 @@ const hostURL = "localhost:6688";
const limit = 20; const limit = 20;
const select = "-password -token"; const select = "-password -token";
const limiter = rateLimit({
windowMs: 10 * 60 * 1000, // 10 minutes
limit: 10,
standardHeaders: "draft-7",
legacyHeaders: false,
});
/** @todo add private to query */ /** @todo add private to query */
/** auth --------------------------------------------- */ /** auth --------------------------------------------- */
/////////////////////////////////////////////////////////////////////// login /////////////////////////////////////////////////////////////////////// login
module.exports.login = [ module.exports.login = [
limiter,
[ [
body("username") body("username")
.if((value, { req }) => { .if((value, { req }) => {
@@ -138,6 +150,170 @@ module.exports.login = [
} }
}, },
]; ];
/** otp --------------------------------------------- */
/////////////////////////////////////////////////////////////////////// otp
module.exports.otp = [
limiter,
[
body("phone")
.notEmpty()
.withMessage(_sr["fa"].required.phone_number)
.bail()
.isMobilePhone("fa-IR")
.withMessage(_sr["fa"].required.phone_number),
// .isLength({ min: 4 })
// .withMessage(_sr["fa"].min_char.min4),
],
async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty())
return res.status(422).json({ validation: errors.mapped() });
const { phone } = req.body;
const user = await User.findOne({ mobileNumber: phone });
if (!user)
return res.status(406).json({
message: "شماره موبایل نامعتبر می باشد",
});
const existOtp = cacheService.get(`OTP:LOGIN:${phone}`);
if (existOtp)
return res.status(400).json({
message: "کد به شماره موبایل شما ارسال شده است",
ttl: (cacheService.getTtl(`OTP:LOGIN:${phone}`) - Date.now()) / 1000,
});
const otp = crypto.randomInt(10000, 99999);
const message = `کد ورود شما ${otp} میباشد. استانداری لغو11`;
/** save otp in cache */
cacheService.set(`OTP:LOGIN:${phone}`, otp, 120);
/** send sms to user */
const smsResult = await sms(phone, message);
if (!smsResult.IsSuccessful) {
console.log(smsResult);
return res500(res, `مشکلی در ارسال پیامک پیش آمده است`);
}
return res.status(200).json({
message: "کد به شماره موبایل شما ارسال شد",
});
} catch (error) {
return res500(res, error?.message);
}
},
];
/////////////////////////////////////////////////////////////////////// verify otp
module.exports.verifyOtp = [
limiter,
[
body("phone")
.notEmpty()
.withMessage(_sr["fa"].required.phone_number)
.bail()
.isMobilePhone("fa-IR")
.withMessage(_sr["fa"].required.phone_number),
body("code")
.notEmpty()
.withMessage(_sr["fa"].required.otp_code)
.bail()
.isLength({ min: 5, max: 5 })
.withMessage(_sr["fa"].format.otp_length),
],
async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty())
return res.status(422).json({ validation: errors.mapped() });
const { phone, code } = req.body;
// Check if the OTP exists in the cache
const cachedOtp = cacheService.get(`OTP:LOGIN:${phone}`);
if (!cachedOtp) {
return res.status(400).json({
message: "کد وارد شده منقضی شده است یا نامعتبر می‌باشد",
});
}
// Verify if the provided OTP matches the cached OTP
if (cachedOtp.toString() !== code.trim()) {
return res.status(422).json({
validation: { code: { msg: "کد وارد شده نامعتبر می‌باشد" } },
});
}
// Find the user by phone number
const user = await User.findOne({ mobileNumber: phone });
if (!user) {
return res.status(406).json({
message: "شماره موبایل نامعتبر می باشد",
});
}
// Check if the user's registration is complete
if (!user.registration_done) {
return res.status(403).json({
message: `اکانت شما غیرفعال می باشد لطفا با ادمین تماس بگیرید`,
});
}
// Create or update login logger
const logger = await Logger.findOne({ user: user._id });
if (logger) {
await Logger.findOneAndUpdate(
{ user: user._id },
{ $set: { LastLogin: new Date() } },
{ new: true }
);
} else {
const newLogger = new Logger({
user: user,
LastLogin: new Date(),
});
await newLogger.save();
}
// Check if the user already has a valid token
if (user.token) {
jwt.verify(
user.token.replace(/^Bearer\s/, ""),
secretKey,
async (err, decoded) => {
if (err || !decoded) {
// Generate a new token if the existing one is invalid
const token = await jwt.sign({ _id: user._id }, secretKey, {
expiresIn: "2h",
});
user.token = token;
await user.save();
// Remove the OTP from the cache
cacheService.del(`OTP:LOGIN:${phone}`);
return res.json({ token: user.token });
} else {
// Remove the OTP from the cache
cacheService.del(`OTP:LOGIN:${phone}`);
return res.json({ token: user.token });
}
}
);
} else {
// Generate a new token if none exists
const token = await jwt.sign({ _id: user._id }, secretKey, {
expiresIn: "1h",
});
user.token = token;
await user.save();
// Remove the OTP from the cache
cacheService.del(`OTP:LOGIN:${phone}`);
return res.json({ token: user.token });
}
} catch (error) {
return res500(res, error?.message);
}
},
];
/////////////////////////////////////////////////////////////////////// logout /////////////////////////////////////////////////////////////////////// logout
module.exports.logout = [ module.exports.logout = [
+2 -1
View File
@@ -6,7 +6,8 @@
// const databaseURL = 'mongodb://ostanmri_user:admin1234@localhost:27017/ostanmri_database' // const databaseURL = 'mongodb://ostanmri_user:admin1234@localhost:27017/ostanmri_database'
const databaseURL = const databaseURL =
"mongodb://root:f2d63313cc3ed6ff@srv-captain--ostandari-db:27017/ostan_db?authSource=admin"; // "mongodb://root:f2d63313cc3ed6ff@srv-captain--ostandari-db:27017/ostan_db?authSource=admin";
"mongodb://root:f2d63313cc3ed6ff@danak-db-public.danakcorp.com:50123/ostan_db?authSource=admin";
//const databaseURL = 'mongodb://danakcorp:danakcorp%212024@ostan-mr.ir:27017/ostan_db?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=admin&authMechanism=SCRAM-SHA-1' //const databaseURL = 'mongodb://danakcorp:danakcorp%212024@ostan-mr.ir:27017/ostan_db?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=admin&authMechanism=SCRAM-SHA-1'
// const databaseURL = 'mongodb://ostanmri_user:admin1234@91.98.96.174:27017/ostanmri_database?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=ostanmri_database' // const databaseURL = 'mongodb://ostanmri_user:admin1234@91.98.96.174:27017/ostanmri_database?serverSelectionTimeoutMS=5000&connectTimeoutMS=10000&authSource=ostanmri_database'
+4 -7
View File
@@ -8,7 +8,7 @@ const {
isLoggedIn, isLoggedIn,
hasPermission, hasPermission,
} = require("./authentication"); } = require("./authentication");
const bodyParser = require("body-parser"); // const bodyParser = require("body-parser");
const cronJobs = require("./plugins/cronJobs"); const cronJobs = require("./plugins/cronJobs");
const swaggerJsdoc = require("swagger-jsdoc"); const swaggerJsdoc = require("swagger-jsdoc");
const cors = require("cors"); const cors = require("cors");
@@ -66,10 +66,11 @@ const options = {
apis: ["./server/routes/*.js"], apis: ["./server/routes/*.js"],
}; };
// const specs = swaggerJsdoc(options); const specs = swaggerJsdoc(options);
cronJobs(); cronJobs();
createAdmins(); createAdmins();
const corsOptions = { const corsOptions = {
origin: "*", origin: "*",
credentials: true, credentials: true,
@@ -81,11 +82,7 @@ app.use(express.json());
app.use(express.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: true }));
app.use(fileUpload()); app.use(fileUpload());
app.use(cors(corsOptions)); app.use(cors(corsOptions));
// app.use( app.use("/v1", swaggerUi.serve, swaggerUi.setup(specs, { explorer: true }));
// "/v1",
// swaggerUi.serve,
// swaggerUi.setup(specs , {explorer:true})
// );
// Require & Import API routes // Require & Import API routes
const Public = require("./routes/public"); const Public = require("./routes/public");
const admin = require("./routes/admin"); const admin = require("./routes/admin");
+5 -5
View File
@@ -1,11 +1,11 @@
const mongoose = require('mongoose'); const mongoose = require("mongoose");
const mongoosePaginate = require('mongoose-paginate-v2'); const mongoosePaginate = require("mongoose-paginate-v2");
const LoggerSchema = mongoose.Schema({ const LoggerSchema = mongoose.Schema({
LastLogin: String, LastLogin: String,
user :{type: mongoose.Schema.Types.ObjectId, ref: 'User'}, user: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
}); });
LoggerSchema.plugin(mongoosePaginate); LoggerSchema.plugin(mongoosePaginate);
module.exports = mongoose.model('Logger', LoggerSchema); module.exports = mongoose.model("Logger", LoggerSchema);
+4
View File
@@ -0,0 +1,4 @@
const NodeCache = require("node-cache");
class CacheService extends NodeCache {}
module.exports = new CacheService();
+12
View File
@@ -0,0 +1,12 @@
exports.paginationOptions = ({ page, limit, sort }) => {
const parsedPage = parseInt(page, 10) || 1;
const parsedLimit = parseInt(limit, 10) || 10;
const parsedSort = sort === "asc" ? "asc" : "desc";
return {
page: parsedPage,
limit: parsedLimit,
sort: parsedSort,
skip: (parsedPage - 1) * parsedLimit,
};
};
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
const axios = require("axios");
module.exports.sms = async (phoneNumber, message) => {
try {
// get token
const getToken = await axios.post("https://RestfulSms.com/api/Token", {
UserApiKey: "569ee43ed0d9ac27708ce43d",
SecretKey: "drtime@A!@#",
});
if (!getToken.data.IsSuccessful) {
throw new Error("sending sms failed");
}
const token = getToken.data.TokenKey;
//get lines
const resData = await axios.get("https://RestfulSms.com/api/SMSLine", {
headers: {
"Content-Type": "application/json",
"x-sms-ir-secure-token": token,
},
});
// message details
const data = {
Messages: [message],
MobileNumbers: [phoneNumber],
LineNumber: resData.data.SMSLines[0].LineNumber,
SendDateTime: "",
CanContinueInCaseOfError: "false",
};
const response = await axios.post(
`http://RestfulSms.com/api/MessageSend`,
data,
{
headers: {
"Content-Type": "application/json",
"x-sms-ir-secure-token": token,
},
}
);
return response.data;
} catch (e) {
console.log(e);
throw e;
}
};
+220 -151
View File
File diff suppressed because it is too large Load Diff
+89 -12
View File
@@ -1,7 +1,7 @@
const {Router} = require('express') const { Router } = require("express");
const router = Router() const router = Router();
const userController = require('../controllers/userController'); const userController = require("../controllers/userController");
const electionController = require('../controllers/electionController'); const electionController = require("../controllers/electionController");
/** /**
* @swagger * @swagger
@@ -48,7 +48,84 @@ const electionController = require('../controllers/electionController');
* description: Validation error. Indicates that the request body contains invalid data. * description: Validation error. Indicates that the request body contains invalid data.
*/ */
// Login User // Login User
router.post('/login', userController.login); router.post("/login", userController.login);
/**
* @swagger
* /auth/otp:
* post:
* summary: Send OTP to user for login
* description: Allows users to log in with their phone number by sending an OTP.
* tags:
* - Auth
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* phone:
* type: string
* example:
* phone: "09124569875"
* responses:
* 200:
* description: OTP sent successfully.
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example:
* message: "OTP sent successfully."
*/
router.post("/otp", userController.otp);
/**
* @swagger
* /auth/otp/verify:
* post:
* summary: Verify the OTP sent to user
* description: Allows users to log in by verifying the OTP sent to their phone number.
* tags:
* - Auth
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* phone:
* type: string
* code:
* type: string
* example:
* phone: "09124569875"
* code: "12345"
* responses:
* 200:
* description: User logged in successfully.
* content:
* application/json:
* schema:
* type: object
* properties:
* token:
* type: string
* example:
* token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
* 401:
* description: Unauthorized. Indicates that the provided credentials are invalid.
* 403:
* description: Forbidden. Indicates that the account is inactive. Contact the admin for assistance.
* 422:
* description: Validation error. Indicates that the request body contains invalid data.
*/
router.post("/otp/verify", userController.verifyOtp);
/** /**
* @swagger * @swagger
* /auth/logout: * /auth/logout:
@@ -73,7 +150,7 @@ router.post('/login', userController.login);
* description: Unauthorized. Indicates that the user is not logged in. * description: Unauthorized. Indicates that the user is not logged in.
*/ */
// Logout User // Logout User
router.delete('/logout', userController.logout); router.delete("/logout", userController.logout);
/** /**
* @swagger * @swagger
* /auth/user: * /auth/user:
@@ -96,7 +173,7 @@ router.delete('/logout', userController.logout);
* description: Unauthorized. Indicates that the user is not authenticated or the token is invalid. * description: Unauthorized. Indicates that the user is not authenticated or the token is invalid.
*/ */
// Data User // Data User
router.get('/user', userController.getuser); router.get("/user", userController.getuser);
/** /**
* @swagger * @swagger
* /auth/forget-password: * /auth/forget-password:
@@ -154,7 +231,7 @@ router.get('/user', userController.getuser);
* description: Error message indicating the internal server error. * description: Error message indicating the internal server error.
*/ */
// Change Password // Change Password
router.post('/changePassword' , userController.forgetPassGenerateToken); router.post("/changePassword", userController.forgetPassGenerateToken);
/** /**
* @swagger * @swagger
* /auth/changePassword/{token}: * /auth/changePassword/{token}:
@@ -213,7 +290,7 @@ router.post('/changePassword' , userController.forgetPassGenerateToken);
* description: Error message indicating the internal server error. * description: Error message indicating the internal server error.
*/ */
// Change Password :token param // Change Password :token param
router.put('/changePassword/:token' , userController.forgetPassGetToken); router.put("/changePassword/:token", userController.forgetPassGetToken);
///////// voter ///////// voter
@@ -272,7 +349,7 @@ router.put('/changePassword/:token' , userController.forgetPassGetToken);
*/ */
//Voter Login //Voter Login
router.post('/voter/login' , electionController.voterLogin); router.post("/voter/login", electionController.voterLogin);
/** /**
* @swagger * @swagger
* /auth/voter/user: * /auth/voter/user:
@@ -316,6 +393,6 @@ router.post('/voter/login' , electionController.voterLogin);
* description: Error message indicating the internal server error. * description: Error message indicating the internal server error.
*/ */
// user Voter Data // user Voter Data
router.get('/voter/user' , electionController.getVoterUser); router.get("/voter/user", electionController.getVoterUser);
module.exports = router module.exports = router;