Refactor privilege management to support hierarchical privilege keys

- Updated privilege key structure to use a 3- or 4-part dotted hierarchy (e.g., `GROUP.PARENT.MODULE`).
- Modified the `RequirePrivilege` decorator to accept multiple keys, allowing for OR logic in privilege checks.
- Enhanced `PrivilegesGuard` to validate against multiple privilege keys, improving access control logic.
- Created migration scripts to update existing privilege keys in the database to the new format.
- Updated related services, controllers, and tests to accommodate the new privilege key structure and validation logic.
This commit is contained in:
shancheas
2026-09-01 13:14:58 +07:00
parent 365a37b8d2
commit 51db4f4a4d
45 changed files with 466 additions and 162 deletions
@@ -29,7 +29,7 @@ import { CurrentUser } from '../../../common/decorators/current-user.decorator';
import { RequirePrivilege } from '../../../common/decorators/require-privilege.decorator';
import { BEARER_AUTH_NAME } from '../../../common/swagger/setup-swagger';
import { isAllowedCsvUpload } from '../shared/sales-fields';
import { SALES_INVOICE_PRIVILEGE_KEY } from './sales-invoices-read.controller';
import { SALES_INVOICE_PRIVILEGE_KEYS } from './sales-invoices-read.controller';
import { SalesInvoicesService } from './sales-invoices.service';
import {
BulkIdsDto,
@@ -47,7 +47,7 @@ export class SalesInvoicesWriteController {
constructor(private readonly salesInvoicesService: SalesInvoicesService) {}
@Post('import')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEY, 'import')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEYS, 'import')
@UseInterceptors(
FileInterceptor('file', {
limits: { fileSize: 1_048_576 },
@@ -86,7 +86,7 @@ export class SalesInvoicesWriteController {
@Post('bulk-delete')
@HttpCode(200)
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEY, 'delete')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEYS, 'delete')
@ApiOperation({ summary: 'Bulk delete sales invoices' })
@ApiOkResponse({
schema: { properties: { deleted: { type: 'number' } } },
@@ -99,7 +99,7 @@ export class SalesInvoicesWriteController {
@Post('bulk-status')
@HttpCode(200)
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEY, 'update')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEYS, 'update')
@ApiOperation({ summary: 'Bulk update sales invoice status' })
@ApiOkResponse({
schema: { properties: { updated: { type: 'number' } } },
@@ -118,7 +118,7 @@ export class SalesInvoicesWriteController {
}
@Post()
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEY, 'create')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEYS, 'create')
@ApiOperation({ summary: 'Create sales invoice' })
@ApiCreatedResponse({ type: SalesInvoiceDto })
@ApiUnauthorizedResponse()
@@ -147,7 +147,7 @@ export class SalesInvoicesWriteController {
}
@Patch(':id/status')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEY, 'update')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEYS, 'update')
@ApiOperation({ summary: 'Update sales invoice status' })
@ApiOkResponse({ type: SalesInvoiceDto })
@ApiNotFoundResponse()
@@ -162,7 +162,7 @@ export class SalesInvoicesWriteController {
}
@Patch(':id')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEY, 'update')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEYS, 'update')
@ApiOperation({ summary: 'Update sales invoice (not status)' })
@ApiOkResponse({ type: SalesInvoiceDto })
@ApiNotFoundResponse()
@@ -193,7 +193,7 @@ export class SalesInvoicesWriteController {
@Delete(':id')
@HttpCode(204)
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEY, 'delete')
@RequirePrivilege(SALES_INVOICE_PRIVILEGE_KEYS, 'delete')
@ApiOperation({ summary: 'Delete sales invoice' })
@ApiNoContentResponse()
@ApiNotFoundResponse()