fix: keep ambiguous legacy phones unbound

This commit is contained in:
2026-09-01 19:34:17 +08:00
parent 271a77fd86
commit 9fc20d5482
3 changed files with 88 additions and 7 deletions
@@ -20,15 +20,18 @@ DROP PROCEDURE IF EXISTS auth_backfill_login_phone;
DELIMITER $$
CREATE PROCEDURE auth_backfill_login_phone()
BEGIN
IF EXISTS (
SELECT user.phone
FROM baiyue_iam.iam_user user
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
SET phone = NULL
WHERE phone IS NOT NULL AND phone NOT REGEXP '^1[3-9][0-9]{9}$';
UPDATE auth_account account
JOIN baiyue_iam.iam_user user ON user.auth_user_id = account.id AND user.deleted = 0
JOIN (
SELECT phone
FROM baiyue_iam.iam_user
WHERE deleted = 0 AND phone REGEXP '^1[3-9][0-9]{9}$'
GROUP BY phone
HAVING COUNT(DISTINCT auth_user_id) = 1
) unique_phone ON unique_phone.phone = user.phone
SET account.phone = user.phone
WHERE account.phone IS NULL AND user.phone REGEXP '^1[3-9][0-9]{9}$';
IF NOT EXISTS (
@@ -0,0 +1,32 @@
package com.baiyue.auth.repository;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
class AuthLoginIdentifiersSqlContractTest {
@Test
void backfillsOnlyUniquelyOwnedPhonesAndKeepsDuplicateLegacyPhonesUnbound() throws Exception {
assertSafeBackfill(new ClassPathResource("db/auth-login-identifiers.sql")
.getContentAsString(StandardCharsets.UTF_8));
assertSafeBackfill(Files.readString(unifiedSql(), StandardCharsets.UTF_8));
}
private static void assertSafeBackfill(String sql) {
assertThat(sql)
.contains("phone NOT REGEXP '^1[3-9][0-9]{9}$'")
.contains("HAVING COUNT(DISTINCT auth_user_id) = 1")
.contains("ADD UNIQUE KEY uk_auth_account_phone (phone)")
.doesNotContain("IAM 存在重复手机号,禁止建立 Auth 唯一登录索引");
}
private static Path unifiedSql() {
Path path = Path.of("deploy", "sql", "头程数据库统一增量-MySQL8.sql");
return Files.exists(path) ? path : Path.of("..", "deploy", "sql", "头程数据库统一增量-MySQL8.sql");
}
}
@@ -17077,6 +17077,52 @@ CREATE TABLE IF NOT EXISTS fl_dropship_pallet_carton (
CONSTRAINT fk_dropship_carton_label FOREIGN KEY (carton_label_id) REFERENCES fl_inbound_carton_label(id)
) ENGINE=InnoDB COMMENT='一件代发托盘内逐箱SKU和入仓单明细';
-- Auth 登录手机号只从 IAM 中唯一归属的中国大陆手机号回填;存量重复号保持 NULL。
USE baiyue_auth;
DROP PROCEDURE IF EXISTS auth_add_login_phone;
DELIMITER $$
CREATE PROCEDURE auth_add_login_phone()
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'baiyue_auth' AND table_name = 'auth_account' AND column_name = 'phone') THEN
ALTER TABLE auth_account ADD COLUMN phone VARCHAR(32) NULL COMMENT '全局唯一中国大陆登录手机号' AFTER username;
END IF;
END$$
DELIMITER ;
CALL auth_add_login_phone();
DROP PROCEDURE auth_add_login_phone;
DROP PROCEDURE IF EXISTS auth_backfill_login_phone;
DELIMITER $$
CREATE PROCEDURE auth_backfill_login_phone()
BEGIN
UPDATE auth_account
SET phone = NULL
WHERE phone IS NOT NULL AND phone NOT REGEXP '^1[3-9][0-9]{9}$';
UPDATE auth_account account
JOIN baiyue_iam.iam_user user ON user.auth_user_id = account.id AND user.deleted = 0
JOIN (
SELECT phone
FROM baiyue_iam.iam_user
WHERE deleted = 0 AND phone REGEXP '^1[3-9][0-9]{9}$'
GROUP BY phone
HAVING COUNT(DISTINCT auth_user_id) = 1
) unique_phone ON unique_phone.phone = user.phone
SET account.phone = user.phone
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'
AND index_name = 'uk_auth_account_phone') THEN
ALTER TABLE auth_account ADD UNIQUE KEY uk_auth_account_phone (phone);
END IF;
END$$
DELIMITER ;
CALL auth_backfill_login_phone();
DROP PROCEDURE auth_backfill_login_phone;
USE baiyue_firstleg;
CALL baiyue_firstleg.assert_unified_final_schema();
DROP PROCEDURE IF EXISTS baiyue_firstleg.assert_unified_final_schema;
SELECT 'PASS' AS migration_status,