Spaces:
Sleeping
Sleeping
| import { | |
| Controller, | |
| Post, | |
| Get, | |
| Body, | |
| UseGuards, | |
| Req, | |
| HttpCode, | |
| HttpStatus, | |
| } from '@nestjs/common'; | |
| import { | |
| ApiTags, | |
| ApiOperation, | |
| ApiResponse, | |
| ApiBearerAuth, | |
| ApiBody, | |
| } from '@nestjs/swagger'; | |
| import { AuthService } from './auth.service'; | |
| import { RegisterRequestDto } from './dto/register-request.dto'; | |
| import { LoginRequestDto } from './dto/login-request.dto'; | |
| import { | |
| ForgotPasswordRequestDto, | |
| ResetPasswordRequestDto, | |
| TokenRefreshRequestDto, | |
| } from './dto/other-dtos'; | |
| import { Public } from '../../common/decorators/public.decorator'; | |
| import { CurrentUser } from '../../common/decorators/current-user.decorator'; | |
| import { JwtAuthGuard } from './guards/jwt-auth.guard'; | |
| import { User } from './entities/user.entity'; | |
| ('🔐 Authentication') | |
| ('api/auth') | |
| export class AuthController { | |
| constructor(private readonly authService: AuthService) {} | |
| () | |
| ('register') | |
| (HttpStatus.CREATED) | |
| ({ | |
| summary: 'Register a new user', | |
| description: ` | |
| ## Register New User Account | |
| Creates a new user account in the EduVerse system. | |
| ### Access Control | |
| - **Authentication Required**: No (Public endpoint) | |
| - **Roles Required**: None | |
| ### Process Flow | |
| 1. Validates email format and password strength | |
| 2. Checks for existing user with same email | |
| 3. Creates user with default STUDENT role (unless specified) | |
| 4. Returns user data | |
| ### Password Requirements | |
| - Minimum 8 characters | |
| - At least one uppercase letter | |
| - At least one lowercase letter | |
| - At least one number | |
| - At least one special character (@$!%*?&) | |
| ### Notes | |
| - Default role is STUDENT if not specified | |
| `, | |
| }) | |
| ({ type: RegisterRequestDto }) | |
| ({ | |
| status: 201, | |
| description: 'User successfully registered.', | |
| schema: { | |
| example: { | |
| user: { | |
| userId: 1, | |
| email: 'user@example.com', | |
| firstName: 'John', | |
| lastName: 'Doe', | |
| isEmailVerified: true, | |
| roles: [{ roleName: 'student' }], | |
| }, | |
| accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', | |
| refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', | |
| }, | |
| }, | |
| }) | |
| ({ status: 400, description: 'Invalid input data or password requirements not met' }) | |
| ({ status: 409, description: 'User with this email already exists' }) | |
| async register(() registerDto: RegisterRequestDto, () request: any) { | |
| return this.authService.register(registerDto, request); | |
| } | |
| () | |
| ('login') | |
| (HttpStatus.OK) | |
| ({ | |
| summary: 'User login', | |
| description: ` | |
| ## User Authentication | |
| Authenticates a user and returns JWT tokens for API access. | |
| ### Access Control | |
| - **Authentication Required**: No (Public endpoint) | |
| - **Roles Required**: None | |
| ### Process Flow | |
| 1. Validates email and password credentials | |
| 2. Checks if user account is active | |
| 3. Creates a new session for the user | |
| 4. Returns access token (short-lived) and refresh token (long-lived) | |
| ### Token Usage | |
| - **Access Token**: Include in Authorization header as \`Bearer <token>\` | |
| - **Refresh Token**: Use with \`/api/auth/refresh-token\` to get new access token | |
| - Access token expires in 15 minutes (default) | |
| - Refresh token expires in 7 days (or 30 days with rememberMe) | |
| ### Remember Me Option | |
| When \`rememberMe: true\`, the refresh token will have extended validity. | |
| `, | |
| }) | |
| ({ type: LoginRequestDto }) | |
| ({ | |
| status: 200, | |
| description: 'Login successful. Returns JWT tokens.', | |
| schema: { | |
| example: { | |
| user: { | |
| userId: 1, | |
| email: 'user@example.com', | |
| firstName: 'John', | |
| lastName: 'Doe', | |
| roles: [{ roleName: 'student' }], | |
| }, | |
| accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', | |
| refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', | |
| expiresIn: 900, | |
| }, | |
| }, | |
| }) | |
| ({ status: 400, description: 'Invalid credentials' }) | |
| ({ status: 401, description: 'Account disabled' }) | |
| async login(() loginDto: LoginRequestDto, () request: any) { | |
| return this.authService.login(loginDto, request); | |
| } | |
| ('logout') | |
| (HttpStatus.OK) | |
| (JwtAuthGuard) | |
| ('JWT-auth') | |
| ({ | |
| summary: 'User logout', | |
| description: ` | |
| ## Logout Current Session | |
| Invalidates the current user session and refresh token. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles Required**: Any authenticated user | |
| ### Process Flow | |
| 1. Validates the JWT access token | |
| 2. Invalidates the provided refresh token | |
| 3. Ends the current session | |
| ### Notes | |
| - The access token will remain valid until expiration | |
| - Client should discard both tokens after logout | |
| - For immediate token invalidation, implement token blacklisting | |
| `, | |
| }) | |
| ({ | |
| schema: { | |
| type: 'object', | |
| properties: { | |
| refreshToken: { | |
| type: 'string', | |
| description: 'The refresh token to invalidate', | |
| example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', | |
| }, | |
| }, | |
| required: ['refreshToken'], | |
| }, | |
| }) | |
| ({ status: 200, description: 'Successfully logged out' }) | |
| ({ status: 401, description: 'Unauthorized - Invalid or expired token' }) | |
| async logout( | |
| () user: User, | |
| ('refreshToken') refreshToken: string, | |
| ) { | |
| await this.authService.logout(user.userId, refreshToken); | |
| return { message: 'Logged out successfully' }; | |
| } | |
| () | |
| ('refresh-token') | |
| (HttpStatus.OK) | |
| ({ | |
| summary: 'Refresh access token', | |
| description: ` | |
| ## Refresh JWT Access Token | |
| Generates a new access token using a valid refresh token. | |
| ### Access Control | |
| - **Authentication Required**: No (Uses refresh token instead) | |
| - **Roles Required**: None | |
| ### Process Flow | |
| 1. Validates the refresh token | |
| 2. Checks if the session is still valid | |
| 3. Generates a new access token | |
| 4. Optionally rotates the refresh token | |
| ### Usage | |
| Call this endpoint when the access token expires (typically after 15 minutes). | |
| The refresh token has a longer validity period (7-30 days). | |
| ### Security Notes | |
| - Refresh tokens should be stored securely (httpOnly cookies recommended) | |
| - Each refresh token can only be used once (token rotation) | |
| `, | |
| }) | |
| ({ type: TokenRefreshRequestDto }) | |
| ({ | |
| status: 200, | |
| description: 'New access token generated', | |
| schema: { | |
| example: { | |
| accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', | |
| refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', | |
| expiresIn: 900, | |
| }, | |
| }, | |
| }) | |
| ({ status: 401, description: 'Invalid or expired refresh token' }) | |
| async refreshToken( | |
| () tokenRefreshDto: TokenRefreshRequestDto, | |
| () request: any, | |
| ) { | |
| return this.authService.refreshToken(tokenRefreshDto.refreshToken, request); | |
| } | |
| () | |
| ('forgot-password') | |
| (HttpStatus.OK) | |
| ({ | |
| summary: 'Request password reset', | |
| description: ` | |
| ## Request Password Reset Email | |
| Sends a password reset link to the user's email address. | |
| ### Access Control | |
| - **Authentication Required**: No (Public endpoint) | |
| - **Roles Required**: None | |
| ### Process Flow | |
| 1. Validates the email format | |
| 2. Checks if user exists (silently fails if not for security) | |
| 3. Generates a secure password reset token | |
| 4. Sends reset link via email | |
| ### Security Notes | |
| - Always returns success message regardless of email existence | |
| - Reset token expires after 1 hour | |
| - Previous reset tokens are invalidated | |
| `, | |
| }) | |
| ({ type: ForgotPasswordRequestDto }) | |
| ({ | |
| status: 200, | |
| description: 'Password reset email sent (if user exists)', | |
| schema: { | |
| example: { | |
| message: 'If the email exists, a password reset link has been sent', | |
| }, | |
| }, | |
| }) | |
| ({ status: 400, description: 'Invalid email format' }) | |
| async forgotPassword(() forgotPasswordDto: ForgotPasswordRequestDto) { | |
| await this.authService.forgotPassword(forgotPasswordDto.email); | |
| return { | |
| message: 'If the email exists, a password reset link has been sent', | |
| }; | |
| } | |
| () | |
| ('reset-password') | |
| (HttpStatus.OK) | |
| ({ | |
| summary: 'Reset password with token', | |
| description: ` | |
| ## Reset User Password | |
| Resets the user's password using a valid reset token from email. | |
| ### Access Control | |
| - **Authentication Required**: No (Uses reset token) | |
| - **Roles Required**: None | |
| ### Process Flow | |
| 1. Validates the reset token | |
| 2. Verifies token hasn't expired | |
| 3. Validates new password meets requirements | |
| 4. Updates user password (hashed) | |
| 5. Invalidates all existing sessions | |
| ### Password Requirements | |
| - Minimum 8 characters | |
| - At least one uppercase letter | |
| - At least one lowercase letter | |
| - At least one number | |
| - At least one special character (@$!%*?&) | |
| `, | |
| }) | |
| ({ type: ResetPasswordRequestDto }) | |
| ({ | |
| status: 200, | |
| description: 'Password reset successful', | |
| schema: { | |
| example: { message: 'Password reset successfully' }, | |
| }, | |
| }) | |
| ({ status: 400, description: 'Invalid or expired reset token' }) | |
| async resetPassword(() resetPasswordDto: ResetPasswordRequestDto) { | |
| await this.authService.resetPassword( | |
| resetPasswordDto.token, | |
| resetPasswordDto.newPassword, | |
| ); | |
| return { message: 'Password reset successfully' }; | |
| } | |
| ('me') | |
| (JwtAuthGuard) | |
| ('JWT-auth') | |
| ({ | |
| summary: 'Get current user profile', | |
| description: ` | |
| ## Get Authenticated User Profile | |
| Returns the complete profile of the currently authenticated user. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles Required**: Any authenticated user (STUDENT, INSTRUCTOR, TA, ADMIN, IT_ADMIN) | |
| ### Response Includes | |
| - User basic information (name, email, phone) | |
| - Assigned roles and permissions | |
| - Account status and verification state | |
| - Campus association (if applicable) | |
| ### Usage | |
| Use this endpoint to: | |
| - Display user profile information | |
| - Check user permissions | |
| - Verify authentication status | |
| `, | |
| }) | |
| ({ | |
| status: 200, | |
| description: 'Current user profile', | |
| schema: { | |
| example: { | |
| userId: 1, | |
| email: 'user@example.com', | |
| firstName: 'John', | |
| lastName: 'Doe', | |
| phone: '+1234567890', | |
| isEmailVerified: true, | |
| status: 'active', | |
| roles: [ | |
| { roleId: 1, roleName: 'student', roleDescription: 'Regular student user' }, | |
| ], | |
| createdAt: '2024-01-15T10:30:00Z', | |
| }, | |
| }, | |
| }) | |
| ({ status: 401, description: 'Unauthorized - Invalid or expired token' }) | |
| async getCurrentUser(() user: User) { | |
| return this.authService.getCurrentUser(user.userId); | |
| } | |
| } | |