fix(health): FHIR converter 身份证号脱敏处理
This commit is contained in:
@@ -32,9 +32,15 @@ pub fn patient_to_fhir(p: &patient::Model) -> serde_json::Value {
|
||||
}
|
||||
|
||||
if let Some(ref id_number) = p.id_number {
|
||||
// 加密密文(v1| 前缀)不输出,明文做脱敏处理
|
||||
let display_value = if id_number.starts_with("v1|") {
|
||||
"[REDACTED]".to_string()
|
||||
} else {
|
||||
mask_sensitive(id_number)
|
||||
};
|
||||
result["identifier"] = serde_json::json!([{
|
||||
"system": "urn:oid:2.16.156.10011.1.3",
|
||||
"value": id_number,
|
||||
"value": display_value,
|
||||
}]);
|
||||
}
|
||||
|
||||
@@ -332,6 +338,15 @@ pub fn follow_up_to_fhir(t: &follow_up_task::Model) -> serde_json::Value {
|
||||
})
|
||||
}
|
||||
|
||||
/// 对敏感字符串做脱敏:保留前 1 位和后 4 位,中间用 * 替代
|
||||
fn mask_sensitive(s: &str) -> String {
|
||||
if s.len() <= 5 {
|
||||
"*".repeat(s.len())
|
||||
} else {
|
||||
format!("{}{}{}", &s[..1], "*".repeat(s.len() - 5), &s[s.len() - 4..])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -370,7 +385,47 @@ mod tests {
|
||||
assert_eq!(fhir["id"], "00000000-0000-0000-0000-000000000001");
|
||||
assert_eq!(fhir["gender"], "male");
|
||||
assert_eq!(fhir["birthDate"], "1968-05-15");
|
||||
assert_eq!(fhir["identifier"][0]["value"], "110101196805150001");
|
||||
assert_eq!(fhir["identifier"][0]["value"], "1*************0001");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_patient_to_fhir_encrypted_id_number_redacted() {
|
||||
let p = patient::Model {
|
||||
id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(),
|
||||
tenant_id: uuid::Uuid::now_v7(),
|
||||
user_id: None,
|
||||
name: "测试".into(),
|
||||
gender: None,
|
||||
birth_date: None,
|
||||
blood_type: None,
|
||||
id_number: Some("v1|encrypted_payload_here".into()),
|
||||
id_number_hash: None,
|
||||
allergy_history: None,
|
||||
medical_history_summary: None,
|
||||
emergency_contact_name: None,
|
||||
emergency_contact_phone: None,
|
||||
emergency_contact_phone_hash: None,
|
||||
key_version: None,
|
||||
status: "active".into(),
|
||||
verification_status: "pending".into(),
|
||||
source: None,
|
||||
notes: None,
|
||||
created_at: chrono::Utc::now(),
|
||||
updated_at: chrono::Utc::now(),
|
||||
created_by: None,
|
||||
updated_by: None,
|
||||
deleted_at: None,
|
||||
version: 1,
|
||||
};
|
||||
let fhir = patient_to_fhir(&p);
|
||||
assert_eq!(fhir["identifier"][0]["value"], "[REDACTED]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mask_sensitive() {
|
||||
assert_eq!(mask_sensitive("110101196805150001"), "1*************0001");
|
||||
assert_eq!(mask_sensitive("12345"), "*****");
|
||||
assert_eq!(mask_sensitive("123456"), "1*3456");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user