login added + middleware

This commit is contained in:
Kfir Dayan 2023-06-08 19:53:03 +03:00
parent 5c831c8f06
commit e1c47fed89
8 changed files with 103 additions and 8 deletions

12
package-lock.json generated
View file

@ -18,7 +18,8 @@
}, },
"devDependencies": { "devDependencies": {
"@types/bcryptjs": "^2.4.2", "@types/bcryptjs": "^2.4.2",
"@types/express": "^4.17.17" "@types/express": "^4.17.17",
"@types/jsonwebtoken": "^9.0.2"
} }
}, },
"node_modules/@types/bcryptjs": { "node_modules/@types/bcryptjs": {
@ -70,6 +71,15 @@
"@types/send": "*" "@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": { "node_modules/@types/mime": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",

View file

@ -18,6 +18,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/bcryptjs": "^2.4.2", "@types/bcryptjs": "^2.4.2",
"@types/express": "^4.17.17" "@types/express": "^4.17.17",
"@types/jsonwebtoken": "^9.0.2"
} }
} }

View file

@ -1 +0,0 @@
import JWT from 'jsonwebtoken';

View file

@ -1,6 +1,7 @@
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import bcrypt from 'bcryptjs'; 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) { export async function createUser(req: Request, res: Response) {
try { 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.' }); 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' });
}
}

View file

@ -1,5 +1,6 @@
import express from 'express'; import express from 'express';
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import { authenticateToken } from './middlewares/authMiddleware';
import userRoutes from './routes/user'; import userRoutes from './routes/user';
const env = require('dotenv').config().parsed; const env = require('dotenv').config().parsed;
@ -8,19 +9,23 @@ const app = express();
const PORT = 3000; const PORT = 3000;
app.use(express.json()); app.use(express.json());
app.use(authenticateToken);
// Connect to MongoDB using Mongoose // Connect to MongoDB using Mongoose
mongoose.connect(env.DATABASE_URL); mongoose.connect(env.DATABASE_URL);
const db = mongoose.connection; const db = mongoose.connection;
// Check for DB connection
db.on('error', console.error.bind(console, 'MongoDB connection error:')); db.on('error', console.error.bind(console, 'MongoDB connection error:'));
db.once('open', () => { db.once('open', () => {
console.log('Connected to MongoDB'); console.log('Connected to MongoDB');
}); });
// Routes
app.use('/users', userRoutes); app.use('/users', userRoutes);
// Start server
app.listen(PORT, () => { app.listen(PORT, () => {
console.log(`Server started on port ${PORT}`); console.log(`Server started on port ${PORT}`);
}); });

View file

@ -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();
});
}

View file

@ -10,16 +10,34 @@ export interface IUser extends Document {
updatedAt: Date; updatedAt: Date;
} }
export interface IProduct extends Document {
name: string;
description: string;
price: number;
createdAt: Date;
updatedAt: Date;
}
const UserSchema: Schema = new Schema({ const UserSchema: Schema = new Schema({
firstName: { type: String, required: true }, firstName: { type: String, required: true },
lastName: { 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 }, password: { type: String, required: true },
address: { type: String, required: true }, address: { type: String, required: true },
createdAt: { type: Date, default: Date.now }, createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now },
}); });
const User = mongoose.model<IUser>('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<IUser>('User', UserSchema);
const Product = mongoose.model<IProduct>('Product', ProductSchema);
export { User, Product };

View file

@ -1,8 +1,9 @@
import express from 'express'; import express from 'express';
import { createUser } from '../controllers/UserController'; import { createUser, login } from '../controllers/UserController';
const router = express.Router(); const router = express.Router();
router.post('/', createUser); router.post('/', createUser);
router.post('/login', login)
export default router; export default router;