Files
ssh-manager/multi-user-management-plan.md
T
liumangmang 1f1d1db65a feat: 多用户管理与公开注册功能
- 后端:User 实体新增 role/enabled 字段、UserController CRUD、UserService
- 安全:SecurityConfig /api/users/** 要求 ROLE_ADMIN、JWT 过滤器检查账号状态
- 注册:POST /api/auth/register 公开注册,固定 ROLE_USER
- 保护:删除/禁用/降级最后 admin 均拒绝,DataInitializer 含 backfill
- 前端:用户管理页面、登录/注册切换、admin 专属导航入口
- 测试:UserServiceTest 19 个 + UserControllerTest 6 个 + AuthControllerTest 适配
2026-05-28 09:13:27 +08:00

139 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 多用户管理功能 — 实现计划
## 目标
当前项目只支持一个硬编码的 `admin` 用户。本计划将其升级为完整的**多用户管理体系**,支持管理员创建/编辑/删除普通用户、密码重置、用户列表展示、用户启用/禁用,以及权限分离(管理员 vs 普通用户)。
---
## 实施步骤
### 步骤 1:后端 — User 实体增加字段
**文件**: `backend/src/main/java/com/sshmanager/entity/User.java`
| 新增字段 | 类型 | 说明 |
|---------|------|------|
| `role` | `String` | `"ROLE_ADMIN"``"ROLE_USER"`,默认 `"ROLE_USER"` |
| `enabled` | `boolean` | 是否启用,默认 `true` |
同时为 `role``enabled` 添加数据库列映射。
---
### 步骤 2:后端 — 创建 User 相关 DTO
**新建文件**:
| 文件 | 说明 |
|------|------|
| `backend/src/main/java/com/sshmanager/dto/UserDto.java` | 返回给前端的用户信息(不含密码) |
| `backend/src/main/java/com/sshmanager/dto/CreateUserRequest.java` | 创建用户请求体 |
| `backend/src/main/java/com/sshmanager/dto/UpdateUserRequest.java` | 更新用户请求体 |
---
### 步骤 3:后端 — 创建 UserService
**新建文件**: `backend/src/main/java/com/sshmanager/service/UserService.java`
方法:
- `listUsers()` — 列出所有用户(仅 admin
- `getUser(id)` — 获取单个用户
- `createUser(request)` — 创建用户,校验 username 唯一性
- `updateUser(id, request)` — 更新用户 displayName / role / enabled
- `deleteUser(id)` — 删除用户(不能删除自己,不能删除最后一个 admin)
- `resetPassword(id, newPassword)` — 管理员重置指定用户密码
---
### 步骤 4:后端 — 创建 UserController
**新建文件**: `backend/src/main/java/com/sshmanager/controller/UserController.java`
REST API (`/api/users`)
| 方法 | 路径 | 权限 | 说明 |
|------|------|------|------|
| GET | `/api/users` | ADMIN | 用户列表 |
| GET | `/api/users/{id}` | ADMIN | 用户详情 |
| POST | `/api/users` | ADMIN | 创建用户 |
| PUT | `/api/users/{id}` | ADMIN | 更新用户 |
| DELETE | `/api/users/{id}` | ADMIN | 删除用户 |
| POST | `/api/users/{id}/reset-password` | ADMIN | 重置密码 |
---
### 步骤 5:后端 — Security / 权限改造
**文件**:
- `CustomUserDetailsService.java` — 在 `UserDetails` 中赋予 `role` 对应的 `SimpleGrantedAuthority`
- `SecurityConfig.java` — 添加 `antMatchers("/api/users/**").hasRole("ADMIN")`
- `AuthController.java` — 修改 `/auth/me` 返回 `role` 字段
- `LoginResponse.java` — 添加 `role` 字段
- `DataInitializer.java` — admin 初始角色设为 `ROLE_ADMIN`
**新建文件**:
- `backend/src/main/java/com/sshmanager/security/AdminOnlyAspect.java` (可选,或直接在 Controller 里通过 Authentication 检查)
---
### 步骤 6:前端 — 类型和服务
**文件**:
- `frontend/src/types.ts``LoginResponse``CurrentUser` 增加 `role: string`
- `frontend/src/services/users.ts` — 用户 CRUD HTTP 服务
---
### 步骤 7:前端 — 用户管理页面
**新建文件**: `frontend/src/pages/UserManagementPage.tsx`
功能:
- 用户列表表格(用户名、显示名、角色、状态、创建时间)
- 创建用户弹窗(用户名、密码、显示名、角色选择)
- 编辑用户弹窗(修改显示名、角色、启用/禁用)
- 删除用户(确认 + 不能删除自己)
- 重置密码弹窗
---
### 步骤 8:前端 — 路由 & 导航接入
**文件**:
- `App.tsx` — 添加 `/users` 路由指向 `UserManagementPage`
- `WorkspacePage.tsx` — 顶部导航栏增加"用户管理"按钮,仅当当前用户 `role === "ROLE_ADMIN"` 时显示
---
## 数据流
```
[UserManagementPage] --GET /api/users--> [UserController] --UserService--> [UserRepository] --> [DB]
--POST /api/users-->
--PUT /api/users/{id}-->
--DELETE /api/users/{id}-->
--POST /api/users/{id}/reset-password-->
```
每个连接(Connection)已经通过 `userId` 与用户关联,同一用户仅能看到自己的连接。多用户后此逻辑保持不变。
---
## 风险 & 注意事项
1. **不能删除最后一个 admin** — UserService 中 deleteUser 需检查
2. **不能禁用自己** — updateUser 如果自己禁用自己的 enabled=false 需拒绝
3. **密码重置后应强制改密** — 重置时设 `passwordChangedAt = Instant.EPOCH`,使 `isPasswordChangeRequired` 返回 true
4. **H2 数据库** — 重启后数据消失但 DataInitializer 会重建 admin;正式部署应考虑迁移到持久化数据库
---
## 验证方式
1. 启动后端,`curl /api/users` 应返回 admin 用户
2. 用新用户登录验证数据隔离(自己只能看到自己的连接)
3. admin 删除最后一个 admin 用户应拒绝