import { Body, Post, Route, Tags, SuccessResponse, Response, Example, Controller, Security, Request } from 'tsoa'; import { AuthService } from '../services/auth.service'; import { LoginRequest, RegisterRequest, RefreshTokenRequest, ResetRequest, ResetPasswordRequest, LoginResponse, RegisterResponse, RefreshTokenResponse } from '../types/auth.types'; import { loginSchema, registerSchema, refreshTokenSchema, resetRequestSchema, resetPasswordSchema } 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', updated_at: new Date('2024-01-01T00:00:00Z'), created_at: new Date('2024-01-01T00:00:00Z'), role: { code: 'ADMIN', name: { th: 'ผู้ดูแลระบบ', en: 'Administrator' } }, profile: { prefix: { th: 'นาย', en: 'Mr.' }, first_name: 'Admin', last_name: 'User', phone: null, avatar_url: null, birth_date: null } } }) 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', updated_at: new Date('2024-01-01T00:00:00Z'), created_at: new Date('2024-01-01T00:00:00Z'), role: { code: 'STUDENT', name: { th: 'นักเรียน', en: 'Student' } }, profile: { prefix: { th: 'นาย', en: 'Mr.' }, first_name: 'John', last_name: 'Doe', phone: null, avatar_url: null, birth_date: null } }, 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); } /** * Reset password request * @summary Request a password reset * @param body Email address * @returns Success message */ @Post('reset-request') @SuccessResponse('200', 'Reset request successful') @Response('401', 'Invalid or expired refresh token') public async resetRequest(@Body() body: ResetRequest): Promise<{ message: string }> { const { error } = resetRequestSchema.validate(body); if (error) { throw new ValidationError(error.details[0].message); } return await this.authService.resetRequest(body.email); } /** * Reset password * @summary Reset password using reset token * @param body Reset token and new password * @returns Success message */ @Post('reset-password') @SuccessResponse('200', 'Password reset successful') @Response('401', 'Invalid or expired reset token') public async resetPassword(@Body() body: ResetPasswordRequest): Promise<{ message: string }> { const { error } = resetPasswordSchema.validate(body); if (error) { throw new ValidationError(error.details[0].message); } return await this.authService.resetPassword(body.token, body.password); } }