273 lines
6.2 KiB
TypeScript
273 lines
6.2 KiB
TypeScript
import {
|
||
Controller,
|
||
Get,
|
||
Post,
|
||
Put,
|
||
Body,
|
||
Param,
|
||
Query,
|
||
Headers,
|
||
HttpCode,
|
||
HttpStatus,
|
||
UnauthorizedException,
|
||
ForbiddenException,
|
||
} from '@nestjs/common';
|
||
import { AdminService } from '../../application/services/admin.service';
|
||
import { AdminRole } from '../../domain/value-objects/admin-role.enum';
|
||
import {
|
||
LoginDto,
|
||
CreateAdminDto,
|
||
UpdateAdminDto,
|
||
ChangePasswordDto,
|
||
ResetPasswordDto,
|
||
LoginResult,
|
||
} from '../../application/dtos/admin.dto';
|
||
|
||
@Controller('admin')
|
||
export class AdminController {
|
||
constructor(private adminService: AdminService) {}
|
||
|
||
/**
|
||
* 管理员登录
|
||
*/
|
||
@Post('login')
|
||
@HttpCode(HttpStatus.OK)
|
||
async login(@Body() dto: LoginDto): Promise<{ success: boolean; data: LoginResult }> {
|
||
try {
|
||
const result = await this.adminService.login(dto.username, dto.password);
|
||
return {
|
||
success: true,
|
||
data: result,
|
||
};
|
||
} catch (error) {
|
||
throw new UnauthorizedException((error as Error).message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 验证Token
|
||
*/
|
||
@Get('verify')
|
||
async verifyToken(@Headers('authorization') auth: string) {
|
||
const token = auth?.replace('Bearer ', '');
|
||
if (!token) {
|
||
throw new UnauthorizedException('Missing token');
|
||
}
|
||
|
||
const result = await this.adminService.verifyToken(token);
|
||
if (!result.valid) {
|
||
throw new UnauthorizedException('Invalid token');
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
data: result.admin,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 获取当前管理员信息
|
||
*/
|
||
@Get('me')
|
||
async getCurrentAdmin(@Headers('authorization') auth: string) {
|
||
const token = auth?.replace('Bearer ', '');
|
||
const result = await this.adminService.verifyToken(token);
|
||
|
||
if (!result.valid) {
|
||
throw new UnauthorizedException('Invalid token');
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
data: result.admin,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 创建管理员(需要ADMIN权限)
|
||
*/
|
||
@Post('admins')
|
||
@HttpCode(HttpStatus.CREATED)
|
||
async createAdmin(
|
||
@Headers('authorization') auth: string,
|
||
@Body() dto: CreateAdminDto,
|
||
) {
|
||
await this.checkPermission(auth, 'admin:create');
|
||
|
||
try {
|
||
const admin = await this.adminService.createAdmin(dto);
|
||
return {
|
||
success: true,
|
||
data: {
|
||
id: admin.id,
|
||
username: admin.username,
|
||
name: admin.name,
|
||
role: admin.role,
|
||
},
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
error: (error as Error).message,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取管理员列表
|
||
*/
|
||
@Get('admins')
|
||
async listAdmins(
|
||
@Headers('authorization') auth: string,
|
||
@Query('role') role?: AdminRole,
|
||
@Query('isActive') isActive?: string,
|
||
@Query('page') page?: string,
|
||
@Query('pageSize') pageSize?: string,
|
||
) {
|
||
await this.checkPermission(auth, 'admin:read');
|
||
|
||
const result = await this.adminService.listAdmins({
|
||
role,
|
||
isActive: isActive === undefined ? undefined : isActive === 'true',
|
||
page: page ? parseInt(page) : 1,
|
||
pageSize: pageSize ? parseInt(pageSize) : 20,
|
||
});
|
||
|
||
return {
|
||
success: true,
|
||
data: {
|
||
items: result.items.map(a => ({
|
||
id: a.id,
|
||
username: a.username,
|
||
name: a.name,
|
||
email: a.email,
|
||
phone: a.phone,
|
||
role: a.role,
|
||
isActive: a.isActive,
|
||
lastLoginAt: a.lastLoginAt,
|
||
createdAt: a.createdAt,
|
||
})),
|
||
total: result.total,
|
||
},
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 更新管理员
|
||
*/
|
||
@Put('admins/:id')
|
||
async updateAdmin(
|
||
@Headers('authorization') auth: string,
|
||
@Param('id') id: string,
|
||
@Body() dto: UpdateAdminDto,
|
||
) {
|
||
await this.checkPermission(auth, 'admin:update');
|
||
|
||
try {
|
||
const admin = await this.adminService.updateAdmin(id, dto);
|
||
return {
|
||
success: true,
|
||
data: {
|
||
id: admin.id,
|
||
username: admin.username,
|
||
name: admin.name,
|
||
role: admin.role,
|
||
isActive: admin.isActive,
|
||
},
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
error: (error as Error).message,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 修改密码(当前用户)
|
||
*/
|
||
@Post('change-password')
|
||
async changePassword(
|
||
@Headers('authorization') auth: string,
|
||
@Body() dto: ChangePasswordDto,
|
||
) {
|
||
const token = auth?.replace('Bearer ', '');
|
||
const result = await this.adminService.verifyToken(token);
|
||
|
||
if (!result.valid || !result.admin) {
|
||
throw new UnauthorizedException('Invalid token');
|
||
}
|
||
|
||
try {
|
||
await this.adminService.changePassword(
|
||
result.admin.id,
|
||
dto.oldPassword,
|
||
dto.newPassword,
|
||
);
|
||
return {
|
||
success: true,
|
||
message: '密码修改成功',
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
error: (error as Error).message,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 重置密码(超管功能)
|
||
*/
|
||
@Post('admins/:id/reset-password')
|
||
async resetPassword(
|
||
@Headers('authorization') auth: string,
|
||
@Param('id') id: string,
|
||
@Body() dto: ResetPasswordDto,
|
||
) {
|
||
// 只有超管可以重置密码
|
||
const token = auth?.replace('Bearer ', '');
|
||
const result = await this.adminService.verifyToken(token);
|
||
|
||
if (!result.valid || !result.admin) {
|
||
throw new UnauthorizedException('Invalid token');
|
||
}
|
||
|
||
if (result.admin.role !== AdminRole.SUPER_ADMIN) {
|
||
throw new ForbiddenException('Only super admin can reset passwords');
|
||
}
|
||
|
||
try {
|
||
await this.adminService.resetPassword(id, dto.newPassword);
|
||
return {
|
||
success: true,
|
||
message: '密码重置成功',
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
error: (error as Error).message,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查权限
|
||
*/
|
||
private async checkPermission(auth: string, permission: string): Promise<void> {
|
||
const token = auth?.replace('Bearer ', '');
|
||
if (!token) {
|
||
throw new UnauthorizedException('Missing token');
|
||
}
|
||
|
||
const result = await this.adminService.verifyToken(token);
|
||
if (!result.valid || !result.admin) {
|
||
throw new UnauthorizedException('Invalid token');
|
||
}
|
||
|
||
if (!this.adminService.hasPermission(result.admin.permissions, permission)) {
|
||
throw new ForbiddenException(`Permission denied: ${permission}`);
|
||
}
|
||
}
|
||
}
|