Merge remote-tracking branch 'origin/test' into dev
This commit is contained in:
@@ -22,7 +22,7 @@ public final class AccountManagementDtos {
|
||||
String newPassword) { }
|
||||
public record CreateAccountRequest(@NotNull Long accountId,
|
||||
@NotBlank @Pattern(regexp = "^[A-Za-z][A-Za-z0-9_.@-]{3,63}$") String username,
|
||||
@Pattern(regexp = "^1\\d{10}$") String phone,
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@NotBlank @Size(min = 8, max = 64)
|
||||
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d).+$", message = "密码必须同时包含字母和数字") String password,
|
||||
@NotBlank String displayName, @NotNull Long tenantId,
|
||||
@@ -42,10 +42,10 @@ public final class AccountManagementDtos {
|
||||
}
|
||||
public record ChangeLoginIdentifiersRequest(
|
||||
@NotBlank @Pattern(regexp = "^[A-Za-z][A-Za-z0-9_.@-]{3,63}$") String username,
|
||||
@NotBlank @Pattern(regexp = "^1\\d{10}$") String phone,
|
||||
@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@NotBlank String currentPassword) { }
|
||||
public record UpdateAccountPhoneRequest(
|
||||
@NotBlank @Pattern(regexp = "^1\\d{10}$") String phone) { }
|
||||
@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$") String phone) { }
|
||||
public record UpdateAccountProfileRequest(@NotBlank @Size(max = 64) String displayName) { }
|
||||
public record UpdateAccountStatusRequest(@NotBlank String status) { }
|
||||
public record RevokeAccountSessionsRequest(
|
||||
|
||||
@@ -13,7 +13,7 @@ public record MerchantRegisterRequest(
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@NotBlank @Size(max = 128) String companyName,
|
||||
@NotBlank @Size(max = 64) String legalPerson,
|
||||
@NotBlank @Pattern(regexp = "^1\\d{10}$") String legalPhone,
|
||||
@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$") String legalPhone,
|
||||
@Email @Size(max = 128) String contactEmail,
|
||||
@Size(min = 2, max = 2) String countryCode,
|
||||
@Size(max = 255) String address
|
||||
|
||||
@@ -61,7 +61,7 @@ public class AuthService {
|
||||
description = "User login / 用户登录", captureAfter = false)
|
||||
public TokenResponse login(LoginRequest request) {
|
||||
String loginId = request.loginId().trim();
|
||||
AuthAccount account = loginId.matches("^1\\d{10}$")
|
||||
AuthAccount account = loginId.matches("^1[3-9]\\d{9}$")
|
||||
? accountRepository.findByPhone(loginId)
|
||||
: accountRepository.findByUsername(loginId);
|
||||
if (account == null) throw invalidCredentials();
|
||||
|
||||
@@ -23,14 +23,14 @@ BEGIN
|
||||
IF EXISTS (
|
||||
SELECT user.phone
|
||||
FROM baiyue_iam.iam_user user
|
||||
WHERE user.deleted = 0 AND user.phone REGEXP '^1[0-9]{10}$'
|
||||
WHERE user.deleted = 0 AND user.phone REGEXP '^1[3-9][0-9]{9}$'
|
||||
GROUP BY user.phone HAVING COUNT(DISTINCT user.auth_user_id) > 1) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'IAM 存在重复手机号,禁止建立 Auth 唯一登录索引';
|
||||
END IF;
|
||||
UPDATE auth_account account
|
||||
JOIN baiyue_iam.iam_user user ON user.auth_user_id = account.id AND user.deleted = 0
|
||||
SET account.phone = user.phone
|
||||
WHERE account.phone IS NULL AND user.phone REGEXP '^1[0-9]{10}$';
|
||||
WHERE account.phone IS NULL AND user.phone REGEXP '^1[3-9][0-9]{9}$';
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.statistics
|
||||
WHERE table_schema = 'baiyue_auth' AND table_name = 'auth_account'
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baiyue.auth.repository;
|
||||
|
||||
import com.baiyue.auth.dto.AccountManagementDtos.ChangeLoginIdentifiersRequest;
|
||||
import com.baiyue.auth.dto.MerchantRegisterRequest;
|
||||
import jakarta.validation.Validation;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class LoginIdentifierContractTest {
|
||||
|
||||
@Test
|
||||
void mainlandMobileRuleRejectsPlaceholderNumbersAcrossJavaAndSql() throws Exception {
|
||||
try (var factory = Validation.buildDefaultValidatorFactory()) {
|
||||
var validator = factory.getValidator();
|
||||
var invalidRegistration = new MerchantRegisterRequest(
|
||||
"merchant.user", "Password1", "测试用户", "测试企业", "张三",
|
||||
"11111111111", null, "CN", null);
|
||||
var validChange = new ChangeLoginIdentifiersRequest(
|
||||
"merchant.user", "13800138000", "Password1");
|
||||
var invalidChange = new ChangeLoginIdentifiersRequest(
|
||||
"merchant.user", "11111111111", "Password1");
|
||||
|
||||
assertThat(validator.validate(invalidRegistration)).isNotEmpty();
|
||||
assertThat(validator.validate(validChange)).isEmpty();
|
||||
assertThat(validator.validate(invalidChange)).isNotEmpty();
|
||||
}
|
||||
|
||||
String sql = new ClassPathResource("db/auth-login-identifiers.sql")
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(sql)
|
||||
.contains("REGEXP '^1[3-9][0-9]{9}$'")
|
||||
.doesNotContain("REGEXP '^1[0-9]{10}$'");
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,18 @@ class AuthServiceSmallJwtTest {
|
||||
verify(repository, never()).findByUsername("13800138000");
|
||||
}
|
||||
|
||||
@Test
|
||||
void placeholderNumberIsNeverResolvedAsAMobileLoginIdentifier() {
|
||||
when(repository.findByUsername("11111111111")).thenReturn(null);
|
||||
|
||||
assertThatThrownBy(() -> service.login(new LoginRequest("11111111111", "secret")))
|
||||
.isInstanceOf(com.baiyue.common.core.exception.BizException.class)
|
||||
.hasMessageContaining("登录标识或密码错误");
|
||||
|
||||
verify(repository).findByUsername("11111111111");
|
||||
verify(repository, never()).findByPhone("11111111111");
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshRotatesDomesticAndOverseasTokensFromOneAuthorizationSnapshot() {
|
||||
AuthAccount account = new AuthAccount();
|
||||
|
||||
@@ -18,7 +18,7 @@ public final class MemberDtos {
|
||||
@NotBlank @Size(min = 8, max = 64)
|
||||
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d).+$", message = "密码必须同时包含字母和数字") String password,
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@Pattern(regexp = "^1\\d{10}$") String phone,
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@Email @Size(max = 128) String email,
|
||||
@NotBlank String memberType,
|
||||
@Size(max = 64) String memberNo,
|
||||
@@ -30,7 +30,7 @@ public final class MemberDtos {
|
||||
|
||||
public record UpdateMemberRequest(
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@Pattern(regexp = "^1\\d{10}$") String phone,
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@Email @Size(max = 128) String email,
|
||||
@NotBlank String memberType,
|
||||
@Size(max = 64) String memberNo,
|
||||
|
||||
@@ -20,7 +20,7 @@ public final class PlatformInternalUserDtos {
|
||||
Long authUserId,
|
||||
String userType,
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@Pattern(regexp = "^1\\d{10}$") String phone,
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@Email @Size(max = 128) String email,
|
||||
@Pattern(regexp = "^[A-Za-z][A-Za-z0-9_.@-]{3,63}$") String username,
|
||||
@Size(min = 8, max = 64)
|
||||
@@ -31,7 +31,7 @@ public final class PlatformInternalUserDtos {
|
||||
|
||||
public record UpdateInternalUserRequest(
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@Pattern(regexp = "^1\\d{10}$") String phone,
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@Email @Size(max = 128) String email,
|
||||
@NotBlank @Size(max = 64) String memberNo,
|
||||
@NotNull List<Long> roleIds) { }
|
||||
|
||||
@@ -16,7 +16,7 @@ public final class PlatformUserManagementDtos {
|
||||
public record CreateUserRequest(
|
||||
@NotBlank @Pattern(regexp = "^[A-Za-z][A-Za-z0-9_.@-]{3,63}$") String username,
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@NotBlank @Pattern(regexp = "^1\\d{10}$", message = "手机号格式不正确") String phone,
|
||||
@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") String phone,
|
||||
@Email @Size(max = 128) String email,
|
||||
@NotNull Long tenantId,
|
||||
@NotNull List<Long> roleIds,
|
||||
@@ -32,7 +32,7 @@ public final class PlatformUserManagementDtos {
|
||||
|
||||
public record UpdateUserRequest(
|
||||
@NotBlank @Size(max = 64) String displayName,
|
||||
@NotBlank @Pattern(regexp = "^1\\d{10}$", message = "手机号格式不正确") String phone,
|
||||
@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") String phone,
|
||||
@Email @Size(max = 128) String email,
|
||||
@NotNull Long tenantId,
|
||||
@NotNull List<Long> roleIds,
|
||||
|
||||
@@ -17,7 +17,7 @@ public final class ProfileDtos {
|
||||
|
||||
public record ChangeLoginIdentifiersRequest(
|
||||
@NotBlank @Pattern(regexp = "^[A-Za-z][A-Za-z0-9_.@-]{3,63}$") String username,
|
||||
@NotBlank @Pattern(regexp = "^1\\d{10}$") String phone,
|
||||
@NotBlank @Pattern(regexp = "^1[3-9]\\d{9}$") String phone,
|
||||
@NotBlank String currentPassword) { }
|
||||
|
||||
public record AddressRequest(@NotBlank String addressType, String countryCode, String province,
|
||||
|
||||
@@ -982,7 +982,7 @@ components:
|
||||
authUserId: {type: string, pattern: '^\d+$'}
|
||||
username: {type: string, pattern: '^[A-Za-z][A-Za-z0-9_.@-]{3,63}$'}
|
||||
displayName: {type: string, maxLength: 64}
|
||||
phone: {type: string, pattern: '^1\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\d{9}$'}
|
||||
email: {type: string, format: email, nullable: true}
|
||||
UpdatePersonalProfileRequest:
|
||||
type: object
|
||||
@@ -995,7 +995,7 @@ components:
|
||||
required: [username, phone, currentPassword]
|
||||
properties:
|
||||
username: {type: string, pattern: '^[A-Za-z][A-Za-z0-9_.@-]{3,63}$'}
|
||||
phone: {type: string, pattern: '^1\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\d{9}$'}
|
||||
currentPassword: {type: string, format: password, writeOnly: true}
|
||||
PersonalProfileApiResponse:
|
||||
allOf:
|
||||
@@ -1398,7 +1398,7 @@ components:
|
||||
properties:
|
||||
username: {type: string, pattern: '^[A-Za-z][A-Za-z0-9_.@-]{3,63}$'}
|
||||
displayName: {type: string, maxLength: 64}
|
||||
phone: {type: string, pattern: '^1\\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\\d{9}$'}
|
||||
email: {type: string, format: email, maxLength: 128}
|
||||
tenantId: {type: integer, format: int64, enum: [0], description: 保留的兼容字段,只允许平台技术作用域 0}
|
||||
roleIds: {type: array, minItems: 1, items: {type: integer, format: int64}}
|
||||
@@ -1410,7 +1410,7 @@ components:
|
||||
required: [displayName, phone, tenantId, roleIds]
|
||||
properties:
|
||||
displayName: {type: string, maxLength: 64}
|
||||
phone: {type: string, pattern: '^1\\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\\d{9}$'}
|
||||
email: {type: string, format: email, maxLength: 128}
|
||||
tenantId: {type: integer, format: int64, enum: [0], description: 保留的兼容字段,只允许平台技术作用域 0}
|
||||
roleIds: {type: array, minItems: 1, items: {type: integer, format: int64}}
|
||||
@@ -1424,7 +1424,7 @@ components:
|
||||
username: {type: string, pattern: '^[A-Za-z][A-Za-z0-9_.@-]{3,63}$'}
|
||||
password: {type: string, format: password, minLength: 8, maxLength: 64, writeOnly: true}
|
||||
displayName: {type: string, maxLength: 64}
|
||||
phone: {type: string, pattern: '^1\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\d{9}$'}
|
||||
email: {type: string, format: email, maxLength: 128}
|
||||
memberNo: {type: string, maxLength: 64}
|
||||
roleIds: {type: array, items: {type: integer, format: int64}}
|
||||
@@ -1433,7 +1433,7 @@ components:
|
||||
required: [displayName, memberNo, roleIds]
|
||||
properties:
|
||||
displayName: {type: string, maxLength: 64}
|
||||
phone: {type: string, pattern: '^1\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\d{9}$'}
|
||||
email: {type: string, format: email, maxLength: 128}
|
||||
memberNo: {type: string, maxLength: 64}
|
||||
roleIds: {type: array, items: {type: integer, format: int64}}
|
||||
@@ -1495,7 +1495,7 @@ components:
|
||||
username: {type: string, pattern: '^[A-Za-z][A-Za-z0-9_.@-]{3,63}$'}
|
||||
password: {type: string, format: password, minLength: 8, maxLength: 64}
|
||||
displayName: {type: string, maxLength: 64}
|
||||
phone: {type: string, pattern: '^1\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\d{9}$'}
|
||||
email: {type: string, format: email, maxLength: 128}
|
||||
memberType: {type: string, enum: [EMPLOYEE]}
|
||||
memberNo: {type: string}
|
||||
@@ -1508,7 +1508,7 @@ components:
|
||||
required: [displayName, memberType]
|
||||
properties:
|
||||
displayName: {type: string, maxLength: 64}
|
||||
phone: {type: string, pattern: '^1\d{10}$'}
|
||||
phone: {type: string, pattern: '^1[3-9]\d{9}$'}
|
||||
email: {type: string, format: email, maxLength: 128}
|
||||
memberType: {type: string, enum: [EMPLOYEE]}
|
||||
memberNo: {type: string, maxLength: 64}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/merchant/v1/order-addresses")
|
||||
@RequestMapping("/api/merchant/v1/orders/first-leg/addresses")
|
||||
public class MerchantCustomerAddressController {
|
||||
@Resource private CustomerAddressService service;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ info:
|
||||
security:
|
||||
- bearerAuth: []
|
||||
paths:
|
||||
/api/merchant/v1/order-addresses:
|
||||
/api/merchant/v1/orders/first-leg/addresses:
|
||||
get:
|
||||
summary: 查询当前客户下单地址簿
|
||||
parameters:
|
||||
@@ -27,7 +27,7 @@ paths:
|
||||
responses:
|
||||
'200': {description: 返回地址内部 ID,Long 按字符串序列化}
|
||||
'403': {description: 需要 merchant:order:create 权限}
|
||||
/api/merchant/v1/order-addresses/{id}:
|
||||
/api/merchant/v1/orders/first-leg/addresses/{id}:
|
||||
put:
|
||||
summary: 修改当前客户下单地址
|
||||
description: 已创建订单保存独立快照,本操作不会修改历史订单。
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ class OrderCustomerFoundationOpenApiContractTest {
|
||||
assertThat(input).isNotNull();
|
||||
String yaml = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
||||
assertThat(yaml)
|
||||
.contains("/api/merchant/v1/order-addresses:")
|
||||
.contains("/api/merchant/v1/orders/first-leg/addresses:")
|
||||
.contains("/api/merchant/v1/orders/first-leg/batch-imports:")
|
||||
.contains("senderAddressId:")
|
||||
.contains("privateDestinationAddressId:")
|
||||
|
||||
Reference in New Issue
Block a user