feat: add puzzle clear template runtime
This commit is contained in:
@@ -455,19 +455,42 @@ fn export_auth_store_snapshot_from_tables_tx(
|
||||
.find(&AUTH_STORE_PROJECTION_META_ID.to_string())
|
||||
.map(|row| row.updated_at.to_micros_since_unix_epoch());
|
||||
|
||||
let snapshot = build_auth_store_snapshot_from_rows(users, identities, sessions)?;
|
||||
if let Some(updated_at_micros) = updated_at_micros {
|
||||
upsert_auth_store_snapshot_rows(ctx, &snapshot, updated_at_micros)?;
|
||||
}
|
||||
let snapshot_json = serde_json::to_string_pretty(&snapshot)
|
||||
.map_err(|error| format!("序列化认证快照失败:{error}"))?;
|
||||
|
||||
Ok(AuthStoreSnapshotRecord {
|
||||
snapshot_json: Some(snapshot_json),
|
||||
updated_at_micros,
|
||||
})
|
||||
}
|
||||
|
||||
fn build_auth_store_snapshot_from_rows(
|
||||
users: Vec<UserAccount>,
|
||||
identities: Vec<AuthIdentity>,
|
||||
sessions: Vec<RefreshSession>,
|
||||
) -> Result<PersistentAuthStoreSnapshot, String> {
|
||||
let valid_user_ids = users
|
||||
.iter()
|
||||
.map(|user| user.user_id.clone())
|
||||
.collect::<std::collections::HashSet<_>>();
|
||||
let mut phone_identity_by_user_id = std::collections::HashMap::new();
|
||||
let mut phone_to_user_id = std::collections::HashMap::new();
|
||||
let mut wechat_identity_by_provider_uid = std::collections::HashMap::new();
|
||||
let mut user_id_by_provider_union_id = std::collections::HashMap::new();
|
||||
|
||||
for identity in identities {
|
||||
if !valid_user_ids.contains(&identity.user_id) {
|
||||
continue;
|
||||
}
|
||||
match identity.provider.as_str() {
|
||||
"phone" => {
|
||||
let phone_number = identity
|
||||
.phone_e164
|
||||
.clone()
|
||||
.unwrap_or_else(|| identity.provider_uid.clone());
|
||||
phone_to_user_id.insert(phone_number.clone(), identity.user_id.clone());
|
||||
phone_identity_by_user_id.insert(identity.user_id, phone_number);
|
||||
}
|
||||
"wechat" => {
|
||||
@@ -490,6 +513,7 @@ fn export_auth_store_snapshot_from_tables_tx(
|
||||
}
|
||||
|
||||
let mut next_user_id = 1_u64;
|
||||
let mut phone_to_user_id = std::collections::HashMap::new();
|
||||
let mut users_by_username = std::collections::HashMap::new();
|
||||
for user in users {
|
||||
if let Some(numeric_id) = user
|
||||
@@ -499,6 +523,13 @@ fn export_auth_store_snapshot_from_tables_tx(
|
||||
{
|
||||
next_user_id = next_user_id.max(numeric_id.saturating_add(1));
|
||||
}
|
||||
let phone_number = user
|
||||
.phone_number_e164
|
||||
.clone()
|
||||
.or_else(|| phone_identity_by_user_id.remove(&user.user_id));
|
||||
if let Some(phone_number) = phone_number.clone() {
|
||||
phone_to_user_id.insert(phone_number, user.user_id.clone());
|
||||
}
|
||||
let auth_user = AuthUserSnapshot {
|
||||
id: user.user_id.clone(),
|
||||
public_user_code: user.public_user_code,
|
||||
@@ -519,9 +550,7 @@ fn export_auth_store_snapshot_from_tables_tx(
|
||||
user: auth_user,
|
||||
password_hash: user.password_hash,
|
||||
password_login_enabled: user.password_login_enabled,
|
||||
phone_number: user
|
||||
.phone_number_e164
|
||||
.or_else(|| phone_identity_by_user_id.remove(&user.user_id)),
|
||||
phone_number,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -554,7 +583,7 @@ fn export_auth_store_snapshot_from_tables_tx(
|
||||
);
|
||||
}
|
||||
|
||||
let snapshot = PersistentAuthStoreSnapshot {
|
||||
Ok(PersistentAuthStoreSnapshot {
|
||||
next_user_id,
|
||||
users_by_username,
|
||||
phone_to_user_id,
|
||||
@@ -562,16 +591,6 @@ fn export_auth_store_snapshot_from_tables_tx(
|
||||
session_id_by_refresh_token_hash,
|
||||
wechat_identity_by_provider_uid,
|
||||
user_id_by_provider_union_id,
|
||||
};
|
||||
if let Some(updated_at_micros) = updated_at_micros {
|
||||
upsert_auth_store_snapshot_rows(ctx, &snapshot, updated_at_micros)?;
|
||||
}
|
||||
let snapshot_json = serde_json::to_string_pretty(&snapshot)
|
||||
.map_err(|error| format!("序列化认证快照失败:{error}"))?;
|
||||
|
||||
Ok(AuthStoreSnapshotRecord {
|
||||
snapshot_json: Some(snapshot_json),
|
||||
updated_at_micros,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -710,4 +729,47 @@ mod tests {
|
||||
auth_store_snapshot_row_ids(&after)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auth_export_ignores_phone_identity_without_user_account() {
|
||||
let live_user = UserAccount {
|
||||
user_id: "user_live".to_string(),
|
||||
public_user_code: "SY-00000001".to_string(),
|
||||
username: "phone_live".to_string(),
|
||||
display_name: "测试玩家".to_string(),
|
||||
avatar_url: None,
|
||||
phone_number_masked: Some("138****8000".to_string()),
|
||||
phone_number_e164: Some("+8613800008000".to_string()),
|
||||
login_method: "phone".to_string(),
|
||||
binding_status: "active".to_string(),
|
||||
wechat_bound: false,
|
||||
password_hash: "hash-live".to_string(),
|
||||
password_login_enabled: true,
|
||||
token_version: 1,
|
||||
user_tags: Some(vec![]),
|
||||
};
|
||||
let orphan_identity = AuthIdentity {
|
||||
identity_id: "authi_phone_orphan".to_string(),
|
||||
user_id: "user_deleted".to_string(),
|
||||
provider: "phone".to_string(),
|
||||
provider_uid: "+8613900009999".to_string(),
|
||||
provider_union_id: None,
|
||||
phone_e164: Some("+8613900009999".to_string()),
|
||||
display_name: None,
|
||||
avatar_url: None,
|
||||
};
|
||||
|
||||
let snapshot =
|
||||
build_auth_store_snapshot_from_rows(vec![live_user], vec![orphan_identity], vec![])
|
||||
.expect("auth rows should export");
|
||||
|
||||
assert_eq!(
|
||||
snapshot.phone_to_user_id,
|
||||
std::collections::HashMap::from([(
|
||||
"+8613800008000".to_string(),
|
||||
"user_live".to_string()
|
||||
)])
|
||||
);
|
||||
assert!(!snapshot.phone_to_user_id.contains_key("+8613900009999"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user