/
goncharovchik
/
secure-api-d
Обзор
Документация
Войти
/
goncharovchik
/
secure-api-d
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/modules/bots/bots.controller.ts
94 строки
3 KB
Aleksey Goncharov
feat: secure API with 26 OWASP security measures
29 апр 2026, 13:30
29 апр 2026, 13:30
449fe34
Код
Авторство
О чём код?
import { Controller, Get, Post, Patch, Delete, Body, Param, Query, UseGuards } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiQuery } from '@nestjs/swagger'; import { BotsService } from './bots.service'; import { CreateBotDto } from './dto/create-bot.dto'; import { UpdateBotDto } from './dto/update-bot.dto'; import { CurrentUser } from '../../common/decorators/current-user.decorator'; import { OwnershipGuard } from '../../common/guards/ownership.guard'; /** * Контроллер ботов. * SECURE: * - Мера #1: JWT Auth (глобальный guard) * - Мера #7: IDOR/BOLA — OwnershipGuard * - Мера #9: Input Validation (DTO) * - Мера #11: SQL Injection — TypeORM */ @ApiTags('Bots') @ApiBearerAuth() @Controller('api/bots') export class BotsController { constructor(private readonly botsService: BotsService) {} @Post() @ApiOperation({ summary: 'Создать бота' }) create(@Body() dto: CreateBotDto, @CurrentUser('id') userId: number) { return this.botsService.create(dto, userId); } /** SECURE: только боты текущего пользователя */ @Get() @ApiOperation({ summary: 'Мои боты (с пагинацией)' }) @ApiQuery({ name: 'page', required: false }) @ApiQuery({ name: 'limit', required: false }) findAll( @CurrentUser('id') userId: number, @Query('page') page?: number, @Query('limit') limit?: number, ) { const skip = ((page || 1) - 1) * (limit || 20); return this.botsService.findAllByUser(userId, skip, limit || 20); } /** SECURE: TypeORM parameterized queries */ @Get('search') @ApiOperation({ summary: 'Поиск ботов (SECURE — без SQL Injection)' }) @ApiQuery({ name: 'name', required: true }) @ApiQuery({ name: 'page', required: false }) @ApiQuery({ name: 'limit', required: false }) search( @Query('name') name: string, @CurrentUser('id') userId: number, @Query('page') page?: number, @Query('limit') limit?: number, ) { const skip = ((page || 1) - 1) * (limit || 20); return this.botsService.search(name, userId, skip, limit || 20); } /** SECURE: OwnershipGuard — только свои боты */ @Get(':id') @UseGuards(OwnershipGuard) @ApiOperation({ summary: 'Получить бота по ID (проверка ownership)' }) findOne(@Param('id') id: string) { return this.botsService.findOne(+id); } @Patch(':id') @UseGuards(OwnershipGuard) @ApiOperation({ summary: 'Обновить бота (проверка ownership)' }) update(@Param('id') id: string, @Body() dto: UpdateBotDto) { return this.botsService.update(+id, dto); } @Delete(':id') @UseGuards(OwnershipGuard) @ApiOperation({ summary: 'Удалить бота (проверка ownership)' }) remove(@Param('id') id: string) { return this.botsService.remove(+id); } @Post(':id/start') @UseGuards(OwnershipGuard) @ApiOperation({ summary: 'Запустить бота' }) start(@Param('id') id: string) { return this.botsService.start(+id); } @Post(':id/stop') @UseGuards(OwnershipGuard) @ApiOperation({ summary: 'Остановить бота' }) stop(@Param('id') id: string) { return this.botsService.stop(+id); } }