# Hệ Thống Phân Quyền - Permission System Guide

## Tổng Quan

Hệ thống phân quyền được thiết kế theo luồng: **User → Role → Role_Permissions → Permissions**

```
User (user_id) 
  ↓
Role (role_id) 
  ↓  
Role_Permissions (role_id, permission_id)
  ↓
Permissions (permission_id, permission_code)
```

## Cấu Trúc Database

### 1. Bảng Users
```sql
CREATE TABLE users (
  user_id VARCHAR(36) PRIMARY KEY,
  username VARCHAR(50) UNIQUE NOT NULL,
  email VARCHAR(100) UNIQUE NOT NULL,
  password VARCHAR(255) NOT NULL,
  full_name VARCHAR(100),
  phone VARCHAR(20),
  is_active TINYINT(1) DEFAULT 1,
  role_id VARCHAR(36),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (role_id) REFERENCES roles(role_id)
);
```

### 2. Bảng Roles
```sql
CREATE TABLE roles (
  role_id VARCHAR(36) PRIMARY KEY,
  role_name VARCHAR(50) UNIQUE NOT NULL,
  description TEXT,
  is_active TINYINT(1) DEFAULT 1,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
```

### 3. Bảng Permissions
```sql
CREATE TABLE permissions (
  permission_id VARCHAR(36) PRIMARY KEY,
  permission_name VARCHAR(100) NOT NULL,
  permission_code VARCHAR(50) UNIQUE NOT NULL,
  description TEXT,
  is_active TINYINT(1) DEFAULT 1,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
```

### 4. Bảng Role_Permissions (Junction Table)
```sql
CREATE TABLE role_permissions (
  role_id VARCHAR(36),
  permission_id VARCHAR(36),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (role_id, permission_id),
  FOREIGN KEY (role_id) REFERENCES roles(role_id) ON DELETE CASCADE,
  FOREIGN KEY (permission_id) REFERENCES permissions(permission_id) ON DELETE CASCADE
);
```

## Middleware Phân Quyền

### 1. Authentication Middleware
```javascript
const { authMiddleware } = require('./middlewares/auth.middleware');

// Sử dụng cơ bản
router.get('/protected-route', authMiddleware, (req, res) => {
  // req.user chứa thông tin user đã xác thực
  res.json({ user: req.user });
});
```

### 2. Role-based Authorization
```javascript
const { authorize } = require('./middlewares/auth.middleware');

// Chỉ cho phép role 'admin'
router.get('/admin-only', 
  authMiddleware, 
  authorize('admin'), 
  (req, res) => {
    res.json({ message: 'Admin access granted' });
  }
);

// Cho phép nhiều roles
router.get('/manager-or-admin', 
  authMiddleware, 
  authorize(['admin', 'manager']), 
  (req, res) => {
    res.json({ message: 'Manager or Admin access granted' });
  }
);
```

### 3. Permission-based Authorization
```javascript
const { checkPermission, checkAnyPermission, checkAllPermissions } = require('./middlewares/auth.middleware');

// Kiểm tra 1 permission cụ thể
router.get('/users', 
  authMiddleware, 
  checkPermission('user.read'), 
  (req, res) => {
    res.json({ message: 'User list access granted' });
  }
);

// Kiểm tra nhiều permissions (OR logic - chỉ cần 1)
router.post('/users', 
  authMiddleware, 
  checkAnyPermission(['user.create', 'user.update']), 
  (req, res) => {
    res.json({ message: 'User creation access granted' });
  }
);

// Kiểm tra nhiều permissions (AND logic - cần tất cả)
router.get('/reports/export', 
  authMiddleware, 
  checkAllPermissions(['report.view', 'report.export']), 
  (req, res) => {
    res.json({ message: 'Report export access granted' });
  }
);
```

## Cách Sử Dụng Trong Routes

### Ví dụ Routes với Phân Quyền

```javascript
const express = require('express');
const router = express.Router();
const { 
  authMiddleware, 
  authorize, 
  checkPermission, 
  checkAnyPermission 
} = require('../middlewares/auth.middleware');

// Public routes (không cần xác thực)
router.get('/public', (req, res) => {
  res.json({ message: 'Public data' });
});

// Protected routes (cần đăng nhập)
router.get('/profile', authMiddleware, (req, res) => {
  res.json({ user: req.user });
});

// Role-based protection
router.get('/admin-panel', 
  authMiddleware, 
  authorize('admin'), 
  (req, res) => {
    res.json({ message: 'Admin panel' });
  }
);

// Permission-based protection
router.get('/users', 
  authMiddleware, 
  checkPermission('user.read'), 
  (req, res) => {
    res.json({ message: 'User list' });
  }
);

// Kết hợp nhiều middleware
router.delete('/users/:id', 
  authMiddleware, 
  checkPermission('user.delete'),
  (req, res) => {
    res.json({ message: 'User deleted' });
  }
);
```

## Permission Codes Thường Dùng

### User Management
- `user.read` - Xem danh sách user
- `user.create` - Tạo user mới
- `user.update` - Cập nhật thông tin user
- `user.delete` - Xóa user

### Product Management
- `product.read` - Xem sản phẩm
- `product.create` - Tạo sản phẩm mới
- `product.update` - Cập nhật sản phẩm
- `product.delete` - Xóa sản phẩm

### Order Management
- `order.read` - Xem đơn hàng
- `order.create` - Tạo đơn hàng
- `order.update` - Cập nhật đơn hàng
- `order.delete` - Xóa đơn hàng
- `order.export` - Xuất báo cáo đơn hàng

### System Management
- `system.settings` - Cài đặt hệ thống
- `system.backup` - Sao lưu dữ liệu
- `system.logs` - Xem logs hệ thống

## Cách Thiết Lập Permissions

### 1. Tạo Permissions
```sql
INSERT INTO permissions (permission_id, permission_name, permission_code, description, is_active) VALUES
(UUID(), 'User Read', 'user.read', 'View user information', 1),
(UUID(), 'User Create', 'user.create', 'Create new users', 1),
(UUID(), 'User Update', 'user.update', 'Update user information', 1),
(UUID(), 'User Delete', 'user.delete', 'Delete users', 1);
```

### 2. Tạo Roles
```sql
INSERT INTO roles (role_id, role_name, description, is_active) VALUES
(UUID(), 'admin', 'Administrator with full access', 1),
(UUID(), 'manager', 'Manager with limited access', 1),
(UUID(), 'user', 'Regular user with basic access', 1);
```

### 3. Gán Permissions cho Roles
```sql
-- Gán tất cả permissions cho admin
INSERT INTO role_permissions (role_id, permission_id) 
SELECT r.role_id, p.permission_id 
FROM roles r, permissions p 
WHERE r.role_name = 'admin';

-- Gán một số permissions cho manager
INSERT INTO role_permissions (role_id, permission_id) 
SELECT r.role_id, p.permission_id 
FROM roles r, permissions p 
WHERE r.role_name = 'manager' 
AND p.permission_code IN ('user.read', 'product.read', 'product.update');
```

## Kiểm Tra Quyền Trong Code

### 1. Sử dụng Permission Service
```javascript
const PermissionService = require('../services/permission.service');

// Kiểm tra user có quyền cụ thể
const hasPermission = await PermissionService.checkUserPermission(userId, 'user.read');

// Lấy tất cả quyền của user
const userPermissions = await PermissionService.getUserPermissions(userId);

// Kiểm tra user có role cụ thể
const hasRole = await PermissionService.checkUserRole(userId, 'admin');
```

### 2. Sử dụng trong Controller
```javascript
exports.deleteUser = async (req, res, next) => {
  try {
    const userId = req.params.id;
    const currentUserId = req.user.user_id;
    
    // Kiểm tra quyền xóa user
    const canDelete = await PermissionService.checkUserPermission(currentUserId, 'user.delete');
    
    if (!canDelete) {
      return res.status(403).json({
        success: false,
        message: 'Access denied: You do not have permission to delete users'
      });
    }
    
    // Thực hiện xóa user
    const result = await UserService.deleteUser(userId);
    res.json({ success: true, message: 'User deleted successfully' });
  } catch (error) {
    next(error);
  }
};
```

## Best Practices

### 1. Đặt tên Permission Codes
- Sử dụng format: `module.action` (ví dụ: `user.read`, `product.create`)
- Tên ngắn gọn, dễ hiểu
- Tránh trùng lặp

### 2. Tổ chức Roles
- Tạo roles theo chức năng: `admin`, `manager`, `user`, `guest`
- Mỗi role có bộ permissions phù hợp
- Tránh tạo quá nhiều roles

### 3. Bảo mật
- Luôn kiểm tra quyền ở cả frontend và backend
- Sử dụng middleware để tự động hóa việc kiểm tra
- Log các hoạt động quan trọng

### 4. Performance
- Cache permissions nếu cần
- Sử dụng indexes cho các truy vấn thường xuyên
- Tránh kiểm tra quyền quá nhiều lần trong 1 request

## Troubleshooting

### 1. Lỗi "Access denied"
- Kiểm tra user có role không
- Kiểm tra role có permissions không
- Kiểm tra permissions có active không

### 2. Lỗi "Authentication required"
- Kiểm tra token có hợp lệ không
- Kiểm tra user có active không
- Kiểm tra token có hết hạn không

### 3. Debug Permissions
```javascript
// Kiểm tra quyền của user
const userPermissions = await PermissionService.getUserPermissions(userId);
console.log('User permissions:', userPermissions);

// Kiểm tra role của user
const userRole = await PermissionService.getUserRoleAndPermissions(userId);
console.log('User role and permissions:', userRole);
```
