TTMT.ManageWebGUI/SYSTEM_ADMIN_PRIORITY_GUIDE.md

5.6 KiB

System Admin Priority Logic - Hướng dẫn

Tổng quan

Đã cập nhật logic để System Admin (Priority = 0) trở thành quyền cao nhất trong hệ thống.

Quy tắc Priority

Priority càng thấp = Quyền càng cao
Priority = 0 (System Admin) = Quyền cao nhất

Các thay đổi đã thực hiện

1. Constants mới (src/config/constants.ts)

export const SYSTEM_ADMIN_PRIORITY = 0;

export const RolePriority = {
  SYSTEM_ADMIN: 0,
} as const;

Mục đích: Định nghĩa giá trị priority của System Admin, tránh hardcode số 0 trong code.


2. Helper Functions (src/helpers/roleHelpers.ts)

isSystemAdminPriority(priority: number): boolean

Kiểm tra xem priority có phải là System Admin không.

import { isSystemAdminPriority } from '@/helpers/roleHelpers';

if (isSystemAdminPriority(userPriority)) {
  // User là System Admin
}

hasHigherOrEqualPriority(priority1, priority2): boolean

So sánh 2 priority (nhỏ hơn = cao hơn).

if (hasHigherOrEqualPriority(userPriority, requiredPriority)) {
  // User có đủ quyền
}

getPriorityLabel(priority: number): string

Lấy nhãn mô tả cho priority.

getPriorityLabel(0) // "System Admin (Highest)"
getPriorityLabel(5) // "Priority 5"

3. useAuth Hook (src/hooks/useAuth.tsx)

Thêm method mới: isSystemAdmin()

const { isSystemAdmin } = useAuth();

if (isSystemAdmin()) {
  // User là System Admin (priority = 0)
  console.log('You have highest permission!');
}

Interface cập nhật:

export interface IAuthContext {
  // ... các field cũ
  isSystemAdmin: () => boolean; // ← Mới
}

4. Sidebar Logic (src/components/sidebars/app-sidebar.tsx)

Cập nhật logic kiểm tra admin:

// TRƯỚC
const isAdmin = acs.includes(PermissionEnum.ALLOW_ALL);

// SAU
const isAdmin = acs.includes(PermissionEnum.ALLOW_ALL) || isSystemAdmin();

Lợi ích:

  • System Admin (Priority = 0) thấy tất cả menu items
  • Không cần phải có permission ALLOW_ALL trong database

Cách sử dụng

Kiểm tra System Admin trong component

import { useAuth } from '@/hooks/useAuth';

function MyComponent() {
  const { isSystemAdmin, role } = useAuth();
  
  return (
    <div>
      {isSystemAdmin() && (
        <AdminOnlyFeature />
      )}
      
      <p>Role: {role.roleName}</p>
      <p>Priority: {role.priority}</p>
    </div>
  );
}

Kiểm tra priority trong logic nghiệp vụ

import { isSystemAdminPriority, hasHigherOrEqualPriority } from '@/helpers/roleHelpers';

function canDeleteUser(currentUserPriority: number, targetUserPriority: number): boolean {
  // System Admin có thể xóa bất kỳ ai
  if (isSystemAdminPriority(currentUserPriority)) {
    return true;
  }
  
  // User chỉ có thể xóa user có priority thấp hơn (số lớn hơn)
  return hasHigherOrEqualPriority(currentUserPriority, targetUserPriority);
}

Hiển thị label priority

import { getPriorityLabel } from '@/helpers/roleHelpers';

<Badge>{getPriorityLabel(role.priority)}</Badge>
// System Admin sẽ hiển thị: "System Admin (Highest)"

Luồng kiểm tra quyền

User đăng nhập
    ↓
Priority được lưu vào localStorage
    ↓
useAuth hook load priority
    ↓
isSystemAdmin() kiểm tra priority === 0
    ↓
Sidebar check: ALLOW_ALL || isSystemAdmin()
    ↓
Hiển thị menu items phù hợp

Ví dụ thực tế

Ví dụ 1: Ẩn/hiện nút Delete dựa trên priority

function UserManagement() {
  const { role, isSystemAdmin } = useAuth();
  const currentUserPriority = role.priority;
  
  function canDelete(targetUserPriority: number): boolean {
    // System Admin xóa được tất cả
    if (isSystemAdmin()) return true;
    
    // Priority thấp hơn (số nhỏ hơn) mới xóa được
    return currentUserPriority < targetUserPriority;
  }
  
  return (
    <Table>
      {users.map(user => (
        <TableRow key={user.id}>
          <TableCell>{user.name}</TableCell>
          <TableCell>
            {canDelete(user.role.priority) && (
              <DeleteButton userId={user.id} />
            )}
          </TableCell>
        </TableRow>
      ))}
    </Table>
  );
}

Ví dụ 2: Route protection

import { useAuth } from '@/hooks/useAuth';
import { redirect } from '@tanstack/react-router';

export const Route = createFileRoute('/_auth/admin-panel')({
  beforeLoad: ({ context }) => {
    const { isSystemAdmin } = context.auth;
    
    if (!isSystemAdmin()) {
      throw redirect({
        to: '/unauthorized',
      });
    }
  },
  component: AdminPanel,
});

Tóm tắt

Priority = 0 là System Admin (quyền cao nhất)
Priority thấp hơn = Quyền cao hơn
Có constants và helpers để tái sử dụng
isSystemAdmin() method trong useAuth hook
Sidebar tự động nhận biết System Admin
Không cần hardcode giá trị priority nữa


Files đã thay đổi

  1. src/config/constants.ts - Constants mới
  2. src/helpers/roleHelpers.ts - Helper functions
  3. src/hooks/useAuth.tsx - Thêm isSystemAdmin()
  4. src/types/auth.ts - Cập nhật interface
  5. src/components/sidebars/app-sidebar.tsx - Logic admin check

Lưu ý quan trọng:
Backend cũng cần implement logic tương tự để đảm bảo consistency giữa frontend và backend!