Add privilege management system with related migrations and guards

- Introduced a new `PrivilegesModule` to manage user privileges and access control.
- Added `RequirePrivilege` decorator to enforce privilege checks on controller handlers.
- Implemented `PrivilegesGuard` to handle authorization based on user privileges.
- Created database migrations for `privileges`, `privilege_keys`, and `privilege_details` tables.
- Updated user model to include `is_superadmin` field for enhanced access control.
- Added unit tests for the new privileges functionality and guards to ensure correct behavior.
This commit is contained in:
shancheas
2026-08-24 11:31:13 +07:00
parent 0550cbe764
commit 07550b3167
51 changed files with 3731 additions and 27 deletions
+34 -3
View File
@@ -16,6 +16,8 @@ import type { AuthUser } from '../../common/auth/auth-user';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { Public } from '../../common/decorators/public.decorator';
import { BEARER_AUTH_NAME } from '../../common/swagger/setup-swagger';
import { PrivilegesService } from '../privileges/privileges.service';
import { UsersService } from '../users/users.service';
import { AuthService } from './auth.service';
import {
LoginDto,
@@ -28,7 +30,11 @@ import {
@ApiTags('auth')
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
constructor(
private readonly authService: AuthService,
private readonly usersService: UsersService,
private readonly privilegesService: PrivilegesService,
) {}
@Public()
@Throttle({ default: { limit: 5, ttl: 60_000 } })
@@ -87,7 +93,32 @@ export class AuthController {
@ApiOperation({ summary: 'Get the current authenticated user' })
@ApiOkResponse({ type: MeResponseDto })
@ApiUnauthorizedResponse({ description: 'Missing or invalid access token' })
me(@CurrentUser() user: AuthUser): MeResponseDto {
return { id: user.id, username: user.username };
async me(@CurrentUser() user: AuthUser): Promise<MeResponseDto> {
const full = await this.usersService.findById(user.id);
const isSuperadmin = full?.isSuperadmin ?? user.isSuperadmin;
if (!full?.privilegeId) {
return {
id: user.id,
username: user.username,
isSuperadmin,
privilege: null,
permissions: {},
};
}
const privilege = await this.privilegesService.findPrivilegeSummary(
full.privilegeId,
);
const permissions = privilege
? await this.privilegesService.getPermissionsMap(privilege.id)
: {};
return {
id: user.id,
username: user.username,
isSuperadmin,
privilege,
permissions,
};
}
}