Set up PostgreSQL database configuration and enhance application structure
- Added .env.example with database connection details and JWT configuration. - Introduced docker-compose.yml for PostgreSQL service setup with health checks. - Created drizzle.config.ts for database schema and migration management. - Updated nest-cli.json to include Swagger plugin configuration for API documentation. - Enhanced package.json with new database-related scripts and dependencies. - Implemented initial database migrations for user and token management. - Configured application bootstrap process to load environment variables and set up Swagger. - Added shared application configuration in configure-app.ts for consistent setup. - Included unit tests for application configuration and Swagger setup.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { Body, Controller, Get, HttpCode, Post } from '@nestjs/common';
|
||||
import {
|
||||
ApiBadRequestResponse,
|
||||
ApiBearerAuth,
|
||||
ApiConflictResponse,
|
||||
ApiCreatedResponse,
|
||||
ApiNoContentResponse,
|
||||
ApiOkResponse,
|
||||
ApiOperation,
|
||||
ApiTags,
|
||||
ApiTooManyRequestsResponse,
|
||||
ApiUnauthorizedResponse,
|
||||
} from '@nestjs/swagger';
|
||||
import { Throttle } from '@nestjs/throttler';
|
||||
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 { AuthService } from './auth.service';
|
||||
import {
|
||||
LoginDto,
|
||||
MeResponseDto,
|
||||
RefreshTokenDto,
|
||||
RegisterDto,
|
||||
TokenPairDto,
|
||||
} from './dto/auth.dto';
|
||||
|
||||
@ApiTags('auth')
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
|
||||
@Public()
|
||||
@Throttle({ default: { limit: 5, ttl: 60_000 } })
|
||||
@Post('register')
|
||||
@ApiOperation({ summary: 'Register a new user' })
|
||||
@ApiCreatedResponse({ type: TokenPairDto })
|
||||
@ApiBadRequestResponse({ description: 'Validation failed' })
|
||||
@ApiConflictResponse({ description: 'Username already registered' })
|
||||
@ApiTooManyRequestsResponse({ description: 'Rate limit exceeded' })
|
||||
register(@Body() dto: RegisterDto): Promise<TokenPairDto> {
|
||||
return this.authService.register(dto.username, dto.password);
|
||||
}
|
||||
|
||||
@Public()
|
||||
@Throttle({ default: { limit: 5, ttl: 60_000 } })
|
||||
@Post('login')
|
||||
@HttpCode(200)
|
||||
@ApiOperation({ summary: 'Log in with username and password' })
|
||||
@ApiOkResponse({ type: TokenPairDto })
|
||||
@ApiBadRequestResponse({ description: 'Validation failed' })
|
||||
@ApiUnauthorizedResponse({ description: 'Invalid credentials' })
|
||||
@ApiTooManyRequestsResponse({ description: 'Rate limit exceeded' })
|
||||
login(@Body() dto: LoginDto): Promise<TokenPairDto> {
|
||||
return this.authService.login(dto.username, dto.password);
|
||||
}
|
||||
|
||||
@Public()
|
||||
@Throttle({ default: { limit: 10, ttl: 60_000 } })
|
||||
@Post('refresh')
|
||||
@HttpCode(200)
|
||||
@ApiOperation({
|
||||
summary: 'Rotate refresh token and issue a new access token',
|
||||
})
|
||||
@ApiOkResponse({ type: TokenPairDto })
|
||||
@ApiBadRequestResponse({ description: 'Validation failed' })
|
||||
@ApiUnauthorizedResponse({ description: 'Invalid refresh token' })
|
||||
@ApiTooManyRequestsResponse({ description: 'Rate limit exceeded' })
|
||||
refresh(@Body() dto: RefreshTokenDto): Promise<TokenPairDto> {
|
||||
return this.authService.refresh(dto.refreshToken);
|
||||
}
|
||||
|
||||
@Public()
|
||||
@Throttle({ default: { limit: 10, ttl: 60_000 } })
|
||||
@Post('revoke')
|
||||
@HttpCode(204)
|
||||
@ApiOperation({ summary: 'Revoke a refresh token session' })
|
||||
@ApiNoContentResponse({ description: 'Session revoked (or already invalid)' })
|
||||
@ApiBadRequestResponse({ description: 'Validation failed' })
|
||||
@ApiTooManyRequestsResponse({ description: 'Rate limit exceeded' })
|
||||
async revoke(@Body() dto: RefreshTokenDto): Promise<void> {
|
||||
await this.authService.revoke(dto.refreshToken);
|
||||
}
|
||||
|
||||
@Get('me')
|
||||
@ApiBearerAuth(BEARER_AUTH_NAME)
|
||||
@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 };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user