OP-886 Anonymize a patient's personal data (GDPR right to erasure) - #1641
OP-886 Anonymize a patient's personal data (GDPR right to erasure)#1641giuseppesorge wants to merge 8 commits into
Conversation
Add a PAT_ANONYMIZED flag to OH_PATIENT and PatientBrowserManager.anonymizePatient(), which irreversibly overwrites the personal identification data (name, surname, mother/ father name, address, city, telephone, tax code) with sentinel values, removes the profile photo and every linked DICOM series, and marks the record as anonymized. The clinical records are preserved for statistical use. Re-anonymizing a patient is rejected. DICOM removal is best-effort so a missing DICOM configuration does not block the erasure.
Register the patient.anonymize permission (used by the REST API and the GUI to gate the anonymization) and grant it to the admin group. P_ID_A/GP_ID are auto-increment, so the inserts assign no explicit id and link the grant with a sub-select — avoiding id clashes with other migrations. Verified on a demo DB.
The GUI gates the Anonymize button via MainMenu.checkUserGrants (which reads the user's menu grants, not OH_PERMISSIONS), so register btnpatientanonymize as a menu item under the Admission/Patient menu and grant it to the admin group. Verified on a demo DB.
The photo was only nulled when PATIENTPHOTOSTORAGE is DB; with filesystem storage the DB relation was left in place, which left a dangling profile-photo reference on the record and broke later mapping (LazyInitializationException when the anonymized patient's admissions were loaded via the API). Now always null the OneToOne relation (GDPR erasure) and additionally delete the file when photos are on the filesystem. Also broaden the best-effort DICOM cleanup to swallow any failure (the DICOM module is unavailable outside the GUI context).
Keep the birth year (needed for age statistics) but drop the exact day and month, which would otherwise remain a re-identifying detail.
…vion # Conflicts: # sql/step_04_all_following_steps.sql
Add PAT_ANONYMIZED (default 0) to the oh_patient demo table and add the anonymize permission and menu entry (oh_permissions, oh_grouppermission, oh_menuitem, oh_groupmenu), regenerated via a MariaDB round-trip of the migration, so a clean demo DB matches the migrated schema.
|
@dbmalkovsky — good call, thanks. Synced |
1 similar comment
|
@dbmalkovsky — good call, thanks. Synced |
…vion # Conflicts: # sql/load_demo_data.sql # sql/step_04_all_following_steps.sql
|
Merged It is resolved with a three-way merge on each row's list of values (merge base / this branch / Two checks afterwards: every |
Implements the CORE part of OP-886 – GDPR 1/4 Oblivion (Art. 17, right to erasure): irreversibly anonymize a patient's personal identification data while keeping the clinical records for statistical use.
Changes
Patient: newPAT_ANONYMIZEDflag (+ getter/setter).PatientIoOperations.anonymizePatient(Patient): overwrites the identifying fields with sentinels (first/second/mother/father name →ANONYMIZED, address/city/telephone → empty, tax code →DELETED), always detaches the profile photo (and deletes the filesystem copy when applicable), sets the flag and saves.PatientBrowserManager.anonymizePatient(int): not-found / already-anonymized guards, best-effort removal of every linked DICOM series, then delegates the erasure.sql/step_aXXX_patient_anonymized.sql: addsPAT_ANONYMIZED, registers thepatient.anonymizepermission (REST API) + thebtnpatientanonymizemenu grant (GUI), both granted toadmin.testMgrAnonymizePatient,testMgrAnonymizePatientAlreadyAnonymizedThrows(full patient suite green).Notes
Auditablecolumns, no extra audit table.step_aXXXplaceholder — to be renumbered at merge.Related PRs (merge order: core first)
Verification
Migration applied and the manager exercised on a MariaDB 10.6 demo DB; anonymization overwrites the PII, keeps birth date/sex and all clinical records, and re-anonymizing is rejected.