From e1c47fed890531818d72957fe432a27973467914 Mon Sep 17 00:00:00 2001 From: Kfir Dayan Date: Thu, 8 Jun 2023 19:53:03 +0300 Subject: [PATCH] login added + middleware --- package-lock.json | 12 ++++++++++- package.json | 3 ++- src/auth/index.ts | 1 - src/controllers/UserController.ts | 30 +++++++++++++++++++++++++++- src/index.ts | 5 +++++ src/middlewares/authMiddleware.ts | 33 +++++++++++++++++++++++++++++++ src/models/User.ts | 24 +++++++++++++++++++--- src/routes/user.ts | 3 ++- 8 files changed, 103 insertions(+), 8 deletions(-) delete mode 100644 src/auth/index.ts create mode 100644 src/middlewares/authMiddleware.ts diff --git a/package-lock.json b/package-lock.json index d826af2..ff3550f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,8 @@ }, "devDependencies": { "@types/bcryptjs": "^2.4.2", - "@types/express": "^4.17.17" + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2" } }, "node_modules/@types/bcryptjs": { @@ -70,6 +71,15 @@ "@types/send": "*" } }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", diff --git a/package.json b/package.json index 2b1fae5..434a22d 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ }, "devDependencies": { "@types/bcryptjs": "^2.4.2", - "@types/express": "^4.17.17" + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2" } } diff --git a/src/auth/index.ts b/src/auth/index.ts deleted file mode 100644 index 6987588..0000000 --- a/src/auth/index.ts +++ /dev/null @@ -1 +0,0 @@ -import JWT from 'jsonwebtoken'; diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 2d5462b..43a2995 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -1,6 +1,7 @@ import { Request, Response } from 'express'; import bcrypt from 'bcryptjs'; -import User, { IUser } from '../models/User'; +import jwt from 'jsonwebtoken'; +import { User, IUser } from '../models/User'; export async function createUser(req: Request, res: Response) { try { @@ -24,3 +25,30 @@ export async function createUser(req: Request, res: Response) { res.status(500).json({ error: 'An error occurred while creating the user.' }); } } + +export async function login(req: Request, res: Response) { + try { + const { email, password } = req.body; + + // Check if the user exists + const user: IUser | null = await User.findOne({ email }); + if (!user) { + return res.status(401).json({ error: 'Invalid email or password' }); + } + + // Compare the provided password with the stored password + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return res.status(401).json({ error: 'Invalid email or password' }); + } + + // Generate a JWT + const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET as string); + + // Send the JWT as the response + res.json({ token }); + } catch (error) { + console.error('Error during login:', error); + res.status(500).json({ error: 'An error occurred during login' }); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 9ee83c0..32f03fa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import express from 'express'; import mongoose from 'mongoose'; +import { authenticateToken } from './middlewares/authMiddleware'; import userRoutes from './routes/user'; const env = require('dotenv').config().parsed; @@ -8,19 +9,23 @@ const app = express(); const PORT = 3000; app.use(express.json()); +app.use(authenticateToken); // Connect to MongoDB using Mongoose mongoose.connect(env.DATABASE_URL); const db = mongoose.connection; +// Check for DB connection db.on('error', console.error.bind(console, 'MongoDB connection error:')); db.once('open', () => { console.log('Connected to MongoDB'); }); +// Routes app.use('/users', userRoutes); +// Start server app.listen(PORT, () => { console.log(`Server started on port ${PORT}`); }); diff --git a/src/middlewares/authMiddleware.ts b/src/middlewares/authMiddleware.ts new file mode 100644 index 0000000..8ee1156 --- /dev/null +++ b/src/middlewares/authMiddleware.ts @@ -0,0 +1,33 @@ +import { Request, Response, NextFunction } from 'express'; +import jwt, { JwtPayload } from 'jsonwebtoken'; + +interface AuthenticatedRequest extends Request { + user?: JwtPayload | string; +} + +const exceptionRoutes: string[] = ['/login', '/']; + +// Middleware function to authenticate requests +export function authenticateToken(req: AuthenticatedRequest, res: Response, next: NextFunction) { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; + + if (!token && exceptionRoutes.includes(req.originalUrl)) { + return res.sendStatus(401); // Unauthorized + } + + if (!exceptionRoutes.includes(req.originalUrl)) { + // Skip authentication for exception routes + return next(); + } + + jwt.verify(token as string, process.env.JWT_SECRET as string, (err, user) => { + if (err) { + return res.sendStatus(403); // Forbidden + } + + // Store the authenticated user in the request object + req.user = user as JwtPayload | string; + next(); + }); +} diff --git a/src/models/User.ts b/src/models/User.ts index 7485137..022a3c5 100644 --- a/src/models/User.ts +++ b/src/models/User.ts @@ -10,16 +10,34 @@ export interface IUser extends Document { updatedAt: Date; } +export interface IProduct extends Document { + name: string; + description: string; + price: number; + createdAt: Date; + updatedAt: Date; +} + const UserSchema: Schema = new Schema({ firstName: { type: String, required: true }, lastName: { type: String, required: true }, - email: { type: String, required: true }, + email: { type: String, required: true, unique: true }, password: { type: String, required: true }, address: { type: String, required: true }, createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now }, }); -const User = mongoose.model('User', UserSchema); +const ProductSchema: Schema = new Schema({ + name: { type: String, required: true }, + description: { type: String, required: true }, + price: { type: Number, required: true }, + userId: { type: Schema.Types.ObjectId, ref: 'User' }, + createdAt: { type: Date, default: Date.now }, + updatedAt: { type: Date, default: Date.now }, +}); -export default User; +const User = mongoose.model('User', UserSchema); +const Product = mongoose.model('Product', ProductSchema); + +export { User, Product }; diff --git a/src/routes/user.ts b/src/routes/user.ts index ef3e0ed..aa8797d 100644 --- a/src/routes/user.ts +++ b/src/routes/user.ts @@ -1,8 +1,9 @@ import express from 'express'; -import { createUser } from '../controllers/UserController'; +import { createUser, login } from '../controllers/UserController'; const router = express.Router(); router.post('/', createUser); +router.post('/login', login) export default router; \ No newline at end of file