From 099303995b0da22359cc9ded209c709d1370dae5 Mon Sep 17 00:00:00 2001 From: Chris Chen Date: Thu, 25 Jun 2026 15:21:11 -0700 Subject: [PATCH] fix(expense-snapshot): gate page on Expenses:write to match the write-only API The snapshot management page backs an API that gates every action on Expenses:Write, so a read-only user reaching it via a read-gated nav/route would hit a silent 403 and a blank page. Require write for both. Co-Authored-By: Claude Opus 4.8 --- APP/src/app/app.routes.ts | 4 +++- APP/src/app/portals/user-portal/user-portal.component.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/APP/src/app/app.routes.ts b/APP/src/app/app.routes.ts index 3ae8f7f..7695999 100644 --- a/APP/src/app/app.routes.ts +++ b/APP/src/app/app.routes.ts @@ -168,7 +168,9 @@ export const routes: Routes = [ component: ExpenseSnapshotsPageComponent, canActivate: [PermissionGuard], data: { - permission: { module: PermissionModules.Expenses, action: 'read' }, + // Snapshots are a write-only management surface (the API gates every action on + // Expenses:Write), so require write — a read-only user has nothing to do here. + permission: { module: PermissionModules.Expenses, action: 'write' }, title: 'Expense Snapshots', titleZh: '費用範本', section: 'Finance', }, }, diff --git a/APP/src/app/portals/user-portal/user-portal.component.ts b/APP/src/app/portals/user-portal/user-portal.component.ts index e7a2353..1d1c991 100644 --- a/APP/src/app/portals/user-portal/user-portal.component.ts +++ b/APP/src/app/portals/user-portal/user-portal.component.ts @@ -133,7 +133,7 @@ export class UserPortalComponent implements OnInit, OnDestroy { { text: 'Expense Categories', icon: categorizeIcon, path: '/user-portal/finance/expense-categories', permission: { module: PermissionModules.ExpenseCategories, action: 'read' } }, { text: 'Expense Snapshots', icon: categorizeIcon, path: '/user-portal/finance/expense-snapshots', - permission: { module: PermissionModules.Expenses, action: 'read' } }, + permission: { module: PermissionModules.Expenses, action: 'write' } }, { text: 'Disbursements', icon: banknoteOutlineIcon, path: '/user-portal/finance/disbursements', permission: { module: PermissionModules.Disbursements, action: 'read' } }, { text: 'Check Register', icon: walletOutlineIcon, path: '/user-portal/finance/check-register',