Refactor account management DTOs by removing displayName and role fields from AccountCreateRequest, AccountUpdateRequest, and AccountResponse, and updating related logic in AccountService. Adjust alwaysApply setting in zh.mdc to false.

This commit is contained in:
zyh
2025-08-24 18:41:57 +08:00
parent f37159e1fc
commit 1b3ce1040a
31 changed files with 240 additions and 46 deletions

View File

@@ -1,5 +1,4 @@
---
description:
globs: 中文回答我
alwaysApply: true
alwaysApply: false
---
中文回答我

199
docs/API文档.md Normal file
View File

@@ -0,0 +1,199 @@
# API 文档
## 用户管理接口
### 创建用户账户
#### 管理员创建用户账户
**接口地址:** `POST /api/admin/accounts`
**请求头:**
```
Content-Type: application/json
Authorization: Bearer {token}
```
**请求参数:**
```json
{
"userType": "ADMIN", // 必填用户类型ADMIN 或 AGENT
"username": "newuser", // 必填用户名3-64字符只能包含字母、数字、下划线
"password": "123456", // 必填密码6-128字符
"status": "ENABLED", // 可选状态ENABLED 或 DISABLED默认ENABLED
"pointsBalance": 0 // 可选积分余额仅AGENT类型默认0
}
```
**成功响应200**
```json
{
"id": 2,
"userType": "ADMIN",
"username": "newuser",
"status": "ENABLED",
"pointsBalance": 0,
"createdAt": "2025-08-24T18:30:00.000",
"updatedAt": "2025-08-24T18:30:00.000"
}
```
**错误响应:**
**400 Bad Request - 参数验证失败:**
```json
{
"timestamp": "2025-08-24T18:30:00.000",
"status": 400,
"error": "Bad Request",
"message": "Validation failed",
"details": [
{
"field": "username",
"message": "用户名长度必须在3-64字符之间"
},
{
"field": "password",
"message": "密码长度必须在6-128字符之间"
}
]
}
```
**409 Conflict - 用户名已存在:**
```json
{
"timestamp": "2025-08-24T18:30:00.000",
"status": 409,
"error": "Conflict",
"message": "用户名已存在"
}
```
**401 Unauthorized - 未授权:**
```json
{
"timestamp": "2025-08-24T18:30:00.000",
"status": 401,
"error": "Unauthorized",
"message": "访问被拒绝"
}
```
**403 Forbidden - 权限不足:**
```json
{
"timestamp": "2025-08-24T18:30:00.000",
"status": 403,
"error": "Forbidden",
"message": "权限不足,无法创建用户"
}
```
#### 用户自注册接口
**接口地址:** `POST /api/users`
**请求头:**
```
Content-Type: application/json
```
**请求参数:**
```json
{
"userType": "AGENT", // 必填,用户类型:只能为 AGENT
"username": "newagent", // 必填用户名3-64字符
"password": "123456", // 必填密码6-128字符
"pointsBalance": 0 // 可选积分余额默认0
}
```
**成功响应201**
```json
{
"id": 3,
"userType": "AGENT",
"username": "newagent",
"status": "ENABLED",
"pointsBalance": 0,
"createdAt": "2025-08-24T18:30:00.000",
"updatedAt": "2025-08-24T18:30:00.000"
}
```
### 接口说明
#### 权限要求
- **管理员接口** (`/api/admin/accounts`)需要管理员权限可以创建ADMIN和AGENT类型用户
- **用户接口** (`/api/users`)公开接口只能创建AGENT类型用户
#### 参数说明
**userType用户类型**
- `ADMIN`:管理员用户
- `AGENT`:代理用户
**username用户名**
- 长度3-64字符
- 格式:只能包含字母、数字、下划线
- 唯一性:系统内必须唯一
**password密码**
- 长度6-128字符
- 存储使用BCrypt加密存储
- 安全:建议包含大小写字母、数字和特殊字符
**status状态**
- 可选值:`ENABLED`(启用)、`DISABLED`(禁用)
- 默认值:`ENABLED`
**pointsBalance积分余额**
- 仅AGENT类型用户可以设置
- 类型:整数,不能为负数
- 默认值0
#### 业务规则
1. 用户名在系统内必须唯一
2. 密码使用BCrypt加密存储无法解密
3. 创建成功后账户默认状态为ENABLED
4. 只有管理员可以创建ADMIN类型用户
5. 简化的用户模型,去除了角色和显示名称等复杂字段
#### 使用示例
**创建管理员用户:**
```bash
curl -X POST http://localhost:8080/api/admin/accounts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token" \
-d '{
"userType": "ADMIN",
"username": "admin001",
"password": "Admin123!"
}'
```
**创建代理用户:**
```bash
curl -X POST http://localhost:8080/api/admin/accounts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token" \
-d '{
"userType": "AGENT",
"username": "agent001",
"password": "Agent123!",
"pointsBalance": 1000
}'
```
**用户自注册:**
```bash
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{
"userType": "AGENT",
"username": "newuser",
"password": "User123!"
}'
```

View File

@@ -8,13 +8,11 @@ public class AccountCreateRequest {
@NotBlank
@Size(min = 3, max = 64)
private String username;
@Size(max = 100)
private String displayName;
private String role; // for ADMIN: SUPER | ADMIN
private String status = "ENABLED"; // ENABLED | DISABLED
@NotBlank
@Size(min = 6, max = 128)
private String initialPassword;
private String password;
@Min(0)
private Long pointsBalance = 0L; // for AGENT
@@ -22,14 +20,11 @@ public class AccountCreateRequest {
public void setUserType(String userType) { this.userType = userType; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getInitialPassword() { return initialPassword; }
public void setInitialPassword(String initialPassword) { this.initialPassword = initialPassword; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public Long getPointsBalance() { return pointsBalance; }
public void setPointsBalance(Long pointsBalance) { this.pointsBalance = pointsBalance; }
}

View File

@@ -6,8 +6,7 @@ public class AccountResponse {
private Long id;
private String userType;
private String username;
private String displayName;
private String role;
private String status;
private Long pointsBalance;
private LocalDateTime createdAt;
@@ -19,10 +18,7 @@ public class AccountResponse {
public void setUserType(String userType) { this.userType = userType; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public Long getPointsBalance() { return pointsBalance; }

View File

@@ -3,15 +3,10 @@ package com.gameplatform.server.model.dto.account;
import jakarta.validation.constraints.Size;
public class AccountUpdateRequest {
@Size(max = 100)
private String displayName;
private String role; // SUPER | ADMIN (only for ADMIN)
private String status; // ENABLED | DISABLED
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}

View File

@@ -6,9 +6,9 @@ public class UserAccount {
private Long id;
private String userType; // ADMIN | AGENT
private String username; // 登录名admin/agent 共用)
private String displayName; // 显示名称agent 可用)
private String passwordHash; // BCrypt 或 PLAIN:xxx初始化用
private String role; // 仅 ADMIN 使用SUPER / ADMIN
private String status; // ENABLED / DISABLED
private Long pointsBalance; // 仅 AGENT 使用
private LocalDateTime createdAt;
@@ -20,12 +20,10 @@ public class UserAccount {
public void setUserType(String userType) { this.userType = userType; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }
public String getPasswordHash() { return passwordHash; }
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public Long getPointsBalance() { return pointsBalance; }

View File

@@ -25,14 +25,14 @@ public class AccountService {
this.passwordEncoder = passwordEncoder;
}
public Mono<PageResult<AccountResponse>> list(String userType, String status, String role, String keyword,
public Mono<PageResult<AccountResponse>> list(String userType, String status, String keyword,
Integer page, Integer size) {
int p = (page == null || page < 1) ? 1 : page;
int s = (size == null || size < 1 || size > 200) ? 20 : size;
int offset = (p - 1) * s;
return Mono.fromCallable(() -> {
long total = mapper.countByFilter(userType, status, role, keyword);
List<UserAccount> list = mapper.listByFilter(userType, status, role, keyword, s, offset);
long total = mapper.countByFilter(userType, status, null, keyword);
List<UserAccount> list = mapper.listByFilter(userType, status, null, keyword, s, offset);
List<AccountResponse> items = list.stream().map(this::toResp).collect(Collectors.toList());
return new PageResult<>(items, total, p, s);
})
@@ -54,16 +54,13 @@ public class AccountService {
UserAccount acc = new UserAccount();
acc.setUserType(type);
acc.setUsername(req.getUsername());
acc.setDisplayName(req.getDisplayName());
acc.setStatus(req.getStatus() == null ? "ENABLED" : req.getStatus());
if ("ADMIN".equals(type)) {
acc.setRole(req.getRole() == null ? "ADMIN" : req.getRole());
acc.setPointsBalance(0L);
} else {
acc.setRole(null);
acc.setPointsBalance(req.getPointsBalance() == null ? 0L : req.getPointsBalance());
}
acc.setPasswordHash(passwordEncoder.encode(req.getInitialPassword()));
acc.setPasswordHash(passwordEncoder.encode(req.getPassword()));
mapper.insert(acc);
return toResp(acc);
})
@@ -83,11 +80,7 @@ public class AccountService {
if (db == null) return null;
UserAccount patch = new UserAccount();
patch.setId(id);
patch.setDisplayName(req.getDisplayName());
// Only ADMIN account may set role; AGENT's role must remain null
if ("ADMIN".equalsIgnoreCase(db.getUserType())) {
patch.setRole(req.getRole());
}
patch.setStatus(req.getStatus());
mapper.update(patch);
return mapper.findById(id);
@@ -119,8 +112,7 @@ public class AccountService {
r.setId(a.getId());
r.setUserType(a.getUserType());
r.setUsername(a.getUsername());
r.setDisplayName(a.getDisplayName());
r.setRole(a.getRole());
r.setStatus(a.getStatus());
r.setPointsBalance(a.getPointsBalance());
r.setCreatedAt(a.getCreatedAt());

View File

@@ -0,0 +1,20 @@
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\GamePlatformServerApplication.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\security\SecurityConfig.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\dto\account\ResetPasswordRequest.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\service\account\AccountService.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\service\auth\AuthService.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\dto\account\AccountUpdateRequest.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\dto\auth\LoginRequest.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\controller\admin\AccountController.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\dto\auth\LoginResponse.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\controller\UserController.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\dto\account\AccountResponse.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\service\UserService.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\controller\auth\AuthController.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\security\JwtService.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\config\CorsConfig.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\exception\GlobalExceptionHandler.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\dto\common\PageResult.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\mapper\account\UserAccountMapper.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\dto\account\AccountCreateRequest.java
D:\project\gamePlatform\server\src\main\java\com\gameplatform\server\model\entity\account\UserAccount.java