forked from wangziqi/gongxue-base
移除删除账号功能
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
|||||||
Tag,
|
Tag,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { PlusOutlined, EditOutlined, DeleteOutlined, KeyOutlined, IdcardOutlined, InboxOutlined } from '@ant-design/icons';
|
import { PlusOutlined, EditOutlined, KeyOutlined, IdcardOutlined, InboxOutlined } from '@ant-design/icons';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import api from '../../api';
|
import api from '../../api';
|
||||||
import PermissionButton from '../../components/PermissionButton';
|
import PermissionButton from '../../components/PermissionButton';
|
||||||
@@ -141,18 +141,6 @@ const UsersPage: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = async (id: number) => {
|
|
||||||
try {
|
|
||||||
await api.delete(`/rbac/users/${id}`);
|
|
||||||
message.success('已删除');
|
|
||||||
fetchData();
|
|
||||||
} catch (e: unknown) {
|
|
||||||
const err = e as { message?: string };
|
|
||||||
message.error(err?.message || '删除失败');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const handleResetPwd = (record: any) => {
|
const handleResetPwd = (record: any) => {
|
||||||
setResetTarget(record);
|
setResetTarget(record);
|
||||||
pwdForm.resetFields();
|
pwdForm.resetFields();
|
||||||
@@ -253,13 +241,6 @@ const UsersPage: React.FC = () => {
|
|||||||
<PermissionButton permission="user:edit" type="link" size="small">归档</PermissionButton>
|
<PermissionButton permission="user:edit" type="link" size="small">归档</PermissionButton>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
)}
|
)}
|
||||||
{record.username !== 'admin' && (
|
|
||||||
<Popconfirm title="确认删除?需先归档" onConfirm={() => handleDelete(record.id)}>
|
|
||||||
<PermissionButton permission="user:delete" type="link" size="small" danger icon={<DeleteOutlined />}>
|
|
||||||
删除
|
|
||||||
</PermissionButton>
|
|
||||||
</Popconfirm>
|
|
||||||
)}
|
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -220,6 +220,6 @@ export const PERMISSION_NODES = [
|
|||||||
'report:generate',
|
'report:generate',
|
||||||
'log:view',
|
'log:view',
|
||||||
'role:view', 'role:add', 'role:update', 'role:delete',
|
'role:view', 'role:add', 'role:update', 'role:delete',
|
||||||
'user:view', 'user:add', 'user:update', 'user:delete',
|
'user:view', 'user:add', 'user:update',
|
||||||
'dashboard:view',
|
'dashboard:view',
|
||||||
] as const;
|
] as const;
|
||||||
|
|||||||
@@ -198,28 +198,6 @@ export class RbacController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete('users/:id')
|
|
||||||
@RequirePermission('user:delete')
|
|
||||||
async deleteUser(@Param('id') id: string, @Request() req: any) {
|
|
||||||
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
||||||
try {
|
|
||||||
const result = await this.rbacService.deleteUser(+id);
|
|
||||||
await this.logService.log({
|
|
||||||
userId: req.user?.id,
|
|
||||||
username: req.user?.username,
|
|
||||||
module: '账号',
|
|
||||||
action: '删除账号',
|
|
||||||
targetId: +id,
|
|
||||||
targetType: 'user',
|
|
||||||
ipAddress,
|
|
||||||
userAgent,
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
} catch (e: any) {
|
|
||||||
throw new BadRequestException(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Put('users/:id/archive')
|
@Put('users/:id/archive')
|
||||||
@RequirePermission('user:edit')
|
@RequirePermission('user:edit')
|
||||||
async archiveUser(@Param('id') id: string) {
|
async archiveUser(@Param('id') id: string) {
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ const PRESET_PERMISSIONS: Array<{ code: string; name: string; group: string }> =
|
|||||||
{ code: 'user:view', name: '查看用户', group: 'user' },
|
{ code: 'user:view', name: '查看用户', group: 'user' },
|
||||||
{ code: 'user:create', name: '创建用户', group: 'user' },
|
{ code: 'user:create', name: '创建用户', group: 'user' },
|
||||||
{ code: 'user:edit', name: '编辑用户', group: 'user' },
|
{ code: 'user:edit', name: '编辑用户', group: 'user' },
|
||||||
{ code: 'user:delete', name: '删除用户', group: 'user' },
|
|
||||||
{ code: 'user:reset-password', name: '重置密码', group: 'user' },
|
{ code: 'user:reset-password', name: '重置密码', group: 'user' },
|
||||||
{ code: 'role:view', name: '查看角色', group: 'role' },
|
{ code: 'role:view', name: '查看角色', group: 'role' },
|
||||||
{ code: 'role:create', name: '创建角色', group: 'role' },
|
{ code: 'role:create', name: '创建角色', group: 'role' },
|
||||||
@@ -250,7 +249,12 @@ export class RbacService {
|
|||||||
await this.permRepo.save(this.permRepo.create(p));
|
await this.permRepo.save(this.permRepo.create(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const allPerms = await this.permRepo.find();
|
const deprecatedUserDeletePermission = await this.permRepo.findOne({
|
||||||
|
where: { code: 'user:delete' },
|
||||||
|
});
|
||||||
|
const allPerms = (await this.permRepo.find()).filter(
|
||||||
|
(permission) => permission.code !== 'user:delete',
|
||||||
|
);
|
||||||
|
|
||||||
// Step 2: 幂等插入预置角色
|
// Step 2: 幂等插入预置角色
|
||||||
for (const r of PRESET_ROLES) {
|
for (const r of PRESET_ROLES) {
|
||||||
@@ -271,6 +275,19 @@ export class RbacService {
|
|||||||
}
|
}
|
||||||
const allRoles = await this.roleRepo.find({ relations: ['permissions', 'users'] });
|
const allRoles = await this.roleRepo.find({ relations: ['permissions', 'users'] });
|
||||||
|
|
||||||
|
if (deprecatedUserDeletePermission) {
|
||||||
|
for (const role of allRoles) {
|
||||||
|
const permissions = role.permissions ?? [];
|
||||||
|
if (permissions.some((permission) => permission.id === deprecatedUserDeletePermission.id)) {
|
||||||
|
role.permissions = permissions.filter(
|
||||||
|
(permission) => permission.id !== deprecatedUserDeletePermission.id,
|
||||||
|
);
|
||||||
|
await this.roleRepo.save(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.permRepo.remove(deprecatedUserDeletePermission);
|
||||||
|
}
|
||||||
|
|
||||||
// Step 3: 合并旧角色并构建新的职责权限矩阵
|
// Step 3: 合并旧角色并构建新的职责权限矩阵
|
||||||
for (const preset of PRESET_ROLES) {
|
for (const preset of PRESET_ROLES) {
|
||||||
const matchesPreset = (role: Role) =>
|
const matchesPreset = (role: Role) =>
|
||||||
@@ -564,15 +581,6 @@ export class RbacService {
|
|||||||
return { message: '已恢复为学员' };
|
return { message: '已恢复为学员' };
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteUser(id: number) {
|
|
||||||
const user = await this.userRepo.findOne({ where: { id } });
|
|
||||||
if (!user) throw new Error('用户不存在');
|
|
||||||
if (user.username === 'admin') throw new Error('不能删除默认管理员');
|
|
||||||
if (!user.isArchived) throw new Error('请先归档再删除');
|
|
||||||
await this.userRepo.remove(user);
|
|
||||||
return { message: '用户已删除' };
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- 用户资料 ----
|
// ---- 用户资料 ----
|
||||||
|
|
||||||
async getUserProfile(id: number) {
|
async getUserProfile(id: number) {
|
||||||
|
|||||||
3
技术文档.md
3
技术文档.md
@@ -169,7 +169,8 @@
|
|||||||
| GET | /api/auth/users | 用户列表 |
|
| GET | /api/auth/users | 用户列表 |
|
||||||
| PUT | /api/auth/users/:id | 编辑用户 |
|
| PUT | /api/auth/users/:id | 编辑用户 |
|
||||||
| PUT | /api/auth/users/:id/password | 重置密码 |
|
| PUT | /api/auth/users/:id/password | 重置密码 |
|
||||||
| DELETE | /api/auth/users/:id | 删除用户 |
|
| PUT | /api/rbac/users/:id/archive | 归档用户 |
|
||||||
|
| PUT | /api/rbac/users/:id/restore | 恢复用户 |
|
||||||
|
|
||||||
### 业务模块
|
### 业务模块
|
||||||
| 方法 | 路径 | 说明 |
|
| 方法 | 路径 | 说明 |
|
||||||
|
|||||||
Reference in New Issue
Block a user