[Series Thực Chiến E-commerce] Bài 12: Khách hàng tự "tút tát" profile - API Cập nhật thông tin User
Chào anh em! Lại tiếp tục hành trình "độ" con app E-commerce của chúng ta nào.
Ở bài trước, Admin đã ra oai với nút Xóa (Delete) rồi. Nhưng thực tế thì trang bán hàng nào cũng phải có một trang "Tài khoản của tôi" để khách hàng tự cập nhật thông tin cá nhân (đổi tên, thêm số điện thoại, cập nhật địa chỉ giao hàng...).
Bài hôm nay cực kỳ thú vị vì đoạn code anh em chuẩn bị chứa một "tuyệt chiêu bảo mật" ngầm mà rất nhiều Newbie thường xuyên mắc lỗi ngớ ngẩn. Cùng bóc tách nó ra nhé!
1. Não bộ xử lý (Controller) & Điểm sáng Bảo mật
Anh em mở file controllers/user.js và thêm hàm này vào:
const updateUser = asyncHandler(async (req, res) => {
// 💡 ĐIỂM SÁNG BẢO MẬT LÀ ĐÂY: Lấy _id từ req.user (Token)
const { _id } = req.user;
// Check xem user có gửi data gì lên không, hay gửi form rỗng?
if (!_id || Object.keys(req.body).length === 0) {
throw new Error('Missing inputs - Bạn chưa nhập thông tin cần cập nhật');
}
// Gọi Mongoose update data
const response = await User.findByIdAndUpdate(
_id,
req.body,
{ new: true } // 💡 KINH NGHIỆM: Phải có option này!
).select('-password -role'); // Vẫn bài cũ: Ém hàng password và role lại
return res.status(200).json({
success: !!response,
updateUser: response || 'Something went wrong',
});
});
module.exports = {
// ... các hàm cũ
updateUser,
};
Tại sao mình lại gọi const { _id } = req.user; là điểm sáng bảo mật?
Nhiều anh em mới học thường viết API update kiểu: Lấy ID từ client gửi lên (req.body.id hoặc req.params.id).
Làm thế là TOANG! Một thằng hacker (hoặc một user biết chút IT) đăng nhập vào tài khoản của nó, nhưng lúc gửi request update, nó cố tình sửa cái ID thành ID của người khác hoặc của Admin. Thế là tự nhiên nó đi đổi tên, đổi địa chỉ của người khác ngon ơ.
Vì vậy, đối với hành động "User tự sửa thông tin của chính mình", chúng ta bắt buộc phải lấy ID từ cái Token đã được giải mã (req.user), vì Token do Server cấp thì không thể làm giả được. User nào đăng nhập thì chỉ sửa được đúng data của user đó. Đỉnh chưa?
Về cái option { new: true }:
Hàm findByIdAndUpdate mặc định sẽ trả về cái document cũ (trước khi update). Nếu anh em không truyền{ new: true } vào, Frontend nhận cục data về sẽ hiển thị sai bét (rõ ràng vừa đổi tên thành Nguyễn B mà màn hình vẫn hiện Nguyễn A). Nhớ nhé!
2. Cắm chốt ở Router
Tính năng này dành cho User bình thường, nên chúng ta không cần gọi "anh bảo vệ" Admin ra làm gì cả. Chỉ cần check xem người ta đã đăng nhập chưa là đủ.
Anh em mở file routers/user.js:
const express = require('express');
const router = express.Router();
const ctrls = require('../controllers/user');
const { verifyAccessToken, isAdmin } = require('../middlewares/verifyToken');
// ... các routes trước đó
// Route cập nhật User: CHỈ CẦN CÓ TOKEN
router.put('/updateUser', [verifyAccessToken], ctrls.updateUser);
module.exports = router;
Bật Postman lên, lấy Access Token của một User bình thường nhét vào Authorization. Bắn một cục JSON chứa firstname hoặc lastname mới vào body qua cổng PUT http://localhost:5000/api/user/updateUser. Trả về data mới tinh là anh em lại được kê cao gối ngủ tiếp rồi.
Lời kết
Xong chức năng cho khách hàng tự sửa nhà của họ. Nhưng ở vị trí là một người quản trị hệ thống, ông Admin cũng cần quyền sửa thông tin của bất kỳ ai (ví dụ: khách gọi điện lên tổng đài nhờ cập nhật sđt hộ, hoặc Admin muốn đổi trạng thái isBlocked thành true để khóa mỏ một gã hay bom hàng).
Đó sẽ là bài toán của Lession 13: Update User By Admin.
All Rights Reserved