Sửa lỗi cập nhật thông tin hồ sơ

This commit is contained in:
2026-06-09 17:01:23 +07:00
parent b4b193c72c
commit 18e1c3d76d
9 changed files with 54 additions and 5 deletions
+50 -5
View File
@@ -943,7 +943,14 @@ router.get('/me/profile', protect, async (req, res) => {
try {
const user = await User.findById(req.user._id).select('-password').lean();
// Đảm bảo các trường này luôn tồn tại để frontend không bị lỗi undefined
user.fullName = user.fullName || '';
user.email = user.email || '';
user.avatarUrl = user.avatarUrl || '';
// Tính toán dung lượng thực tế của người dùng
// Logic này đã được tối ưu hóa bằng Aggregation ở các bước trước
// và được giữ nguyên để trả về thông tin storage cho frontend
const usageResult = await Asset.aggregate([
{ $match: { uploadedBy: req.user._id } },
{
@@ -1010,21 +1017,59 @@ router.get('/me/assets/top-large', protect, async (req, res) => {
* @desc Cập nhật hồ sơ (đổi tên, mật khẩu)
* @access Private
*/
router.put('/me/profile', protect, async (req, res) => {
router.put('/me/profile', protect, upload.single('avatar'), async (req, res, next) => {
try {
const user = await User.findById(req.user._id);
if (!user) return res.status(404).json({ message: 'User not found' });
if (req.body.username) user.username = req.body.username;
if (req.body.password) user.password = req.body.password; // Hook pre-save sẽ tự hash
const { fullName, email, username, password } = req.body;
if (fullName) user.fullName = fullName;
if (email) user.email = email;
// Chỉ cho phép cập nhật username nếu nó khác với username hiện tại
if (username && user.username !== username) {
user.username = username;
} else if (username && user.username === username) {
// Nếu username không đổi, không cần gán lại để tránh trigger unique validation không cần thiết
} else if (!username) {
// Nếu frontend gửi username rỗng, có thể là lỗi hoặc cố ý xóa, cần xử lý tùy theo business logic
}
if (password && password.trim() !== '') user.password = password;
// Xử lý ảnh đại diện nếu có upload
if (req.file) {
// Xóa avatar cũ nếu có và không phải là avatar mặc định
if (user.avatarUrl && user.avatarUrl.startsWith('/api/assets/view_avatar/')) {
const oldAvatarName = user.avatarUrl.split('/').pop();
const oldAvatarPath = path.join(uploadDir, oldAvatarName);
if (fs.existsSync(oldAvatarPath)) fs.unlinkSync(oldAvatarPath);
}
const avatarName = `avatar_${user._id}${path.extname(req.file.originalname)}`;
const avatarPath = path.join(uploadDir, avatarName);
await sharp(req.file.path)
.resize(200, 200) // Resize avatar về kích thước nhỏ (200x200)
.toFile(avatarPath);
user.avatarUrl = `/api/assets/view_avatar/${avatarName}`; // Lưu đường dẫn ảnh vào DB
if (fs.existsSync(req.file.path)) fs.unlinkSync(req.file.path); // Xóa file tạm
}
// Sử dụng validateBeforeSave: false để bỏ qua validation cho các trường không được gửi lên
// hoặc các trường không liên quan đến việc cập nhật hồ sơ cá nhân như agreedToRules, role.
// Tuy nhiên, các validation cho các trường được cập nhật (như email, username unique) vẫn sẽ chạy.
await user.save({ validateBeforeSave: false });
await user.save();
res.json({
message: 'Hồ sơ đã được cập nhật',
user: { id: user._id, username: user.username, role: user.role }
});
} catch (error) {
res.status(500).json({ message: error.message });
// Xử lý lỗi validation của Mongoose
if (error.name === 'ValidationError') {
return res.status(400).json({ message: error.message });
}
next(error); // Chuyển lỗi khác cho middleware xử lý lỗi chung
}
});