Files
spotlightcam/backend/src/controllers/user.js

150 lines
4.5 KiB
JavaScript
Raw Normal View History

const { prisma } = require('../utils/db');
const { hashPassword, comparePassword, generateToken, generateVerificationToken, generateVerificationCode } = require('../utils/auth');
const { sendVerificationEmail } = require('../utils/email');
const { sanitizeForEmail } = require('../utils/sanitize');
/**
* Update user profile
* PATCH /api/users/me
*/
async function updateProfile(req, res, next) {
try {
const userId = req.user.id;
const { firstName, lastName, email, wsdcId, youtubeUrl, instagramUrl, facebookUrl, tiktokUrl } = req.body;
// Build update data
const updateData = {};
if (firstName !== undefined) updateData.firstName = firstName;
if (lastName !== undefined) updateData.lastName = lastName;
if (wsdcId !== undefined) updateData.wsdcId = wsdcId || null; // Allow empty string to clear WSDC ID
if (youtubeUrl !== undefined) updateData.youtubeUrl = youtubeUrl || null;
if (instagramUrl !== undefined) updateData.instagramUrl = instagramUrl || null;
if (facebookUrl !== undefined) updateData.facebookUrl = facebookUrl || null;
if (tiktokUrl !== undefined) updateData.tiktokUrl = tiktokUrl || null;
// Check if email is being changed
const currentUser = await prisma.user.findUnique({
where: { id: userId },
select: { email: true },
});
let emailChanged = false;
if (email && email !== currentUser.email) {
// Check if new email is already taken by another user
const existingUser = await prisma.user.findUnique({
where: { email },
});
if (existingUser && existingUser.id !== userId) {
return res.status(400).json({
success: false,
error: 'Email is already registered to another account',
});
}
// Email is being changed - require re-verification
updateData.email = email;
updateData.emailVerified = false;
updateData.verificationToken = generateVerificationToken();
updateData.verificationCode = generateVerificationCode();
updateData.verificationTokenExpiry = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours
emailChanged = true;
}
// Update user
const updatedUser = await prisma.user.update({
where: { id: userId },
data: updateData,
});
// If email changed, send verification email
if (emailChanged) {
try {
await sendVerificationEmail(
updatedUser.email,
sanitizeForEmail(updatedUser.firstName || updatedUser.username),
updatedUser.verificationToken,
updatedUser.verificationCode
);
} catch (emailError) {
console.error('Failed to send verification email:', emailError);
// Continue anyway - user is updated but email might not have been sent
}
}
// Generate new JWT token (in case emailVerified changed)
const token = generateToken({ userId: updatedUser.id });
// Remove sensitive data
const { passwordHash, verificationToken, verificationCode, verificationTokenExpiry, resetToken, resetTokenExpiry, ...userWithoutPassword } = updatedUser;
res.json({
success: true,
message: emailChanged
? 'Profile updated. Please verify your new email address.'
: 'Profile updated successfully',
data: {
user: userWithoutPassword,
token,
emailChanged,
},
});
} catch (error) {
next(error);
}
}
/**
* Change password
* PATCH /api/users/me/password
*/
async function changePassword(req, res, next) {
try {
const userId = req.user.id;
const { currentPassword, newPassword } = req.body;
if (!currentPassword || !newPassword) {
return res.status(400).json({
success: false,
error: 'Current password and new password are required',
});
}
// Get user with password
const user = await prisma.user.findUnique({
where: { id: userId },
});
// Verify current password
const isPasswordValid = await comparePassword(currentPassword, user.passwordHash);
if (!isPasswordValid) {
return res.status(401).json({
success: false,
error: 'Current password is incorrect',
});
}
// Hash new password
const hashedPassword = await hashPassword(newPassword);
// Update password
await prisma.user.update({
where: { id: userId },
data: { passwordHash: hashedPassword },
});
res.json({
success: true,
message: 'Password changed successfully',
});
} catch (error) {
next(error);
}
}
module.exports = {
updateProfile,
changePassword,
};