87 lines
2.7 KiB
TypeScript
87 lines
2.7 KiB
TypeScript
import express, { Request, Response, NextFunction } from 'express';
|
|
import jwt from 'jsonwebtoken';
|
|
import bcrypt from 'bcrypt';
|
|
import { storage } from '../storage';
|
|
import { UserUncheckedCreateInputObjectSchema } from '@repo/db/shared/schemas';
|
|
import { z } from 'zod';
|
|
|
|
type SelectUser = z.infer<typeof UserUncheckedCreateInputObjectSchema>;
|
|
|
|
const JWT_SECRET = process.env.JWT_SECRET || 'your-jwt-secret';
|
|
const JWT_EXPIRATION = '24h'; // JWT expiration time (1 day)
|
|
|
|
// Function to hash password using bcrypt
|
|
async function hashPassword(password: string) {
|
|
const saltRounds = 10; // Salt rounds for bcrypt
|
|
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
|
return hashedPassword;
|
|
}
|
|
|
|
// Function to compare passwords using bcrypt
|
|
async function comparePasswords(supplied: string, stored: string) {
|
|
const isMatch = await bcrypt.compare(supplied, stored);
|
|
return isMatch;
|
|
}
|
|
|
|
// Function to generate JWT
|
|
function generateToken(user: SelectUser) {
|
|
return jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, {
|
|
expiresIn: JWT_EXPIRATION,
|
|
});
|
|
}
|
|
|
|
const router = express.Router();
|
|
|
|
|
|
// User registration route
|
|
router.post("/register", async (req: Request, res: Response, next: NextFunction): Promise<any> => {
|
|
|
|
try {
|
|
const existingUser = await storage.getUserByUsername(req.body.username);
|
|
if (existingUser) {
|
|
return res.status(400).send("Username already exists");
|
|
}
|
|
|
|
const hashedPassword = await hashPassword(req.body.password);
|
|
const user = await storage.createUser({
|
|
...req.body,
|
|
password: hashedPassword,
|
|
});
|
|
|
|
// Generate a JWT token for the user after successful registration
|
|
const token = generateToken(user);
|
|
|
|
const { password, ...safeUser } = user;
|
|
return res.status(201).json({ user: safeUser, token });
|
|
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// User login route
|
|
router.post("/login", async (req: Request, res: Response, next: NextFunction): Promise<any> => {
|
|
try {
|
|
const user = await storage.getUserByUsername(req.body.username);
|
|
if (!user || !(await comparePasswords(req.body.password, user.password))) {
|
|
return res.status(401).send("Invalid username or password");
|
|
}
|
|
|
|
// Generate a JWT token for the user after successful login
|
|
const token = generateToken(user);
|
|
const { password, ...safeUser } = user;
|
|
return res.status(200).json({ user: safeUser, token });
|
|
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
// Logout route (client-side action to remove the token)
|
|
router.post("/logout", (req: Request, res: Response) => {
|
|
// For JWT-based auth, logout is handled on the client (by removing token)
|
|
res.status(200).send("Logged out successfully");
|
|
});
|
|
|
|
|
|
export default router; |