Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 1x 4x 4x 4x 4x 2x 4x 1x 6x 6x 6x 6x 6x 3x 3x 1x 2x 1x 1x 1x 6x 6x 6x 6x 6x 3x 3x 1x 2x 2x 2x 2x 1x 2x 2x 1x 2x 2x 1x 2x 2x 1x 2x 2x 1x 2x 2x | import type { Role } from '@prisma/client';
// =============================================================================
// Permission rules — locked by client 2026-05-20 (consolidated single-system)
// =============================================================================
//
// One system, two roles (MASTER / STAFF). No subdomain split.
//
// USER MANAGEMENT RULES (final, 2026-05-20):
// - CREATE: STAFF can create only STAFF users. MASTER can create either role.
// - EDIT/DELETE/RESET: STAFF can act only on themselves.
// MASTER can act on themselves AND on STAFF users.
// No peer editing (Master cannot touch another Master,
// Staff cannot touch another Staff).
// No upward editing (Staff cannot touch Master).
//
// USER SECTION restrictions (unchanged):
// - "รับสินค้า & log" page: MASTER only.
// - Inventory: STAFF cannot use the import flow.
// - Transfer: STAFF cannot use bulk-accept ("กดรับเฟสทั้งหมดที่แจ้ง").
// - Transfer initiation: MASTER → COMPLETED immediately,
// STAFF → PENDING, awaits MASTER approval.
//
// =============================================================================
// ----- USER MANAGEMENT -----
export function canCreateUserWithRole(
actorRole: Role,
targetRole: Role,
): boolean {
if (actorRole === 'MASTER') return true;
return actorRole === 'STAFF' && targetRole === 'STAFF';
}
/**
* Can the actor edit / delete / change-role of the target?
*
* Strict rules: self always allowed; downward only for MASTER → STAFF;
* no peer (same role, different user); no upward (STAFF → MASTER).
*/
export function canManageUser(
actor: { id: string; role: Role },
target: { id: string; role: Role },
): boolean {
if (actor.id === target.id) return true;
if (actor.role === 'MASTER' && target.role === 'STAFF') return true;
return false;
}
export function assignableRoles(actorRole: Role): Role[] {
if (actorRole === 'MASTER') return ['MASTER', 'STAFF'];
return ['STAFF'];
}
// ----- PASSWORD RESET -----
//
// Rules (client 2026-05-20):
// MASTER can: reset self, reset any STAFF. Cannot reset another MASTER.
// STAFF can: reset self only.
//
// "Reset self" = change-password flow (requires current password).
// "Reset other (Master → Staff)" = force-reset flow (no current password).
// If a MASTER forgets their own password, recovery is a DBA task (no peer-reset
// path) — this is acceptable for a 10-20-user internal system.
export function canResetPassword(
actor: { id: string; role: Role },
target: { id: string; role: Role },
): boolean {
if (actor.id === target.id) return true; // self-reset
if (actor.role === 'MASTER' && target.role === 'STAFF') return true; // master → staff
return false; // everything else blocked
}
// ----- TRANSFER WORKFLOW -----
//
// MASTER initiating a transfer: created directly as COMPLETED.
// STAFF initiating a transfer: created as PENDING — must be approved by a MASTER.
// Only MASTER can approve / reject a pending transfer.
export function transferInitialStatus(
actorRole: Role,
): 'PENDING' | 'COMPLETED' {
return actorRole === 'MASTER' ? 'COMPLETED' : 'PENDING';
}
export function canApproveTransfer(role: Role): boolean {
return role === 'MASTER';
}
// ----- USER SECTION -----
/** Can the user see the "รับสินค้า & log" menu / open /reception? */
export function canSeeReception(role: Role): boolean {
return role === 'MASTER';
}
/** Inventory page: can the user use the import-product flow? */
export function canImportInventory(role: Role): boolean {
return role === 'MASTER';
}
/** Transfer page: can the user press "กดรับเฟสทั้งหมดที่แจ้ง" (bulk-accept)? */
export function canBulkAcceptTransfer(role: Role): boolean {
return role === 'MASTER';
}
/** Settings (reference data CRUD): MASTER only. */
export function canManageSettings(role: Role): boolean {
return role === 'MASTER';
}
|