fix: default register client id
This commit is contained in:
19
openspec/changes/fix-register-body-validation/.comet.yaml
Normal file
19
openspec/changes/fix-register-body-validation/.comet.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
workflow: hotfix
|
||||
phase: build
|
||||
context_compression: off
|
||||
build_mode: direct
|
||||
build_pause: null
|
||||
subagent_dispatch: null
|
||||
tdd_mode: direct
|
||||
isolation: branch
|
||||
verify_mode: light
|
||||
auto_transition: true
|
||||
base_ref: 2f7597ed53736b965191d4e48ee2c73d09ff71c0
|
||||
design_doc: null
|
||||
plan: null
|
||||
verify_result: pending
|
||||
verification_report: null
|
||||
branch_status: pending
|
||||
created_at: 2026-08-14
|
||||
verified_at: null
|
||||
archived: false
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-08-14
|
||||
27
openspec/changes/fix-register-body-validation/design.md
Normal file
27
openspec/changes/fix-register-body-validation/design.md
Normal file
@@ -0,0 +1,27 @@
|
||||
## Context
|
||||
|
||||
`AuthController.register` 当前依赖 Spring MVC 的 `@Validated` 自动校验。该校验发生在控制器方法调用之前,所以方法体无法为缺失的 `clientId` 补默认值。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- 空白 `clientId` 使用固定注册客户端 ID `32324a04c0175c8d61ac8a282553aea1`。
|
||||
- 默认值补充后仍执行 `RegisterBody` 的全部 Bean Validation 约束。
|
||||
- 保持注册开关检查和注册服务调用顺序不变。
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- 不调整 `RegisterBody` 的继承结构或其他登录字段。
|
||||
- 不改变登录接口和认证客户端配置。
|
||||
|
||||
## Decisions
|
||||
|
||||
- 移除注册方法参数上的 `@Validated`,在方法体开始处补默认 `clientId` 后调用现有 `ValidatorUtils.validate(user)`。该工具已被认证控制器和各登录策略使用,异常处理行为与现有认证流程一致。
|
||||
- 使用 `StringUtils.isBlank`,同时覆盖 `null`、空字符串和纯空白字符串。
|
||||
- 通过 `AuthController` 单元测试观察注册服务收到的请求对象,验证公共接口行为。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 固定客户端 ID 变更时需要同步修改代码和测试;本次按明确业务值实现。
|
||||
- 手动校验依赖控制器方法内调用顺序;测试覆盖默认值补充发生在校验和业务调用之前。
|
||||
25
openspec/changes/fix-register-body-validation/proposal.md
Normal file
25
openspec/changes/fix-register-body-validation/proposal.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Why
|
||||
|
||||
`/auth/register` 使用 `@Validated` 在进入控制器方法前校验 `RegisterBody`,缺少 `clientId` 的请求会直接返回“认证客户端id不能为空”,因此控制器无法为注册请求补充系统默认客户端 ID。注册入口需要先补默认值,再执行原有参数校验。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 注册接口收到空白 `clientId` 时,将其设置为 `32324a04c0175c8d61ac8a282553aea1`。
|
||||
- 默认值补充完成后,通过现有 `ValidatorUtils` 执行 `RegisterBody` 的完整 Bean Validation。
|
||||
- 增加控制器回归测试,覆盖默认客户端 ID 和注册服务调用。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `auth-registration`: 为已有注册入口补充默认认证客户端 ID 的行为规范。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
无。仓库当前没有注册流程的既有 OpenSpec。
|
||||
|
||||
## Impact
|
||||
|
||||
- 影响 `water-admin` 中的 `/auth/register` 控制器及其单元测试。
|
||||
- `/auth/register` 允许调用方省略或传入空白 `clientId`,其他注册参数约束保持不变。
|
||||
- 不新增依赖,不修改数据库结构,也不新增公共端点。
|
||||
@@ -0,0 +1,11 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 注册请求使用默认认证客户端
|
||||
|
||||
系统 SHALL 在校验注册请求前,为缺失或空白的 `clientId` 设置默认值 `32324a04c0175c8d61ac8a282553aea1`,并在补值后执行 `RegisterBody` 的全部参数约束。
|
||||
|
||||
#### Scenario: 注册请求未提供客户端 ID
|
||||
|
||||
- **WHEN** 调用方提交的注册请求中 `clientId` 缺失或为空白
|
||||
- **THEN** 系统将 `clientId` 设置为 `32324a04c0175c8d61ac8a282553aea1`
|
||||
- **AND** 系统在调用注册服务前校验补值后的注册请求
|
||||
4
openspec/changes/fix-register-body-validation/tasks.md
Normal file
4
openspec/changes/fix-register-body-validation/tasks.md
Normal file
@@ -0,0 +1,4 @@
|
||||
## 1. 注册默认客户端 ID
|
||||
|
||||
- [x] 1.1 在控制器单元测试中覆盖空白 `clientId` 自动补默认值的注册场景,并确认修改前失败。
|
||||
- [x] 1.2 调整 `/auth/register` 的校验顺序,补默认 `clientId` 后执行完整参数校验,并运行相关测试。
|
||||
@@ -201,7 +201,11 @@ public class AuthController {
|
||||
*/
|
||||
@ApiEncrypt
|
||||
@PostMapping("/register")
|
||||
public R<Void> register(@Validated @RequestBody RegisterBody user) {
|
||||
public R<Void> register(@RequestBody RegisterBody user) {
|
||||
if (StringUtils.isBlank(user.getClientId())) {
|
||||
user.setClientId("32324a04c0175c8d61ac8a282553aea1");
|
||||
}
|
||||
ValidatorUtils.validate(user);
|
||||
if (!configService.selectRegisterEnabled(user.getTenantId())) {
|
||||
return R.fail("当前系统没有开启注册功能!");
|
||||
}
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
package org.dromara.web.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.domain.model.AccountCancelBody;
|
||||
import org.dromara.common.core.domain.model.RegisterBody;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.system.service.ISysConfigService;
|
||||
import org.dromara.web.service.AccountCancellationService;
|
||||
import org.dromara.web.service.SysRegisterService;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@Tag("dev")
|
||||
@@ -23,6 +31,12 @@ class AuthControllerUnitTest {
|
||||
@Mock
|
||||
private AccountCancellationService accountCancellationService;
|
||||
|
||||
@Mock
|
||||
private SysRegisterService registerService;
|
||||
|
||||
@Mock
|
||||
private ISysConfigService configService;
|
||||
|
||||
@Test
|
||||
void cancelAccount_checksLoginCancelsAccountAndLogsOut() {
|
||||
AuthController controller = new AuthController(
|
||||
@@ -52,4 +66,38 @@ class AuthControllerUnitTest {
|
||||
stpUtil.verify(() -> StpUtil.logout(100L));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void register_defaultsClientIdWhenMissing() {
|
||||
AuthController controller = new AuthController(
|
||||
null,
|
||||
null,
|
||||
registerService,
|
||||
configService,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
accountCancellationService
|
||||
);
|
||||
RegisterBody user = new RegisterBody();
|
||||
user.setUsername("register-user");
|
||||
user.setPassword("12345");
|
||||
user.setGrantType("password");
|
||||
when(configService.selectRegisterEnabled(user.getTenantId())).thenReturn(true);
|
||||
|
||||
try (ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
|
||||
GenericApplicationContext context = new GenericApplicationContext()) {
|
||||
context.getBeanFactory().registerSingleton("validator", validatorFactory.getValidator());
|
||||
context.refresh();
|
||||
new SpringUtil().setApplicationContext(context);
|
||||
|
||||
R<Void> result = controller.register(user);
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(200);
|
||||
assertThat(user.getClientId()).isEqualTo("32324a04c0175c8d61ac8a282553aea1");
|
||||
verify(registerService).register(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user