node-backend-generator
Version:
🚀 CLI tool to generate professional Node.js backend templates with best practices, multiple databases, authentication, and production-ready features
188 lines (161 loc) • 4.57 kB
JavaScript
import jwt from 'jsonwebtoken';
import bcrypt from 'bcryptjs';
import { User } from '../models/User.js';
import { redis } from '../config/redis.js';
import { authQueue } from '../queues/authQueue.js';
export class AuthController {
async register(req, res) {
try {
const { name, email, password } = req.body;
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({
success: false,
error: 'User already exists'
});
}
const user = await User.create({ name, email, password });
const accessToken = jwt.sign(
{ userId: user.id, service: 'auth' },
process.env.JWT_ACCESS_SECRET,
{ expiresIn: process.env.JWT_ACCESS_EXPIRES_IN }
);
const refreshToken = jwt.sign(
{ userId: user.id, service: 'auth' },
process.env.JWT_REFRESH_SECRET,
{ expiresIn: process.env.JWT_REFRESH_EXPIRES_IN }
);
await redis.set(`refresh_token:${user.id}`, refreshToken, 'EX', 60 * 60 * 24 * 7);
await authQueue.add('send-welcome-email', {
userId: user.id,
email: user.email,
name: user.name
});
res.status(201).json({
success: true,
message: 'User registered successfully',
data: {
user: {
id: user.id,
name: user.name,
email: user.email
},
tokens: {
accessToken,
refreshToken
}
}
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
}
async login(req, res) {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({
success: false,
error: 'Invalid credentials'
});
}
const isMatch = await user.comparePassword(password);
if (!isMatch) {
return res.status(400).json({
success: false,
error: 'Invalid credentials'
});
}
const accessToken = jwt.sign(
{ userId: user.id, service: 'auth' },
process.env.JWT_ACCESS_SECRET,
{ expiresIn: process.env.JWT_ACCESS_EXPIRES_IN }
);
const refreshToken = jwt.sign(
{ userId: user.id, service: 'auth' },
process.env.JWT_REFRESH_SECRET,
{ expiresIn: process.env.JWT_REFRESH_EXPIRES_IN }
);
await redis.set(`refresh_token:${user.id}`, refreshToken, 'EX', 60 * 60 * 24 * 7);
res.json({
success: true,
message: 'Login successful',
data: {
user: {
id: user.id,
name: user.name,
email: user.email
},
tokens: {
accessToken,
refreshToken
}
}
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
}
async refreshToken(req, res) {
try {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(400).json({
success: false,
error: 'Refresh token required'
});
}
const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
const storedToken = await redis.get(`refresh_token:${decoded.userId}`);
if (storedToken !== refreshToken) {
return res.status(401).json({
success: false,
error: 'Invalid refresh token'
});
}
const accessToken = jwt.sign(
{ userId: decoded.userId, service: 'auth' },
process.env.JWT_ACCESS_SECRET,
{ expiresIn: process.env.JWT_ACCESS_EXPIRES_IN }
);
res.json({
success: true,
data: { accessToken }
});
} catch (error) {
res.status(401).json({
success: false,
error: 'Invalid refresh token'
});
}
}
async validateToken(req, res) {
try {
const { token } = req.body;
if (!token) {
return res.status(400).json({
success: false,
error: 'Token required'
});
}
const decoded = jwt.verify(token, process.env.JWT_ACCESS_SECRET);
res.json({
success: true,
data: { valid: true, user: decoded }
});
} catch (error) {
res.json({
success: true,
data: { valid: false }
});
}
}
}
export default new AuthController();