first commit
This commit is contained in:
111
apps/api-gateway/src/controllers/security.controller.ts
Normal file
111
apps/api-gateway/src/controllers/security.controller.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { CoreGrpcService } from '../core-grpc.service';
|
||||
import { OptionalPinDto, PinDto, VerifySecurityPinDto } from '../dto/security.dto';
|
||||
|
||||
@ApiTags('Безопасность')
|
||||
@ApiBearerAuth()
|
||||
@Controller('security')
|
||||
export class SecurityController {
|
||||
constructor(private readonly core: CoreGrpcService) {}
|
||||
|
||||
@Get('users/:userId/devices')
|
||||
@ApiOperation({ summary: 'Активные устройства', description: 'Показывает устройства пользователя и связанные активные сессии.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiResponse({ status: 200, description: 'Список устройств получен' })
|
||||
listDevices(@Param('userId') userId: string) {
|
||||
return this.core.security.ListActiveDevices({ userId });
|
||||
}
|
||||
|
||||
@Get('users/:userId/sessions')
|
||||
@ApiOperation({ summary: 'Активные сессии', description: 'Возвращает ACTIVE и LOCKED сессии пользователя для управления устройствами.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiResponse({ status: 200, description: 'Список активных сессий получен' })
|
||||
listSessions(@Param('userId') userId: string) {
|
||||
return this.core.security.ListActiveSessions({ userId });
|
||||
}
|
||||
|
||||
@Get('users/:userId/sign-in-history')
|
||||
@ApiOperation({ summary: 'История входов', description: 'Показывает последние попытки входа и причины отказов.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiResponse({ status: 200, description: 'История входов получена' })
|
||||
listHistory(@Param('userId') userId: string) {
|
||||
return this.core.security.ListSignInHistory({ userId });
|
||||
}
|
||||
|
||||
@Post('users/:userId/pin/setup')
|
||||
@ApiOperation({ summary: 'Настроить PIN-код', description: 'Создает или включает PIN-код пользователя. PIN хранится только в виде bcrypt hash.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiBody({ type: PinDto })
|
||||
@ApiResponse({ status: 201, description: 'PIN-код настроен' })
|
||||
setupPin(@Param('userId') userId: string, @Body() dto: PinDto) {
|
||||
return this.core.security.SetupPin({ userId, pin: dto.pin });
|
||||
}
|
||||
|
||||
@Post('users/:userId/pin/update')
|
||||
@ApiOperation({ summary: 'Обновить PIN-код', description: 'Меняет PIN-код и переводит активные сессии пользователя в LOCKED до повторной проверки.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiBody({ type: PinDto })
|
||||
@ApiResponse({ status: 201, description: 'PIN-код обновлен' })
|
||||
updatePin(@Param('userId') userId: string, @Body() dto: PinDto) {
|
||||
return this.core.security.UpdatePin({ userId, pin: dto.pin });
|
||||
}
|
||||
|
||||
@Post('users/:userId/pin/delete-request')
|
||||
@ApiOperation({ summary: 'Запросить удаление PIN-кода', description: 'Запускает период ожидания перед отключением PIN-кода согласно SystemSetting.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiBody({ type: OptionalPinDto })
|
||||
requestPinDeletion(@Param('userId') userId: string, @Body() dto: OptionalPinDto) {
|
||||
return this.core.security.RequestPinDeletion({ userId, pin: dto.pin ?? '' });
|
||||
}
|
||||
|
||||
@Post('users/:userId/pin/delete-cancel')
|
||||
@ApiOperation({ summary: 'Отменить удаление PIN-кода', description: 'Отменяет запланированное удаление PIN-кода.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
cancelPinDeletion(@Param('userId') userId: string) {
|
||||
return this.core.security.CancelPinDeletion({ userId });
|
||||
}
|
||||
|
||||
@Post('pin/verify')
|
||||
@ApiOperation({ summary: 'Проверить PIN-код', description: 'Проверяет PIN-код и возвращает access token с pinVerified=true для указанной сессии.' })
|
||||
@ApiBody({ type: VerifySecurityPinDto })
|
||||
@ApiResponse({ status: 201, description: 'PIN-код проверен' })
|
||||
verifyPin(@Body() dto: VerifySecurityPinDto) {
|
||||
return this.core.security.VerifyPinCode(dto);
|
||||
}
|
||||
|
||||
@Post('users/:userId/sessions/:sessionId/lock')
|
||||
@ApiOperation({ summary: 'Заблокировать сессию', description: 'Переводит активную сессию в LOCKED и сбрасывает pinVerified=false.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiParam({ name: 'sessionId', description: 'ID сессии' })
|
||||
@ApiResponse({ status: 201, description: 'Сессия заблокирована' })
|
||||
lockSession(@Param('userId') userId: string, @Param('sessionId') sessionId: string) {
|
||||
return this.core.security.LockSession({ userId, sessionId });
|
||||
}
|
||||
|
||||
@Post('users/:userId/sessions/:sessionId/revoke')
|
||||
@ApiOperation({ summary: 'Выйти с устройства', description: 'Отзывает конкретную сессию пользователя и завершает доступ с выбранного устройства.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiParam({ name: 'sessionId', description: 'ID сессии' })
|
||||
@ApiResponse({ status: 201, description: 'Сессия отозвана' })
|
||||
revokeSession(@Param('userId') userId: string, @Param('sessionId') sessionId: string) {
|
||||
return this.core.security.RevokeSession({ userId, sessionId });
|
||||
}
|
||||
|
||||
@Post('users/:userId/devices/:deviceId/revoke')
|
||||
@ApiOperation({ summary: 'Завершить сессии устройства', description: 'Отзывает все активные сессии выбранного устройства пользователя.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiParam({ name: 'deviceId', description: 'ID устройства' })
|
||||
@ApiResponse({ status: 201, description: 'Сессии устройства завершены' })
|
||||
revokeDevice(@Param('userId') userId: string, @Param('deviceId') deviceId: string) {
|
||||
return this.core.security.RevokeDevice({ userId, deviceId });
|
||||
}
|
||||
|
||||
@Post('users/:userId/revoke-all-sessions')
|
||||
@ApiOperation({ summary: 'Выйти везде', description: 'Отзывает все активные и PIN-заблокированные сессии пользователя.' })
|
||||
@ApiParam({ name: 'userId', description: 'ID пользователя' })
|
||||
@ApiResponse({ status: 201, description: 'Все сессии отозваны' })
|
||||
revokeAll(@Param('userId') userId: string) {
|
||||
return this.core.security.RevokeAllSessions({ userId });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user