mirror of
https://github.com/samanhappy/mcphub.git
synced 2025-12-24 02:39:19 -05:00
feat(auth): implement user authentication and password change functionality
This commit is contained in:
179
src/controllers/authController.ts
Normal file
179
src/controllers/authController.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import { Request, Response } from 'express';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { validationResult } from 'express-validator';
|
||||
import { findUserByUsername, verifyPassword, createUser, updateUserPassword } from '../models/User.js';
|
||||
|
||||
// Default secret key - in production, use an environment variable
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-this';
|
||||
const TOKEN_EXPIRY = '24h';
|
||||
|
||||
// Login user
|
||||
export const login = async (req: Request, res: Response): Promise<void> => {
|
||||
// Validate request
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
res.status(400).json({ success: false, errors: errors.array() });
|
||||
return;
|
||||
}
|
||||
|
||||
const { username, password } = req.body;
|
||||
|
||||
try {
|
||||
// Find user by username
|
||||
const user = findUserByUsername(username);
|
||||
|
||||
if (!user) {
|
||||
res.status(401).json({ success: false, message: 'Invalid credentials' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify password
|
||||
const isPasswordValid = await verifyPassword(password, user.password);
|
||||
|
||||
if (!isPasswordValid) {
|
||||
res.status(401).json({ success: false, message: 'Invalid credentials' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate JWT token
|
||||
const payload = {
|
||||
user: {
|
||||
username: user.username,
|
||||
isAdmin: user.isAdmin || false
|
||||
}
|
||||
};
|
||||
|
||||
jwt.sign(
|
||||
payload,
|
||||
JWT_SECRET,
|
||||
{ expiresIn: TOKEN_EXPIRY },
|
||||
(err, token) => {
|
||||
if (err) throw err;
|
||||
res.json({
|
||||
success: true,
|
||||
token,
|
||||
user: {
|
||||
username: user.username,
|
||||
isAdmin: user.isAdmin
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
|
||||
// Register new user
|
||||
export const register = async (req: Request, res: Response): Promise<void> => {
|
||||
// Validate request
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
res.status(400).json({ success: false, errors: errors.array() });
|
||||
return;
|
||||
}
|
||||
|
||||
const { username, password, isAdmin } = req.body;
|
||||
|
||||
try {
|
||||
// Create new user
|
||||
const newUser = await createUser({ username, password, isAdmin });
|
||||
|
||||
if (!newUser) {
|
||||
res.status(400).json({ success: false, message: 'User already exists' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate JWT token
|
||||
const payload = {
|
||||
user: {
|
||||
username: newUser.username,
|
||||
isAdmin: newUser.isAdmin || false
|
||||
}
|
||||
};
|
||||
|
||||
jwt.sign(
|
||||
payload,
|
||||
JWT_SECRET,
|
||||
{ expiresIn: TOKEN_EXPIRY },
|
||||
(err, token) => {
|
||||
if (err) throw err;
|
||||
res.json({
|
||||
success: true,
|
||||
token,
|
||||
user: {
|
||||
username: newUser.username,
|
||||
isAdmin: newUser.isAdmin
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
|
||||
// Get current user
|
||||
export const getCurrentUser = (req: Request, res: Response): void => {
|
||||
try {
|
||||
// User is already attached to request by auth middleware
|
||||
const user = (req as any).user;
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
user: {
|
||||
username: user.username,
|
||||
isAdmin: user.isAdmin
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Get current user error:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
|
||||
// Change password
|
||||
export const changePassword = async (req: Request, res: Response): Promise<void> => {
|
||||
// Validate request
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
res.status(400).json({ success: false, errors: errors.array() });
|
||||
return;
|
||||
}
|
||||
|
||||
const { currentPassword, newPassword } = req.body;
|
||||
const username = (req as any).user.username;
|
||||
|
||||
try {
|
||||
// Find user by username
|
||||
const user = findUserByUsername(username);
|
||||
|
||||
if (!user) {
|
||||
res.status(404).json({ success: false, message: 'User not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify current password
|
||||
const isPasswordValid = await verifyPassword(currentPassword, user.password);
|
||||
|
||||
if (!isPasswordValid) {
|
||||
res.status(401).json({ success: false, message: 'Current password is incorrect' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the password
|
||||
const updated = await updateUserPassword(username, newPassword);
|
||||
|
||||
if (!updated) {
|
||||
res.status(500).json({ success: false, message: 'Failed to update password' });
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({ success: true, message: 'Password updated successfully' });
|
||||
} catch (error) {
|
||||
console.error('Change password error:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user