fix(health): FHIR allowed_patient_ids=None 拒绝所有访问

This commit is contained in:
iven
2026-05-05 23:42:29 +08:00
parent 4f84c94a42
commit 741aaf0e40

View File

@@ -70,14 +70,19 @@ pub struct FhirSearchParams {
/// 检查单个 patient_id 是否在 OAuth 客户端的允许范围内
fn enforce_patient_scope(fhir_ctx: &FhirAuthContext, patient_id: Uuid) -> Result<(), AppError> {
if let Some(ref allowed) = fhir_ctx.allowed_patient_ids {
if !allowed.iter().any(|id| id == &patient_id.to_string()) {
tracing::warn!(
client_id = %fhir_ctx.client_id,
requested_patient = %patient_id,
"FHIR 客户端尝试访问授权范围外的患者"
);
return Err(AppError::Forbidden("Access denied: patient not in allowed scope".into()));
match &fhir_ctx.allowed_patient_ids {
Some(allowed) if !allowed.is_empty() => {
if !allowed.iter().any(|id| id == &patient_id.to_string()) {
tracing::warn!(
client_id = %fhir_ctx.client_id,
requested_patient = %patient_id,
"FHIR 客户端尝试访问授权范围外的患者"
);
return Err(AppError::Forbidden("Access denied: patient not in allowed scope".into()));
}
}
_ => {
return Err(AppError::Forbidden("OAuth client has no patient access configured".into()));
}
}
Ok(())
@@ -751,3 +756,59 @@ pub async fn patient_everything(
"entry": entries,
})))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::oauth::middleware::FhirAuthContext;
fn default_fhir_ctx() -> FhirAuthContext {
FhirAuthContext {
client_id: Uuid::now_v7(),
tenant_id: Uuid::now_v7(),
scopes: vec!["patient/*.read".to_string()],
allowed_patient_ids: None,
}
}
#[test]
fn test_enforce_patient_scope_none_is_denied() {
let fhir_ctx = FhirAuthContext {
allowed_patient_ids: None,
..default_fhir_ctx()
};
let result = enforce_patient_scope(&fhir_ctx, Uuid::now_v7());
assert!(result.is_err(), "None should deny all access");
}
#[test]
fn test_enforce_patient_scope_empty_vec_is_denied() {
let fhir_ctx = FhirAuthContext {
allowed_patient_ids: Some(vec![]),
..default_fhir_ctx()
};
let result = enforce_patient_scope(&fhir_ctx, Uuid::now_v7());
assert!(result.is_err(), "Empty list should deny all access");
}
#[test]
fn test_enforce_patient_scope_allowed_access() {
let patient_id = Uuid::now_v7();
let fhir_ctx = FhirAuthContext {
allowed_patient_ids: Some(vec![patient_id.to_string()]),
..default_fhir_ctx()
};
let result = enforce_patient_scope(&fhir_ctx, patient_id);
assert!(result.is_ok(), "Patient in allowed list should succeed");
}
#[test]
fn test_enforce_patient_scope_wrong_patient_denied() {
let fhir_ctx = FhirAuthContext {
allowed_patient_ids: Some(vec![Uuid::now_v7().to_string()]),
..default_fhir_ctx()
};
let result = enforce_patient_scope(&fhir_ctx, Uuid::now_v7());
assert!(result.is_err(), "Patient not in allowed list should be denied");
}
}