313 lines
8.3 KiB
TypeScript
313 lines
8.3 KiB
TypeScript
import { Request, Response } from 'express';
|
|
import { z } from 'zod';
|
|
|
|
import { NotFoundError } from '../../../errors/http-error';
|
|
import { UpdateUserDto, UserFiltersDto, BulkImportUsersDto } from '../identity.dto';
|
|
|
|
import { userManagementService } from './user.service';
|
|
import { getErrorMessage } from '../../../utils/error-utils';
|
|
|
|
/**
|
|
* EN: User Management Controller
|
|
* VI: Controller quản lý người dùng
|
|
*/
|
|
export class UserManagementController {
|
|
/**
|
|
* EN: List users
|
|
* VI: Liệt kê users
|
|
*/
|
|
async list(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const filters = UserFiltersDto.parse({
|
|
organizationId: req.query.organizationId as string,
|
|
isActive: req.query.isActive === 'true' ? true : req.query.isActive === 'false' ? false : undefined,
|
|
emailVerified: req.query.emailVerified === 'true' ? true : req.query.emailVerified === 'false' ? false : undefined,
|
|
search: req.query.search as string,
|
|
skip: parseInt(req.query.skip as string) || 0,
|
|
take: parseInt(req.query.take as string) || 20,
|
|
});
|
|
|
|
const result = await userManagementService.searchUsers(filters);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
users: result.users,
|
|
pagination: {
|
|
total: result.total,
|
|
skip: filters.skip,
|
|
take: filters.take,
|
|
},
|
|
},
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid filters',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'LIST_USERS_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to list users',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Get user by ID
|
|
* VI: Lấy user theo ID
|
|
*/
|
|
async get(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params;
|
|
const user = await userManagementService.getUser(id);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: user,
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof NotFoundError) {
|
|
res.status(404).json(error.toApiResponse());
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'GET_USER_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to get user',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Update user
|
|
* VI: Cập nhật user
|
|
*/
|
|
async update(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params;
|
|
const data = UpdateUserDto.parse(req.body);
|
|
const user = await userManagementService.updateUser(id, data, req);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: user,
|
|
message: 'User updated successfully / User đã được cập nhật thành công',
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid input',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (error instanceof NotFoundError) {
|
|
res.status(404).json(error.toApiResponse());
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'UPDATE_USER_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to update user',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Delete user
|
|
* VI: Xóa user
|
|
*/
|
|
async delete(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params;
|
|
await userManagementService.deleteUser(id, req);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'User deleted successfully / User đã được xóa thành công',
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof NotFoundError) {
|
|
res.status(404).json(error.toApiResponse());
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'DELETE_USER_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to delete user',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Deactivate user
|
|
* VI: Vô hiệu hóa user
|
|
*/
|
|
async deactivate(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params;
|
|
const user = await userManagementService.deactivateUser(id, req);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: user,
|
|
message: 'User deactivated successfully / User đã được vô hiệu hóa thành công',
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof NotFoundError) {
|
|
res.status(404).json(error.toApiResponse());
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'DEACTIVATE_USER_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to deactivate user',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Reactivate user
|
|
* VI: Kích hoạt lại user
|
|
*/
|
|
async reactivate(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params;
|
|
const user = await userManagementService.reactivateUser(id, req);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: user,
|
|
message: 'User reactivated successfully / User đã được kích hoạt lại thành công',
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof NotFoundError) {
|
|
res.status(404).json(error.toApiResponse());
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'REACTIVATE_USER_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to reactivate user',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Bulk import users
|
|
* VI: Import hàng loạt users
|
|
*/
|
|
async bulkImport(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const data = BulkImportUsersDto.parse(req.body);
|
|
const result = await userManagementService.bulkImportUsers(data, req);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
data: result,
|
|
message: `Imported ${result.created} users successfully / Đã import ${result.created} users thành công`,
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid input',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'BULK_IMPORT_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to import users',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EN: Bulk export users
|
|
* VI: Export hàng loạt users
|
|
*/
|
|
async bulkExport(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const filters = UserFiltersDto.parse({
|
|
organizationId: req.query.organizationId as string,
|
|
isActive: req.query.isActive === 'true' ? true : req.query.isActive === 'false' ? false : undefined,
|
|
emailVerified: req.query.emailVerified === 'true' ? true : req.query.emailVerified === 'false' ? false : undefined,
|
|
skip: 0,
|
|
take: 10000, // Large limit for export
|
|
});
|
|
|
|
const users = await userManagementService.bulkExportUsers(filters);
|
|
|
|
res.setHeader('Content-Type', 'application/json');
|
|
res.setHeader('Content-Disposition', `attachment; filename="users-export-${Date.now()}.json"`);
|
|
res.json({
|
|
success: true,
|
|
data: users,
|
|
exportedAt: new Date().toISOString(),
|
|
total: users.length,
|
|
});
|
|
} catch (error: unknown) {
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid filters',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'BULK_EXPORT_FAILED',
|
|
message: getErrorMessage(error) || 'Failed to export users',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
export const userManagementController = new UserManagementController();
|