feat(auth): add module read/write admin RBAC

Introduce permission catalog, PermissionsGuard, JWT/me payload with
role+permissions, and gate all module controllers. Admins CRUD accepts
role/permissions with safety rules; migrate existing users to super_admin.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-10 15:29:04 +03:30
co-authored by Cursor
parent 4b3a8a1d6c
commit af1e217a68
28 changed files with 532 additions and 75 deletions
+16 -1
View File
@@ -10,6 +10,8 @@ import {
UseGuards,
} from '@nestjs/common';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { PermissionsGuard } from '../auth/permissions.guard';
import { RequirePermissions } from '../auth/permissions.decorator';
import { CurrentUser } from '../auth/current-user.decorator';
import {
ChargeSmsWalletDto,
@@ -20,31 +22,36 @@ import {
import { SmsService } from './sms.service';
@Controller('sms')
@UseGuards(JwtAuthGuard)
@UseGuards(JwtAuthGuard, PermissionsGuard)
export class SmsController {
constructor(private readonly smsService: SmsService) {}
@Get('tenants')
@RequirePermissions('sms:read')
listTenants() {
return this.smsService.listTenants();
}
@Get('lowest')
@RequirePermissions('sms:read')
lowest(@Query('limit') limit?: string) {
return this.smsService.getLowestBalances(Number(limit) || 5);
}
@Get('tenants/:id')
@RequirePermissions('sms:read')
getAccount(@Param('id') id: string) {
return this.smsService.getAccount(id);
}
@Get('tenants/:id/charge-info')
@RequirePermissions('sms:read')
getChargeInfo(@Param('id') id: string) {
return this.smsService.getChargeInfo(id);
}
@Put('tenants/:id/charge-info')
@RequirePermissions('sms:write')
updateChargeInfo(
@Param('id') id: string,
@Body() dto: UpdateSmsChargeInfoDto,
@@ -54,6 +61,7 @@ export class SmsController {
}
@Get('tenants/:id/report')
@RequirePermissions('sms:read')
report(
@Param('id') id: string,
@Query('fromDate') fromDate?: string,
@@ -63,6 +71,7 @@ export class SmsController {
}
@Get('tenants/:id/report/charges')
@RequirePermissions('sms:read')
chargeReport(
@Param('id') id: string,
@Query('fromDate') fromDate?: string,
@@ -72,16 +81,19 @@ export class SmsController {
}
@Post('tenants/:id/logs/table')
@RequirePermissions('sms:read')
logsTable(@Param('id') id: string, @Body() dto: SmsTableQueryDto) {
return this.smsService.getLogsTable(id, dto);
}
@Post('tenants/:id/ledger/table')
@RequirePermissions('sms:read')
ledgerTable(@Param('id') id: string, @Body() dto: SmsTableQueryDto) {
return this.smsService.getLedgerTable(id, dto);
}
@Patch('tenants/:id')
@RequirePermissions('sms:write')
updateAccount(
@Param('id') id: string,
@Body() dto: UpdateSmsAccountDto,
@@ -91,6 +103,7 @@ export class SmsController {
}
@Post('tenants/:id/charge')
@RequirePermissions('sms:write')
charge(
@Param('id') id: string,
@Body() dto: ChargeSmsWalletDto,
@@ -100,11 +113,13 @@ export class SmsController {
}
@Post('tenants/:id/block')
@RequirePermissions('sms:write')
block(@Param('id') id: string, @CurrentUser() user: { id: string }) {
return this.smsService.setBlocked(id, true, user.id);
}
@Post('tenants/:id/unblock')
@RequirePermissions('sms:write')
unblock(@Param('id') id: string, @CurrentUser() user: { id: string }) {
return this.smsService.setBlocked(id, false, user.id);
}