import { Body, Post, Route, Tags, SuccessResponse, Response, Example, Controller } from 'tsoa'; import { AuthService } from '../services/auth.service'; import { LoginRequest, RegisterRequest, RefreshTokenRequest, LoginResponse, RegisterResponse, RefreshTokenResponse } from '../types/auth.types'; import { loginSchema, registerSchema, refreshTokenSchema } from '../validators/auth.validator'; import { ValidationError } from '../middleware/errorHandler'; @Route('api/auth') @Tags('Authentication') export class AuthController { private authService = new AuthService(); /** * User login * @summary Login with email and password * @param body Login credentials * @returns JWT token and user information */ @Post('login') @SuccessResponse('200', 'Login successful') @Response('401', 'Invalid credentials') @Example({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', user: { id: 1, username: 'admin', email: 'admin@elearning.local', role: { code: 'ADMIN', name: { th: 'ผู้ดูแลระบบ', en: 'Administrator' } }, profile: { prefix: { th: 'นาย', en: 'Mr.' }, first_name: 'Admin', last_name: 'User', avatar_url: undefined } } }) public async login(@Body() body: LoginRequest): Promise { // Validate input const { error, value } = loginSchema.validate(body); if (error) { throw new ValidationError(error.details[0].message); } return await this.authService.login(body); } /** * User registration * @summary Register a new student account * @param body Registration data * @returns Created user information */ @Post('register') @SuccessResponse('201', 'Registration successful') @Response('400', 'Validation error') @Response('409', 'Username or email already exists') @Example({ user: { id: 4, username: 'newstudent', email: 'student@example.com', role: { code: 'STUDENT', name: { th: 'นักเรียน', en: 'Student' } }, profile: { prefix: { th: 'นาย', en: 'Mr.' }, first_name: 'John', last_name: 'Doe' } }, message: 'Registration successful' }) public async register(@Body() body: RegisterRequest): Promise { // Validate input const { error } = registerSchema.validate(body); if (error) { throw new ValidationError(error.details[0].message); } return await this.authService.register(body); } /** * Refresh access token * @summary Get a new access token using refresh token * @param body Refresh token * @returns New access token and refresh token */ @Post('refresh') @SuccessResponse('200', 'Token refreshed') @Response('401', 'Invalid or expired refresh token') @Example({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' }) public async refreshToken(@Body() body: RefreshTokenRequest): Promise { // Validate input const { error } = refreshTokenSchema.validate(body); if (error) { throw new ValidationError(error.details[0].message); } return await this.authService.refreshToken(body.refreshToken); } }