diff --git a/crates/erp-health/src/dto/appointment_dto.rs b/crates/erp-health/src/dto/appointment_dto.rs index 451e7b2..f3b2f5c 100644 --- a/crates/erp-health/src/dto/appointment_dto.rs +++ b/crates/erp-health/src/dto/appointment_dto.rs @@ -1,4 +1,5 @@ use chrono::{NaiveDate, NaiveTime}; +use erp_core::sanitize::sanitize_option; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use uuid::Uuid; @@ -14,12 +15,24 @@ pub struct CreateAppointmentReq { pub notes: Option, } +impl CreateAppointmentReq { + pub fn sanitize(&mut self) { + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct UpdateAppointmentStatusReq { pub status: String, pub cancel_reason: Option, } +impl UpdateAppointmentStatusReq { + pub fn sanitize(&mut self) { + self.cancel_reason = sanitize_option(self.cancel_reason.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct AppointmentResp { pub id: Uuid, diff --git a/crates/erp-health/src/dto/consultation_dto.rs b/crates/erp-health/src/dto/consultation_dto.rs index cf04b3b..a2ce9df 100644 --- a/crates/erp-health/src/dto/consultation_dto.rs +++ b/crates/erp-health/src/dto/consultation_dto.rs @@ -1,3 +1,4 @@ +use erp_core::sanitize::sanitize_string; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use uuid::Uuid; @@ -36,6 +37,12 @@ pub struct CreateMessageReq { pub content: String, } +impl CreateMessageReq { + pub fn sanitize(&mut self) { + self.content = sanitize_string(&self.content); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct CreateSessionReq { pub patient_id: Uuid, diff --git a/crates/erp-health/src/dto/doctor_dto.rs b/crates/erp-health/src/dto/doctor_dto.rs index 40168eb..cab13b6 100644 --- a/crates/erp-health/src/dto/doctor_dto.rs +++ b/crates/erp-health/src/dto/doctor_dto.rs @@ -1,3 +1,4 @@ +use erp_core::sanitize::{sanitize_option, sanitize_string, strip_html_tags}; use serde::{Deserialize, Serialize}; use utoipa::{IntoParams, ToSchema}; use uuid::Uuid; @@ -22,6 +23,16 @@ pub struct CreateDoctorReq { pub bio: Option, } +impl CreateDoctorReq { + pub fn sanitize(&mut self) { + self.name = sanitize_string(&self.name); + self.department = sanitize_option(self.department.take()); + self.title = sanitize_option(self.title.take()); + self.specialty = sanitize_option(self.specialty.take()); + self.bio = sanitize_option(self.bio.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct UpdateDoctorReq { pub name: Option, @@ -33,6 +44,18 @@ pub struct UpdateDoctorReq { pub online_status: Option, } +impl UpdateDoctorReq { + pub fn sanitize(&mut self) { + if let Some(ref mut v) = self.name { + *v = strip_html_tags(v); + } + self.department = sanitize_option(self.department.take()); + self.title = sanitize_option(self.title.take()); + self.specialty = sanitize_option(self.specialty.take()); + self.bio = sanitize_option(self.bio.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct DoctorResp { pub id: Uuid, diff --git a/crates/erp-health/src/dto/follow_up_dto.rs b/crates/erp-health/src/dto/follow_up_dto.rs index f8eedbb..d1e6ce0 100644 --- a/crates/erp-health/src/dto/follow_up_dto.rs +++ b/crates/erp-health/src/dto/follow_up_dto.rs @@ -1,4 +1,5 @@ use chrono::NaiveDate; +use erp_core::sanitize::sanitize_option; use serde::{Deserialize, Serialize}; use utoipa::{IntoParams, ToSchema}; use uuid::Uuid; @@ -22,6 +23,12 @@ pub struct CreateFollowUpTaskReq { pub related_appointment_id: Option, } +impl CreateFollowUpTaskReq { + pub fn sanitize(&mut self) { + self.content_template = sanitize_option(self.content_template.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct UpdateFollowUpTaskReq { pub assigned_to: Option, @@ -31,6 +38,12 @@ pub struct UpdateFollowUpTaskReq { pub status: Option, } +impl UpdateFollowUpTaskReq { + pub fn sanitize(&mut self) { + self.content_template = sanitize_option(self.content_template.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct FollowUpTaskResp { pub id: Uuid, @@ -65,6 +78,13 @@ pub struct CreateFollowUpRecordReq { pub next_follow_up_date: Option, } +impl CreateFollowUpRecordReq { + pub fn sanitize(&mut self) { + self.patient_condition = sanitize_option(self.patient_condition.take()); + self.medical_advice = sanitize_option(self.medical_advice.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct FollowUpRecordResp { pub id: Uuid, diff --git a/crates/erp-health/src/dto/health_data_dto.rs b/crates/erp-health/src/dto/health_data_dto.rs index 964c99d..ee63851 100644 --- a/crates/erp-health/src/dto/health_data_dto.rs +++ b/crates/erp-health/src/dto/health_data_dto.rs @@ -1,4 +1,5 @@ use chrono::NaiveDate; +use erp_core::sanitize::sanitize_option; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use uuid::Uuid; @@ -21,6 +22,12 @@ pub struct CreateVitalSignsReq { pub notes: Option, } +impl CreateVitalSignsReq { + pub fn sanitize(&mut self) { + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct UpdateVitalSignsReq { pub record_date: Option, @@ -36,6 +43,12 @@ pub struct UpdateVitalSignsReq { pub notes: Option, } +impl UpdateVitalSignsReq { + pub fn sanitize(&mut self) { + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct VitalSignsResp { pub id: Uuid, @@ -65,6 +78,12 @@ pub struct CreateLabReportReq { pub doctor_interpretation: Option, } +impl CreateLabReportReq { + pub fn sanitize(&mut self) { + self.doctor_interpretation = sanitize_option(self.doctor_interpretation.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct UpdateLabReportReq { pub report_date: Option, @@ -74,6 +93,12 @@ pub struct UpdateLabReportReq { pub doctor_interpretation: Option, } +impl UpdateLabReportReq { + pub fn sanitize(&mut self) { + self.doctor_interpretation = sanitize_option(self.doctor_interpretation.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct LabReportResp { pub id: Uuid, @@ -98,6 +123,14 @@ pub struct CreateHealthRecordReq { pub notes: Option, } +impl CreateHealthRecordReq { + pub fn sanitize(&mut self) { + self.source = sanitize_option(self.source.take()); + self.overall_assessment = sanitize_option(self.overall_assessment.take()); + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct UpdateHealthRecordReq { pub record_type: Option, @@ -108,6 +141,14 @@ pub struct UpdateHealthRecordReq { pub notes: Option, } +impl UpdateHealthRecordReq { + pub fn sanitize(&mut self) { + self.source = sanitize_option(self.source.take()); + self.overall_assessment = sanitize_option(self.overall_assessment.take()); + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct HealthRecordResp { pub id: Uuid, diff --git a/crates/erp-health/src/dto/patient_dto.rs b/crates/erp-health/src/dto/patient_dto.rs index 081d5b9..af80885 100644 --- a/crates/erp-health/src/dto/patient_dto.rs +++ b/crates/erp-health/src/dto/patient_dto.rs @@ -1,4 +1,5 @@ use chrono::NaiveDate; +use erp_core::sanitize::{sanitize_option, sanitize_string, strip_html_tags}; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use uuid::Uuid; @@ -18,6 +19,19 @@ pub struct CreatePatientReq { pub notes: Option, } +impl CreatePatientReq { + pub fn sanitize(&mut self) { + self.name = sanitize_string(&self.name); + self.id_number = sanitize_option(self.id_number.take()); + self.allergy_history = sanitize_option(self.allergy_history.take()); + self.medical_history_summary = sanitize_option(self.medical_history_summary.take()); + self.emergency_contact_name = sanitize_option(self.emergency_contact_name.take()); + self.emergency_contact_phone = sanitize_option(self.emergency_contact_phone.take()); + self.source = sanitize_option(self.source.take()); + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct UpdatePatientReq { pub name: Option, @@ -35,6 +49,21 @@ pub struct UpdatePatientReq { pub verification_status: Option, } +impl UpdatePatientReq { + pub fn sanitize(&mut self) { + if let Some(ref mut v) = self.name { + *v = strip_html_tags(v); + } + self.id_number = sanitize_option(self.id_number.take()); + self.allergy_history = sanitize_option(self.allergy_history.take()); + self.medical_history_summary = sanitize_option(self.medical_history_summary.take()); + self.emergency_contact_name = sanitize_option(self.emergency_contact_name.take()); + self.emergency_contact_phone = sanitize_option(self.emergency_contact_phone.take()); + self.source = sanitize_option(self.source.take()); + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct PatientResp { pub id: Uuid, @@ -66,6 +95,14 @@ pub struct FamilyMemberReq { pub notes: Option, } +impl FamilyMemberReq { + pub fn sanitize(&mut self) { + self.name = sanitize_string(&self.name); + self.phone = sanitize_option(self.phone.take()); + self.notes = sanitize_option(self.notes.take()); + } +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct FamilyMemberResp { pub id: Uuid, diff --git a/crates/erp-health/src/handler/appointment_handler.rs b/crates/erp-health/src/handler/appointment_handler.rs index 4b68193..dd0dbc5 100644 --- a/crates/erp-health/src/handler/appointment_handler.rs +++ b/crates/erp-health/src/handler/appointment_handler.rs @@ -81,6 +81,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.appointment.manage")?; + let mut req = req; + req.sanitize(); let result = appointment_service::create_appointment( &state, ctx.tenant_id, Some(ctx.user_id), req, ) @@ -113,10 +115,11 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.appointment.manage")?; - let update_req = UpdateAppointmentStatusReq { + let mut update_req = UpdateAppointmentStatusReq { status: req.status, cancel_reason: req.cancel_reason, }; + update_req.sanitize(); let result = appointment_service::update_appointment_status( &state, ctx.tenant_id, id, Some(ctx.user_id), update_req, req.version, ) diff --git a/crates/erp-health/src/handler/consultation_handler.rs b/crates/erp-health/src/handler/consultation_handler.rs index c897010..0b010b8 100644 --- a/crates/erp-health/src/handler/consultation_handler.rs +++ b/crates/erp-health/src/handler/consultation_handler.rs @@ -131,13 +131,14 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.consultation.manage")?; - let msg_req = CreateMessageReq { + let mut msg_req = CreateMessageReq { session_id: req.session_id, sender_id: ctx.user_id, sender_role: "doctor".to_string(), content_type: req.content_type, content: req.content, }; + msg_req.sanitize(); let result = consultation_service::create_message( &state, ctx.tenant_id, Some(ctx.user_id), msg_req, ) diff --git a/crates/erp-health/src/handler/doctor_handler.rs b/crates/erp-health/src/handler/doctor_handler.rs index 9550297..1bda341 100644 --- a/crates/erp-health/src/handler/doctor_handler.rs +++ b/crates/erp-health/src/handler/doctor_handler.rs @@ -62,6 +62,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.doctor.manage")?; + let mut req = req; + req.sanitize(); let result = doctor_service::create_doctor( &state, ctx.tenant_id, Some(ctx.user_id), req, ) @@ -94,8 +96,10 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.doctor.manage")?; + let mut data = req.data; + data.sanitize(); let result = doctor_service::update_doctor( - &state, ctx.tenant_id, id, Some(ctx.user_id), req.data, req.version, + &state, ctx.tenant_id, id, Some(ctx.user_id), data, req.version, ) .await?; Ok(Json(ApiResponse::ok(result))) diff --git a/crates/erp-health/src/handler/follow_up_handler.rs b/crates/erp-health/src/handler/follow_up_handler.rs index 4fc0813..f697e84 100644 --- a/crates/erp-health/src/handler/follow_up_handler.rs +++ b/crates/erp-health/src/handler/follow_up_handler.rs @@ -85,6 +85,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.follow-up.manage")?; + let mut req = req; + req.sanitize(); let result = follow_up_service::create_task( &state, ctx.tenant_id, Some(ctx.user_id), req, ) @@ -103,8 +105,10 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.follow-up.manage")?; + let mut data = req.data; + data.sanitize(); let result = follow_up_service::update_task( - &state, ctx.tenant_id, id, Some(ctx.user_id), req.data, req.version, + &state, ctx.tenant_id, id, Some(ctx.user_id), data, req.version, ) .await?; Ok(Json(ApiResponse::ok(result))) @@ -139,6 +143,8 @@ where if req.task_id != task_id { return Err(AppError::Validation("路径中的 task_id 与请求体不一致".to_string())); } + let mut req = req; + req.sanitize(); let result = follow_up_service::create_record( &state, ctx.tenant_id, Some(ctx.user_id), req, ) diff --git a/crates/erp-health/src/handler/health_data_handler.rs b/crates/erp-health/src/handler/health_data_handler.rs index 3aa0ae4..08284e6 100644 --- a/crates/erp-health/src/handler/health_data_handler.rs +++ b/crates/erp-health/src/handler/health_data_handler.rs @@ -80,6 +80,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.health-data.manage")?; + let mut req = req; + req.sanitize(); let result = health_data_service::create_vital_signs( &state, ctx.tenant_id, patient_id, Some(ctx.user_id), req, ) @@ -98,8 +100,10 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.health-data.manage")?; + let mut data = req.data; + data.sanitize(); let result = health_data_service::update_vital_signs( - &state, ctx.tenant_id, patient_id, vid, Some(ctx.user_id), req.data, req.version, + &state, ctx.tenant_id, patient_id, vid, Some(ctx.user_id), data, req.version, ) .await?; Ok(Json(ApiResponse::ok(result))) @@ -155,6 +159,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.health-data.manage")?; + let mut req = req; + req.sanitize(); let result = health_data_service::create_lab_report( &state, ctx.tenant_id, patient_id, Some(ctx.user_id), req, ) @@ -173,8 +179,10 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.health-data.manage")?; + let mut data = req.data; + data.sanitize(); let result = health_data_service::update_lab_report( - &state, ctx.tenant_id, _patient_id, rid, Some(ctx.user_id), req.data, req.version, + &state, ctx.tenant_id, _patient_id, rid, Some(ctx.user_id), data, req.version, ) .await?; Ok(Json(ApiResponse::ok(result))) @@ -230,6 +238,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.health-data.manage")?; + let mut req = req; + req.sanitize(); let result = health_data_service::create_health_record( &state, ctx.tenant_id, patient_id, Some(ctx.user_id), req, ) @@ -248,8 +258,10 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.health-data.manage")?; + let mut data = req.data; + data.sanitize(); let result = health_data_service::update_health_record( - &state, ctx.tenant_id, patient_id, rid, Some(ctx.user_id), req.data, req.version, + &state, ctx.tenant_id, patient_id, rid, Some(ctx.user_id), data, req.version, ) .await?; Ok(Json(ApiResponse::ok(result))) diff --git a/crates/erp-health/src/handler/patient_handler.rs b/crates/erp-health/src/handler/patient_handler.rs index d3bd3af..3117782 100644 --- a/crates/erp-health/src/handler/patient_handler.rs +++ b/crates/erp-health/src/handler/patient_handler.rs @@ -64,6 +64,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; + let mut req = req; + req.sanitize(); let result = patient_service::create_patient( &state, ctx.tenant_id, Some(ctx.user_id), req, ) @@ -97,7 +99,7 @@ where { require_permission(&ctx, "health.patient.manage")?; let version = req.version; - let update = UpdatePatientReq { + let mut update = UpdatePatientReq { name: req.name, gender: req.gender, birth_date: req.birth_date, @@ -112,6 +114,7 @@ where status: req.status, verification_status: req.verification_status, }; + update.sanitize(); let result = patient_service::update_patient( &state, ctx.tenant_id, id, Some(ctx.user_id), update, version, ) @@ -188,6 +191,8 @@ where S: Clone + Send + Sync + 'static, { require_permission(&ctx, "health.patient.manage")?; + let mut req = req; + req.sanitize(); let result = patient_service::create_family_member( &state, ctx.tenant_id, id, Some(ctx.user_id), req, ) @@ -207,13 +212,14 @@ where { require_permission(&ctx, "health.patient.manage")?; let version = req.version; - let update = FamilyMemberReq { + let mut update = FamilyMemberReq { name: req.name, relationship: req.relationship, phone: req.phone, birth_date: req.birth_date, notes: req.notes, }; + update.sanitize(); let result = patient_service::update_family_member( &state, ctx.tenant_id, _patient_id, member_id, Some(ctx.user_id), update, version, )