Authorization & Permissions
ระบบสิทธิ์ใช้โมเดล 3-tier role + per-module permission overlay
3-Tier Role Hierarchy
จาก User.role (default operator):
superadmin ← bypass ทุกอย่าง
│
▼
admin ← bypass ทุกอย่าง
│
▼
manager / supervisor / ← role-based + per-module (สำหรับ admin portal)
operator / viewer| Role | คำอธิบาย | ขอบเขต |
|---|---|---|
superadmin | ผู้ดูแลระบบสูงสุด | ทุก action ทุก tenant |
admin | ผู้ดูแล tenant | ทุก action ใน tenant ตัวเอง |
manager | ผู้จัดการคลัง | approval, override, settings (จำกัด) |
supervisor | หัวหน้างาน | สร้าง/แก้ไข operation records |
operator | พนักงานคลัง | บันทึก task ที่ assign (pick/putaway) |
viewer | ผู้อ่านอย่างเดียว | view dashboard + reports |
Per-Module Permissions
นอกเหนือจาก role — User มี 2 columns พิเศษ:
adminModules String[] @default([]) @map("admin_modules") // READ
adminModulesWrite String[] @default([]) @map("admin_modules_write") // WRITEWrite implies Read — ถ้ามี write access จะอ่านได้อัตโนมัติ
ตัวอย่างผู้ใช้:
{
"role": "manager",
"adminModules": ["users", "audit", "reports.inventory"],
"adminModulesWrite": ["users"]
}→ manager คนนี้:
- Read+Write
users - Read
audit,reports.inventory - ไม่มีสิทธิ์เปิด module อื่น ๆ ใน Admin Portal
RolesGuard Logic
จาก apps/api/src/modules/auth/guards/roles.guard.ts:
canActivate(context): boolean {
const requiredRoles = reflector.getAllAndOverride(ROLES_KEY, ...);
const requiredModule = reflector.getAllAndOverride(REQUIRE_MODULE_KEY, ...);
// 1. No metadata → allow
if (!requiredRoles?.length && !requiredModule) return true;
const { user } = request;
if (!user) throw new ForbiddenException();
// 2. Admin / superadmin → bypass
if (user.role === 'admin' || user.role === 'superadmin') return true;
// 3. @Roles check
if (requiredRoles?.includes(user.role)) return true;
// 4. @RequireModule check
if (requiredModule) {
const reads = user.adminModules || [];
const writes = user.adminModulesWrite || [];
if (requiredModule.level === 'write') {
if (writes.includes(requiredModule.moduleName)) return true;
} else { // 'read'
if (reads.includes(requiredModule.moduleName) ||
writes.includes(requiredModule.moduleName)) return true;
}
}
throw new ForbiddenException('Access denied. Required: ...');
}ลำดับสำคัญ — admin role ชนะทุกอย่าง ไม่ต้องเช็ค modules
Decorators
@Roles('manager', 'supervisor')
อนุญาตเฉพาะ role ที่ระบุ (+ admin/superadmin โดยอัตโนมัติ)
@Get('approvals')
@Roles('manager', 'admin')
findPending() { ... }@RequireModule(moduleName, level)
ต้องการ permission key — level คือ 'read' หรือ 'write'
@Post()
@RequireModule('users', 'write')
create(@Body() dto: CreateUserDto) { ... }
@Get()
@RequireModule('users', 'read')
list() { ... }ใช้ได้ทั้ง class-level (ทุก endpoint ของ controller) หรือ method-level
@Public()
bypass JwtAuthGuard — สำหรับ /auth/login, /health/*
@CurrentUser() (param decorator)
extract request.user:
@Get('me')
me(@CurrentUser() user) { return user; }@ApiKey() + @ApiKeyScopes('write')
สำหรับ integration controller — extract request.apiKey + enforce scope
API Key Scopes
จาก ApiKey.scopes: String[]:
| Scope | สิทธิ์ |
|---|---|
read | GET endpoints (inquiry) |
write | POST / PATCH (upsert master, สร้าง orders) |
admin | super-scope — ผ่านทุก scope check |
ตั้งตอนสร้าง key ใน Admin Portal → API Keys
Admin Management Protection
UsersService.assertCanManageTarget(actor, target) — ป้องกัน:
- Non-admin แก้ admin
- Admin tenant A แก้ user ของ tenant B
- ใครก็ตามทำ self-demotion สุดท้าย admin คนเดียวออก
(เช็คใน service layer ก่อน update/delete)
Module Catalog
รายการ module keys ทั้งหมดที่ใช้ใน adminModules / adminModulesWrite:
Core
| Key | หน้า Admin |
|---|---|
dashboard | Dashboard |
users | Users |
roles | Roles |
warehouses | Warehouses |
Master Data
| Key | หน้า |
|---|---|
master-data.items | Items |
master-data.locations | Locations |
master-data.uoms | UoMs |
master-data.partners | Partners |
Operations
| Key | หน้า |
|---|---|
inbound.asn | ASN |
inbound.grn | GRN |
inbound.putaway-rules | Putaway Rules |
outbound.orders | Orders |
outbound.waves | Waves |
outbound.pick-tasks | Pick Tasks |
outbound.shipments | Shipments |
inventory.stock | Stock |
inventory.movements | Movements |
inventory.adjustments | Adjustments |
inventory.cycle-counts | Cycle Counts |
returns.rma | RMA |
lpn | License Plates |
replenishment.rules | Replenishment Rules |
replenishment.tasks | Replenishment Tasks |
approvals | Approvals |
System
| Key | หน้า |
|---|---|
audit | Audit Logs |
announcements | Announcements |
api-keys | API Keys |
webhooks | Webhooks |
wms-settings | WMS Settings (8 tabs) |
global-config | Global Config |
health | System Health |
Reports
| Key | หน้า |
|---|---|
reports.inventory | Inventory Reports |
reports.receiving | Receiving Reports |
reports.outbound | Outbound Reports |
reports.delivery | Delivery Reports |
reports.users | User Reports |
ดู workflow การตั้ง permission: Per-Module Permissions