Added signin route in backend

This commit is contained in:
Manik Maity
2024-11-08 12:51:14 +05:30
parent edfce3edaa
commit 582daa2c3b
9 changed files with 256 additions and 28 deletions

View File

@@ -10,9 +10,11 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"express": "^4.21.1", "express": "^4.21.1",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.8.0", "mongoose": "^8.8.0",
"socket.io": "^4.8.1", "socket.io": "^4.8.1",
"swagger-jsdoc": "^6.2.8", "swagger-jsdoc": "^6.2.8",
@@ -324,6 +326,12 @@
"node": ">=16.20.1" "node": ">=16.20.1"
} }
}, },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause"
},
"node_modules/bytes": { "node_modules/bytes": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -427,6 +435,28 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/cookie-parser": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
"license": "MIT",
"dependencies": {
"cookie": "0.7.2",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": { "node_modules/cookie-signature": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -530,6 +560,15 @@
"url": "https://dotenvx.com" "url": "https://dotenvx.com"
} }
}, },
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1013,6 +1052,55 @@
"js-yaml": "bin/js-yaml.js" "js-yaml": "bin/js-yaml.js"
} }
}, },
"node_modules/jsonwebtoken": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
"license": "MIT",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^7.5.4"
},
"engines": {
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jsonwebtoken/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"license": "MIT",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/kareem": { "node_modules/kareem": {
"version": "2.6.3", "version": "2.6.3",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
@@ -1028,18 +1116,60 @@
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
"license": "MIT"
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
"license": "MIT"
},
"node_modules/lodash.isequal": { "node_modules/lodash.isequal": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
"license": "MIT"
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
"license": "MIT"
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"license": "MIT"
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
"license": "MIT"
},
"node_modules/lodash.mergewith": { "node_modules/lodash.mergewith": {
"version": "4.6.2", "version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
"integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
"license": "MIT"
},
"node_modules/make-dir": { "node_modules/make-dir": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",

View File

@@ -13,9 +13,11 @@
"description": "", "description": "",
"dependencies": { "dependencies": {
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"express": "^4.21.1", "express": "^4.21.1",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.8.0", "mongoose": "^8.8.0",
"socket.io": "^4.8.1", "socket.io": "^4.8.1",
"swagger-jsdoc": "^6.2.8", "swagger-jsdoc": "^6.2.8",

View File

@@ -4,3 +4,4 @@ dotenv.config();
export const PORT = Number(process.env.PORT); export const PORT = Number(process.env.PORT);
export const DB_URL = process.env.DB_CONNECTION; export const DB_URL = process.env.DB_CONNECTION;
export const SALT = Number(process.env.SALT_ROUNDS); export const SALT = Number(process.env.SALT_ROUNDS);
export const JWT_PRIVATE = process.env.JWT_PRIVATE;

View File

@@ -1,28 +1,55 @@
import { signupService } from "../services/user.service.js"; import { signinService, signupService } from "../services/user.service.js";
export async function signupController(req, res) { export async function signupController(req, res) {
try { try {
const { username, email, password } = req.body; const { username, email, password } = req.body;
const user = await signupService(username, email, password); const user = await signupService(username, email, password);
res.status(201).json({ res.status(201).json({
success : true, success: true,
message : "User created successfully", message: "User created successfully",
data : user data: user,
}) });
} } catch (err) {
catch(err){
console.log(err); console.log(err);
if (err.statusCode){ if (err.statusCode) {
res.status(err.statusCode).json({ res.status(err.statusCode).json({
success : false, success: false,
message : err.message message: err.message,
}) });
} } else {
else {
res.status(500).json({ res.status(500).json({
success : false, success: false,
message : err.message message: err.message,
}) });
}
}
}
export async function signinController(req, res) {
try {
const { email, password } = req.body;
const { token, userData } = await signinService(email, password);
res.cookie("access-token", token, {
httpOnly: true,
maxAge: 10 * 24 * 60 * 60 * 1000, // 10 days
}).status(200).json({
success : true,
message : "User signedin successfully.",
user : userData
});
} catch (err) {
console.log(err);
if (err.statusCode) {
res.status(err.statusCode).json({
success: false,
message: err.message,
});
} else {
res.status(500).json({
success: false,
message: err.message,
});
} }
} }
} }

View File

@@ -7,6 +7,7 @@ import { connectDB } from './config/dbConfig.js';
import userRouter from './routes/v1/user.route.js'; import userRouter from './routes/v1/user.route.js';
import swaggerDocs from '../swagger.js'; import swaggerDocs from '../swagger.js';
import swaggerUi from 'swagger-ui-express'; import swaggerUi from 'swagger-ui-express';
import cookieParser from "cookie-parser";
const app = express(); const app = express();
@@ -20,6 +21,7 @@ const io = new Server(httpServer, {
} }
}) })
app.use(cookieParser());
app.use(cors()) app.use(cors())
app.use(express.json()) app.use(express.json())
app.get("/ping", (_req, res) => { app.get("/ping", (_req, res) => {

View File

@@ -14,3 +14,13 @@ export const createUser = async (username, email, password) => {
throw err throw err
} }
} }
export async function findUserByEmail(email) {
try{
const user = await UserModel.findOne({email});
return user;
}
catch(err){
throw err;
}
}

View File

@@ -1,7 +1,8 @@
import express from "express"; import express from "express";
import { signupController } from "../../controllers/user.controller.js"; import { signinController, signupController } from "../../controllers/user.controller.js";
import validate from "../../validations/validator.js"; import validate from "../../validations/validator.js";
import signupSchema from "../../validations/signupValidation.js"; import signupSchema from "../../validations/signupValidation.js";
import signinSchema from "../../validations/signinValidation.js";
const userRouter = express.Router(); const userRouter = express.Router();
/** /**
@@ -39,4 +40,6 @@ userRouter.get("/test", (req, res) => {
*/ */
userRouter.post("/signup", validate(signupSchema), signupController); userRouter.post("/signup", validate(signupSchema), signupController);
userRouter.post("/signin", validate(signinSchema), signinController);
export default userRouter; export default userRouter;

View File

@@ -1,6 +1,7 @@
import { SALT } from "../config/veriables.js"; import { JWT_PRIVATE, SALT } from "../config/veriables.js";
import { createUser } from "../repositories/user.repo.js"; import { createUser, findUserByEmail } from "../repositories/user.repo.js";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
export async function signupService(username, email, password) { export async function signupService(username, email, password) {
try { try {
@@ -24,3 +25,35 @@ export async function signupService(username, email, password) {
} }
} }
} }
export async function signinService(email, password) {
try{
if (email.trim() == "" || password.trim() == "") {
throw {
statusCode: 400,
message: "All fields are required",
};
}
const user = await findUserByEmail(email);
if (!user){
throw {
statusCode : 404,
message : "User not found."
}
}
if (!bcrypt.compareSync(password, user?.password)){
throw {
statusCode : 401,
message : "Password isn't correct."
}
}
const token = jwt.sign({id : user._id}, JWT_PRIVATE);
const {password:pass, ...userData} = user._doc;
return {token, userData};
}
catch(err){
throw err;
}
}

View File

@@ -0,0 +1,20 @@
import { z } from "zod";
const signinSchema = z.object({
email: z
.string({
required_error: "Email is required.",
})
.min(1, "Email is required.")
.max(200, "Email cant be more then 200 charecters.")
.email("Invalid email input"),
password: z
.string({
required_error: "Password is required",
})
.min(6, "Password cant be less than 6 charecters")
.max(50, "Password cant be more than 50 charecters"),
});
export default signinSchema;