[Series Thực Chiến E-commerce] Bài 13: Quyền lực tối thượng - Admin "thao túng" data User
Chào anh em!
Hôm trước ở Bài 12, chúng ta đã làm xong tính năng cho phép User tự cập nhật thông tin cá nhân. Nhờ việc lấy ID trực tiếp từ Token giải mã (req.user._id), chúng ta đã khóa chặt cửa, không cho User này sửa data của User khác.
Nhưng ở góc độ quản trị hệ thống thì sao? Sẽ có những lúc Admin nhận được cú điện thoại: "Em ơi, anh nhập sai số điện thoại lúc đăng ký, em sửa giùm anh với", hoặc Admin phát hiện ra một tài khoản chuyên đi bom hàng và muốn đổi trạng thái isBlocked của tài khoản đó thành true.
Lúc này, Admin cần một API có khả năng truyền ID của bất kỳ ai vào để sửa. Đây chính là quyền lực tối thượng của Admin. Cùng triển khai nhé!
1. Viết Controller: Lấy ID từ URL (Dynamic Params)
Sự khác biệt lớn nhất giữa API này và API ở Bài 12 nằm ở chỗ: ID cần sửa đến từ đâu? Thay vì lấy ID giấu kín trong Token, lần này chúng ta sẽ cho phép Frontend truyền thẳng ID của mục tiêu lên thanh URL.
Anh em mở controllers/user.js và thêm hàm này vào:
const updateUserByAdmin = asyncHandler(async (req, res) => {
// 💡 Lấy UID từ params (đường dẫn URL), thay vì từ req.user
const { uid } = req.params;
// Validate: Chặn mấy pha gọi API mà body rỗng tuếch
if (Object.keys(req.body).length === 0) {
throw new Error('Missing inputs - Không có dữ liệu để cập nhật');
}
// Gọi Mongoose update mục tiêu
const response = await User.findByIdAndUpdate(
uid,
req.body,
{ new: true } // Vẫn phải có cờ này để Mongoose trả về data MỚI
).select('-password -role'); // Che giấu dữ liệu nhạy cảm
return res.status(200).json({
success: response ? true : false,
updatedUser: response ? response : 'Something went wrong'
});
});
module.exports = {
// ... các hàm cũ
updateUserByAdmin,
};
2. Định tuyến API: Dùng Params chuẩn RESTful
Ở Bài 11 (Xóa User), mình có nhắc nhẹ anh em về việc dùng req.query (dấu ?) chưa được "chuẩn" RESTful API cho lắm. Thì đến bài này, đoạn code Router của anh em đã dùng chuẩn URL Parameters.
Anh em mở routers/user.js ra và nối dây cho nó:
const express = require('express');
const router = express.Router();
const ctrls = require('../controllers/user');
const { verifyAccessToken, isAdmin } = require('../middlewares/verifyToken');
// ... các routes khác
// Route Admin Update User
// Dấu hai chấm (:) ám chỉ 'uid' là một biến động (Dynamic Param)
router.put('/updateUserByAdmin/:uid', [verifyAccessToken, isAdmin], ctrls.updateUserByAdmin);
module.exports = router;
Cách test trên Postman:
- Anh em dùng tài khoản có quyền
adminđể lấy token gán vào Header - Bắn request PUT vào đường dẫn: http://localhost:5000/api/user/updateUserByAdmin/64abc123... (thay cái chuỗi lằng nhằng kia bằng ID thực tế của một thằng user rác nào đó trong DB).
- Trong body, truyền lên JSON {
"isBlocked": true}. Bấm Send và tận hưởng kết quả tài khoản đó bị khóa mỏ ngay lập tức!
Lời kết cho Module User
Vậy là xin chúc mừng anh em! Chúng ta đã hoàn thành trọn vẹn Module User (Người dùng) & Authentication (Xác thực). Từ việc đúc database, đăng ký, đăng nhập, cấp token, refresh token, gửi email quên pass, cho đến các thao tác CRUD (Thêm/Đọc/Sửa/Xóa) phân quyền rõ ràng giữa User và Admin.
Đây là phần xương xẩu nhất của mọi hệ thống. Làm xong phần này là coi như anh em đã nắm được cốt lõi của việc xây dựng Backend với Node.js rồi đấy.
Nhưng web bán hàng mà không có hàng thì bán cho ai? Tiếp theo, chúng ta sẽ chuyển sang một module mới tinh, hấp dẫn không kém: Quản lý Sản phẩm (Product).
Anh em chuẩn bị súng ống đạn dược cho Lession 14: Add product chưa? Hãy ném cho mình cấu trúc Product Model và Controller tạo sản phẩm của bạn, để mình xem thử anh em xử lý cái cục data sản phẩm phức tạp này (như hình ảnh, giá cả, số lượng tồn kho...) như thế nào nhé!
All rights reserved