- Added `xmlchars` dependency to `pnpm-lock.yaml` for improved XML character handling. - Updated IAM Service audit plan to streamline post-deployment monitoring tasks. - Enhanced Dockerfile to prune development dependencies after build for a leaner production image. - Introduced a new encryption key configuration in the environment example for better security practices. - Refactored multiple service files to improve import organization and maintainability. - Improved error handling in seed scripts to provide more detailed logging on failures. - Updated various controllers and services to ensure consistent import statements and enhance readability. These changes aim to improve the overall functionality, security, and maintainability of the IAM Service.
194 lines
4.6 KiB
TypeScript
194 lines
4.6 KiB
TypeScript
import { Request, Response } from 'express';
|
|
import { z } from 'zod';
|
|
|
|
// import { cookieService } from '../token/cookie.service';
|
|
|
|
import { RegisterDto, LoginDto } from './auth.dto';
|
|
import { authService } from './auth.service';
|
|
|
|
|
|
/**
|
|
* EN: Auth Controller
|
|
* VI: Controller xác thực
|
|
*/
|
|
export class AuthController {
|
|
/**
|
|
* EN: Register endpoint
|
|
* VI: Endpoint đăng ký
|
|
*/
|
|
async register(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const data = RegisterDto.parse(req.body);
|
|
const result = await authService.register(data, req);
|
|
|
|
// Set cookies
|
|
// cookieService.setAuthCookies(res, result.tokens);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
data: {
|
|
user: {
|
|
id: result.user.id,
|
|
email: result.user.email,
|
|
username: result.user.username,
|
|
},
|
|
tokens: result.tokens,
|
|
},
|
|
});
|
|
} catch (error: any) {
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid input',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'REGISTRATION_FAILED',
|
|
message: error.message || 'Registration failed',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Login endpoint
|
|
* VI: Endpoint đăng nhập
|
|
*/
|
|
async login(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const data = LoginDto.parse(req.body);
|
|
const result = await authService.login(data, req);
|
|
|
|
if (result.user.mfaRequired) {
|
|
res.status(200).json({
|
|
success: true,
|
|
data: {
|
|
mfaRequired: true,
|
|
userId: result.user.id,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Set cookies
|
|
// cookieService.setAuthCookies(res, result.tokens);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: {
|
|
user: {
|
|
id: result.user.id,
|
|
email: result.user.email,
|
|
username: result.user.username,
|
|
},
|
|
tokens: result.tokens,
|
|
},
|
|
});
|
|
} catch (error: any) {
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid input',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(401).json({
|
|
success: false,
|
|
error: {
|
|
code: 'LOGIN_FAILED',
|
|
message: error.message || 'Login failed',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Logout endpoint
|
|
* VI: Endpoint đăng xuất
|
|
*/
|
|
async logout(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const userId = (req as any).user?.id || (req as any).user?.sub;
|
|
if (!userId) {
|
|
res.status(401).json({
|
|
success: false,
|
|
error: { code: 'UNAUTHORIZED', message: 'Not authenticated' },
|
|
});
|
|
return;
|
|
}
|
|
|
|
await authService.logout(userId, undefined, req);
|
|
// cookieService.clearAuthCookies(res);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: { message: 'Logged out successfully' },
|
|
});
|
|
} catch (error: any) {
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'LOGOUT_FAILED',
|
|
message: error.message || 'Logout failed',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Refresh token endpoint
|
|
* VI: Endpoint làm mới token
|
|
*/
|
|
async refreshToken(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const refreshToken = req.body.refreshToken; // cookieService.getTokenFromCookie(req, 'refresh') || req.body.refreshToken;
|
|
|
|
if (!refreshToken) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: { code: 'REFRESH_TOKEN_REQUIRED', message: 'Refresh token required' },
|
|
});
|
|
return;
|
|
}
|
|
|
|
const result = await authService.refreshToken(refreshToken, req);
|
|
|
|
// Update cookies if new refresh token provided
|
|
if (result.refreshToken) {
|
|
// cookieService.setAuthCookies(res, {
|
|
// accessToken: result.accessToken,
|
|
// refreshToken: result.refreshToken,
|
|
// });
|
|
}
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: result,
|
|
});
|
|
} catch (error: any) {
|
|
res.status(401).json({
|
|
success: false,
|
|
error: {
|
|
code: 'REFRESH_FAILED',
|
|
message: error.message || 'Token refresh failed',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
export const authController = new AuthController();
|