0

[Series Thực Chiến E-commerce] Bài 11: "Trảm" tài khoản vi phạm - Viết API Xóa User cho Admin

Chào anh em! Lại là mình với series tự tay nặn ra hệ thống E-commerce đây.

Ở Bài 10, ông Admin của chúng ta đã có đặc quyền ngồi xem toàn bộ danh sách khách hàng nhờ vào trạm gác phân quyền isAdmin. Nhưng xem thôi thì chưa đủ "đô". Giả sử cuối tuần đẹp trời, Admin lướt danh sách thấy một mớ tài khoản clone, spammer chuyên tạo đơn ảo phá shop thì phải làm sao? Chắc chắn là phải có một cái nút "Xóa" (Delete) để tiễn mấy thành phần này "bay màu" khỏi cơ sở dữ liệu rồi!

Hôm nay, công việc của anh em mình khá nhẹ nhàng: Viết một API Xóa User. Cùng mổ xẻ đoạn code dưới đây nhé!

1. Hàm "Thi hành án" (Controller)

Để xóa một document trong MongoDB, Mongoose cung cấp cho chúng ta một hàm cực kỳ tiện lợi là findByIdAndDelete(). Anh em chỉ cần quăng cái ID của user vào, nó sẽ dọn dẹp sạch sẽ.

Mở file controllers/user.js và thêm đoạn này vào:

const deleteUser = asyncHandler(async (req, res) => {
  // Bốc cái _id từ URL query string (ví dụ: /api/user/deleteuser?_id=12345)
  const { _id } = req.query;

  // Validate sương sương, không truyền ID thì đuổi về
  if (!_id) {
    throw new Error('Missing inputs - Bạn chưa cung cấp ID của User cần xóa!');
  }

  // Gọi Mongoose ra thi hành án
  const response = await User.findByIdAndDelete(_id);

  return res.status(200).json({
    // Nếu response có data tức là xóa thành công (true), ngược lại là false
    success: !!response, 
    // Trả về câu thông báo cho Front-end biết đường mà hiện popup
    deletedUser: response
      ? `Tài khoản có email ${response.email} đã bị xóa vĩnh viễn`
      : 'Không tìm thấy user nào để xóa',
  });
});

module.exports = {
  getUsers,
  deleteUser, // Xuất xưởng
};

💡 Góc nhìn thực chiến & Góp ý nhỏ cho anh em: Đoạn code trên của bạn chạy hoàn toàn ngon lành. Tuy nhiên, nếu muốn ứng dụng đạt chuẩn RESTful API cao nhất, người ta thường không dùng req.query (truyền qua dấu ?) cho phương thức DELETE. Thay vào đó, họ sẽ dùng req.params (truyền thẳng vào đường dẫn). Ví dụ: DELETE /api/user/12345. Lúc đó code controller sẽ lấy ID bằng const { id } = req.params;. Anh em tham khảo thêm tip này để múa code cho ngầu nhé, còn hiện tại cứ giữ nguyên req.query để chạy cũng không sao cả!

2. Cắm chốt bảo vệ ở Router

Cái nút "Xóa" này quyền lực quá lớn. Nếu để hớ hênh, user bình thường táy máy gọi API xóa luôn tài khoản của ông khác (thậm chí xóa luôn cả Admin) thì đúng là thảm họa.

Vì vậy, anh em tuyệt đối không được quên bế 2 "anh bảo vệ" từ Bài 10 sang đây đứng gác. Mở routers/user.js:

const express = require('express');
const router = express.Router();
const ctrls = require('../controllers/user');
const { verifyAccessToken, isAdmin } = require('../middlewares/verifyToken');

// ... các route auth và getalluser

// Route xóa user: PHẢI CÓ TOKEN & PHẢI LÀ ADMIN mới được vào
router.delete('/deleteuser', [verifyAccessToken, isAdmin], ctrls.deleteUser);

module.exports = router;

Bật Postman lên test thôi!

Đăng nhập bằng tài khoản Admin lấy accessToken.

Gọi request DELETE vào http://localhost:5000/api/user/deleteuser?_id=... (copy một cái ID tài khoản rác thả vào).

Nhận dòng chữ báo đã xóa email thành công là anh em có thể kê cao gối ngủ rồi.

Lời kết

Xóa thì nhanh và dứt khoát thật đấy. Nhưng đời sống thực tế, ít khi Admin xóa thẳng tay (trừ khi là spammer). Thường thì khách hàng chỉ muốn cập nhật lại thông tin cá nhân (đổi tên, thêm địa chỉ, cập nhật số điện thoại...), hoặc Admin muốn khóa (block) tài khoản đó tạm thời chứ không xóa hẳn.

Đó chính là lúc chúng ta cần đến phương thức PUT để Update dữ liệu. Bài viết cũng đủ ý rồi, anh em nghỉ tay chút xíu trước khi chuyển sang Lession 12: Update User nhé.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí