endoreg-db 0.8.8.0__py3-none-any.whl → 0.8.9.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/data/__init__.py +22 -8
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +0 -1
- endoreg_db/data/examination/examinations/data.yaml +114 -14
- endoreg_db/data/examination/time-type/data.yaml +0 -3
- endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
- endoreg_db/data/finding/00_generic.yaml +35 -0
- endoreg_db/data/finding/00_generic_complication.yaml +9 -0
- endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
- endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
- endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
- endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
- endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
- endoreg_db/data/finding_classification/00_generic.yaml +44 -0
- endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
- endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
- endoreg_db/data/finding_classification/{colonoscopy_bowel_preparation.yaml → 02_colonoscopy_baseline.yaml} +35 -20
- endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
- endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
- endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
- endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
- endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
- endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
- endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
- endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
- endoreg_db/data/{_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml → finding_classification_choice/02_colonoscopy_generic.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
- endoreg_db/data/{_examples/finding_classification_choice/colonoscopy_location.yaml → finding_classification_choice/02_colonoscopy_location.yaml} +23 -4
- endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
- endoreg_db/data/{_examples/finding_classification_choice/colon_lesion_paris.yaml → finding_classification_choice/02_colonoscopy_polyp_morphology.yaml} +26 -8
- endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
- endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
- endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
- endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
- endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
- endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
- endoreg_db/data/finding_type/data.yaml +8 -12
- endoreg_db/data/requirement/01_patient_data.yaml +93 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +0 -2
- endoreg_db/data/requirement_set/90_coloreg.yaml +20 -8
- endoreg_db/exceptions.py +0 -1
- endoreg_db/forms/examination_form.py +1 -1
- endoreg_db/helpers/data_loader.py +124 -52
- endoreg_db/helpers/default_objects.py +116 -81
- endoreg_db/import_files/__init__.py +27 -0
- endoreg_db/import_files/context/__init__.py +7 -0
- endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
- endoreg_db/import_files/context/ensure_center.py +17 -0
- endoreg_db/import_files/context/file_lock.py +66 -0
- endoreg_db/import_files/context/import_context.py +43 -0
- endoreg_db/import_files/context/validate_directories.py +56 -0
- endoreg_db/import_files/file_storage/__init__.py +15 -0
- endoreg_db/import_files/file_storage/create_report_file.py +76 -0
- endoreg_db/import_files/file_storage/create_video_file.py +75 -0
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
- endoreg_db/import_files/file_storage/state_management.py +496 -0
- endoreg_db/import_files/file_storage/storage.py +36 -0
- endoreg_db/import_files/import_service.md +26 -0
- endoreg_db/import_files/processing/__init__.py +11 -0
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
- endoreg_db/import_files/pseudonymization/fake.py +52 -0
- endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
- endoreg_db/import_files/pseudonymization/pseudonymize.py +0 -0
- endoreg_db/import_files/report_import_service.py +141 -0
- endoreg_db/import_files/video_import_service.py +150 -0
- endoreg_db/management/commands/import_report.py +130 -65
- endoreg_db/management/commands/import_video_with_classification.py +1 -1
- endoreg_db/management/commands/load_ai_model_data.py +5 -5
- endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
- endoreg_db/management/commands/load_base_db_data.py +5 -134
- endoreg_db/management/commands/load_contraindication_data.py +14 -16
- endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
- endoreg_db/management/commands/load_disease_classification_data.py +15 -18
- endoreg_db/management/commands/load_disease_data.py +25 -28
- endoreg_db/management/commands/load_endoscope_data.py +20 -27
- endoreg_db/management/commands/load_event_data.py +14 -16
- endoreg_db/management/commands/load_examination_data.py +31 -44
- endoreg_db/management/commands/load_examination_indication_data.py +20 -21
- endoreg_db/management/commands/load_finding_data.py +52 -80
- endoreg_db/management/commands/load_information_source.py +21 -23
- endoreg_db/management/commands/load_lab_value_data.py +17 -26
- endoreg_db/management/commands/load_medication_data.py +13 -12
- endoreg_db/management/commands/load_organ_data.py +15 -19
- endoreg_db/management/commands/load_pdf_type_data.py +19 -18
- endoreg_db/management/commands/load_profession_data.py +14 -17
- endoreg_db/management/commands/load_qualification_data.py +20 -23
- endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
- endoreg_db/management/commands/load_requirement_data.py +14 -20
- endoreg_db/management/commands/load_risk_data.py +7 -6
- endoreg_db/management/commands/load_shift_data.py +20 -23
- endoreg_db/management/commands/load_tag_data.py +8 -11
- endoreg_db/management/commands/load_unit_data.py +17 -19
- endoreg_db/management/commands/start_filewatcher.py +46 -37
- endoreg_db/management/commands/validate_video_files.py +1 -5
- endoreg_db/migrations/0001_initial.py +1360 -1812
- endoreg_db/models/administration/person/patient/patient.py +72 -46
- endoreg_db/models/label/__init__.py +2 -2
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +18 -26
- endoreg_db/models/label/label_video_segment/label_video_segment.py +23 -1
- endoreg_db/models/media/pdf/raw_pdf.py +136 -64
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +34 -10
- endoreg_db/models/media/processing_history/__init__.py +5 -0
- endoreg_db/models/media/processing_history/processing_history.py +96 -0
- endoreg_db/models/media/video/create_from_file.py +101 -31
- endoreg_db/models/media/video/video_file.py +125 -105
- endoreg_db/models/media/video/video_file_io.py +31 -26
- endoreg_db/models/medical/contraindication/README.md +1 -0
- endoreg_db/models/medical/examination/examination.py +28 -8
- endoreg_db/models/medical/examination/examination_indication.py +13 -79
- endoreg_db/models/medical/examination/examination_time.py +8 -3
- endoreg_db/models/medical/finding/finding.py +5 -12
- endoreg_db/models/medical/finding/finding_classification.py +18 -37
- endoreg_db/models/medical/finding/finding_intervention.py +7 -9
- endoreg_db/models/medical/hardware/endoscope.py +6 -0
- endoreg_db/models/medical/patient/medication_examples.py +5 -1
- endoreg_db/models/medical/patient/patient_finding.py +1 -1
- endoreg_db/models/metadata/pdf_meta.py +22 -10
- endoreg_db/models/metadata/sensitive_meta.py +3 -0
- endoreg_db/models/metadata/sensitive_meta_logic.py +200 -124
- endoreg_db/models/other/information_source.py +27 -6
- endoreg_db/models/report/__init__.py +0 -0
- endoreg_db/models/report/images.py +0 -0
- endoreg_db/models/report/report.py +6 -0
- endoreg_db/models/requirement/requirement.py +59 -399
- endoreg_db/models/requirement/requirement_operator.py +86 -98
- endoreg_db/models/state/audit_ledger.py +4 -5
- endoreg_db/models/state/raw_pdf.py +69 -30
- endoreg_db/models/state/video.py +65 -49
- endoreg_db/models/upload_job.py +33 -9
- endoreg_db/models/utils.py +27 -23
- endoreg_db/queries/__init__.py +3 -1
- endoreg_db/schemas/examination_evaluation.py +1 -1
- endoreg_db/serializers/__init__.py +2 -8
- endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
- endoreg_db/serializers/meta/__init__.py +1 -6
- endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
- endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
- endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
- endoreg_db/serializers/video/video_file_list.py +65 -34
- endoreg_db/services/__old/pdf_import.py +1487 -0
- endoreg_db/services/__old/video_import.py +1306 -0
- endoreg_db/services/anonymization.py +63 -26
- endoreg_db/services/lookup_service.py +28 -28
- endoreg_db/services/lookup_store.py +2 -2
- endoreg_db/services/pdf_import.py +0 -1480
- endoreg_db/services/report_import.py +10 -0
- endoreg_db/services/video_import.py +6 -1165
- endoreg_db/tasks/upload_tasks.py +79 -70
- endoreg_db/tasks/video_ingest.py +8 -4
- endoreg_db/urls/__init__.py +0 -14
- endoreg_db/urls/ai.py +32 -0
- endoreg_db/urls/media.py +21 -24
- endoreg_db/utils/dataloader.py +87 -57
- endoreg_db/utils/paths.py +110 -46
- endoreg_db/utils/pipelines/Readme.md +1 -1
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
- endoreg_db/utils/video/ffmpeg_wrapper.py +217 -52
- endoreg_db/views/__init__.py +85 -173
- endoreg_db/views/ai/__init__.py +8 -0
- endoreg_db/views/ai/label.py +155 -0
- endoreg_db/views/anonymization/media_management.py +8 -7
- endoreg_db/views/anonymization/overview.py +97 -68
- endoreg_db/views/anonymization/validate.py +25 -21
- endoreg_db/views/media/__init__.py +5 -20
- endoreg_db/views/media/pdf_media.py +109 -65
- endoreg_db/views/media/sensitive_metadata.py +163 -148
- endoreg_db/views/meta/__init__.py +0 -8
- endoreg_db/views/misc/__init__.py +1 -7
- endoreg_db/views/misc/upload_views.py +94 -93
- endoreg_db/views/report/__init__.py +7 -0
- endoreg_db/views/{pdf → report}/reimport.py +45 -24
- endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +40 -32
- endoreg_db/views/requirement/lookup_store.py +22 -90
- endoreg_db/views/video/__init__.py +23 -22
- endoreg_db/views/video/correction.py +201 -172
- endoreg_db/views/video/reimport.py +1 -1
- endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +75 -37
- endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
- endoreg_db/views/video/video_stream.py +7 -8
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/METADATA +2 -2
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/RECORD +217 -335
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/WHEEL +1 -1
- endoreg_db/data/_examples/disease.yaml +0 -55
- endoreg_db/data/_examples/disease_classification.yaml +0 -13
- endoreg_db/data/_examples/disease_classification_choice.yaml +0 -62
- endoreg_db/data/_examples/event.yaml +0 -64
- endoreg_db/data/_examples/examination.yaml +0 -72
- endoreg_db/data/_examples/finding/anatomy_colon.yaml +0 -128
- endoreg_db/data/_examples/finding/colonoscopy.yaml +0 -40
- endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +0 -56
- endoreg_db/data/_examples/finding/complication.yaml +0 -16
- endoreg_db/data/_examples/finding/data.yaml +0 -105
- endoreg_db/data/_examples/finding/examination_setting.yaml +0 -16
- endoreg_db/data/_examples/finding/medication_related.yaml +0 -18
- endoreg_db/data/_examples/finding/outcome.yaml +0 -12
- endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +0 -68
- endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +0 -22
- endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +0 -25
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +0 -68
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +0 -80
- endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +0 -21
- endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +0 -20
- endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +0 -26
- endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +0 -22
- endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +0 -53
- endoreg_db/data/_examples/finding_classification/complication_generic.yaml +0 -25
- endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +0 -40
- endoreg_db/data/_examples/finding_classification/histology_colo.yaml +0 -51
- endoreg_db/data/_examples/finding_classification/intervention_required.yaml +0 -26
- endoreg_db/data/_examples/finding_classification/medication_related.yaml +0 -23
- endoreg_db/data/_examples/finding_classification/visualized.yaml +0 -33
- endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +0 -78
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +0 -17
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +0 -14
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +0 -82
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +0 -15
- endoreg_db/data/_examples/finding_classification_choice/histology.yaml +0 -24
- endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +0 -20
- endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +0 -19
- endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +0 -11
- endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +0 -48
- endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +0 -43
- endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
- endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +0 -128
- endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +0 -32
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +0 -9
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +0 -36
- endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +0 -15
- endoreg_db/data/_examples/finding_type/data.yaml +0 -43
- endoreg_db/data/_examples/requirement/age.yaml +0 -26
- endoreg_db/data/_examples/requirement/gender.yaml +0 -25
- endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +0 -48
- endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +0 -57
- endoreg_db/data/_examples/requirement_set/endoscopy_bleeding_risk.yaml +0 -52
- endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
- endoreg_db/data/finding/anatomy_colon.yaml +0 -128
- endoreg_db/data/finding/colonoscopy.yaml +0 -40
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
- endoreg_db/data/finding/complication.yaml +0 -16
- endoreg_db/data/finding/data.yaml +0 -105
- endoreg_db/data/finding/examination_setting.yaml +0 -16
- endoreg_db/data/finding/medication_related.yaml +0 -18
- endoreg_db/data/finding/outcome.yaml +0 -12
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -38
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -49
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
- endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
- endoreg_db/data/finding_classification/histology_colo.yaml +0 -43
- endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
- endoreg_db/data/finding_classification/medication_related.yaml +0 -23
- endoreg_db/data/finding_classification/visualized.yaml +0 -33
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
- endoreg_db/data/finding_classification_choice/colon_lesion_paris.yaml +0 -57
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
- endoreg_db/data/finding_classification_choice/colonoscopy_location.yaml +0 -229
- endoreg_db/data/finding_classification_choice/colonoscopy_not_complete_reason.yaml +0 -19
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
- endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
- endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
- endoreg_db/data/requirement/age.yaml +0 -26
- endoreg_db/data/requirement/colonoscopy_baseline_austria.yaml +0 -45
- endoreg_db/data/requirement/disease_cardiovascular.yaml +0 -79
- endoreg_db/data/requirement/disease_classification_choice_cardiovascular.yaml +0 -41
- endoreg_db/data/requirement/disease_hepatology.yaml +0 -12
- endoreg_db/data/requirement/disease_misc.yaml +0 -12
- endoreg_db/data/requirement/disease_renal.yaml +0 -96
- endoreg_db/data/requirement/endoscopy_bleeding_risk.yaml +0 -59
- endoreg_db/data/requirement/event_cardiology.yaml +0 -251
- endoreg_db/data/requirement/event_requirements.yaml +0 -145
- endoreg_db/data/requirement/finding_colon_polyp.yaml +0 -50
- endoreg_db/data/requirement/gender.yaml +0 -25
- endoreg_db/data/requirement/lab_value.yaml +0 -441
- endoreg_db/data/requirement/medication.yaml +0 -93
- endoreg_db/data/requirement_operator/age.yaml +0 -13
- endoreg_db/data/requirement_operator/lab_operators.yaml +0 -129
- endoreg_db/data/requirement_operator/model_operators.yaml +0 -96
- endoreg_db/management/commands/init_default_ai_model.py +0 -112
- endoreg_db/management/commands/reset_celery_schedule.py +0 -9
- endoreg_db/management/commands/validate_video.py +0 -204
- endoreg_db/migrations/0002_requirementset_depends_on.py +0 -18
- endoreg_db/migrations/_old/0001_initial.py +0 -1857
- endoreg_db/migrations/_old/0002_add_video_correction_models.py +0 -52
- endoreg_db/migrations/_old/0003_add_center_display_name.py +0 -30
- endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +0 -68
- endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +0 -77
- endoreg_db/migrations/_old/0005_merge_20251111_1003.py +0 -14
- endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +0 -68
- endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +0 -89
- endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +0 -27
- endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +0 -21
- endoreg_db/renames.yml +0 -8
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
- endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
- endoreg_db/serializers/_old/video.py +0 -71
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
- endoreg_db/serializers/meta/report_meta.py +0 -53
- endoreg_db/serializers/report/__init__.py +0 -9
- endoreg_db/serializers/report/mixins.py +0 -45
- endoreg_db/serializers/report/report.py +0 -105
- endoreg_db/serializers/report/report_list.py +0 -22
- endoreg_db/serializers/report/secure_file_url.py +0 -26
- endoreg_db/services/requirements_object.py +0 -147
- endoreg_db/services/storage_aware_video_processor.py +0 -370
- endoreg_db/urls/files.py +0 -6
- endoreg_db/urls/label_video_segment_validate.py +0 -33
- endoreg_db/urls/label_video_segments.py +0 -46
- endoreg_db/views/label/__init__.py +0 -5
- endoreg_db/views/label/label.py +0 -15
- endoreg_db/views/label_video_segment/__init__.py +0 -16
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
- endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
- endoreg_db/views/label_video_segment/validate.py +0 -226
- endoreg_db/views/media/segments.py +0 -71
- endoreg_db/views/meta/available_files_list.py +0 -146
- endoreg_db/views/meta/report_meta.py +0 -53
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -85
- endoreg_db/views/misc/secure_file_serving_view.py +0 -80
- endoreg_db/views/misc/secure_file_url_view.py +0 -84
- endoreg_db/views/misc/secure_url_validate.py +0 -79
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
- endoreg_db/views/patient_finding_location/__init__.py +0 -5
- endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
- endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
- endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
- endoreg_db/views/pdf/__init__.py +0 -8
- endoreg_db/views/video/segmentation.py +0 -274
- endoreg_db/views/video/task_status.py +0 -49
- endoreg_db/views/video/timeline.py +0 -46
- endoreg_db/views/video/video_analyze.py +0 -52
- /endoreg_db/data/requirement/{colon_polyp_intervention.yaml → old/colon_polyp_intervention.yaml} +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/colonoscopy_baseline_austria.yaml +0 -0
- /endoreg_db/data/requirement/{coloreg_colon_polyp.yaml → old/coloreg_colon_polyp.yaml} +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_cardiovascular.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_classification_choice_cardiovascular.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_hepatology.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_misc.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/disease_renal.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/endoscopy_bleeding_risk.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/event_cardiology.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/event_requirements.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/finding_colon_polyp.yaml +0 -0
- /endoreg_db/{urls/sensitive_meta.py → data/requirement/old/gender.yaml} +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/lab_value.yaml +0 -0
- /endoreg_db/data/{_examples/requirement → requirement/old}/medication.yaml +0 -0
- /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/age.yaml +0 -0
- /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/lab_operators.yaml +0 -0
- /endoreg_db/data/{_examples/requirement_operator → requirement_operator/_old}/model_operators.yaml +0 -0
- /endoreg_db/{views/pdf/pdf_stream_views.py → import_files/pseudonymization/__init__.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{model_evaluators.py → _old/model_evaluators.py} +0 -0
- {endoreg_db-0.8.8.0.dist-info → endoreg_db-0.8.9.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile, VideoFile
|
|
2
|
-
from endoreg_db.utils.permissions import DEBUG_PERMISSIONS
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
|
-
from rest_framework import status
|
|
6
|
-
from rest_framework.response import Response
|
|
7
|
-
from rest_framework.views import APIView
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
class AvailableFilesListView(APIView):
|
|
12
|
-
"""
|
|
13
|
-
API endpoint to list available PDFs and videos for anonymization selection.
|
|
14
|
-
|
|
15
|
-
GET: Returns lists of available PDF and video files with their metadata
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
permission_classes = DEBUG_PERMISSIONS
|
|
19
|
-
|
|
20
|
-
def _validate_pagination_params(self, request):
|
|
21
|
-
"""Validates and returns pagination parameters, raising ValueError on failure."""
|
|
22
|
-
try:
|
|
23
|
-
limit = int(request.query_params.get('limit', 50))
|
|
24
|
-
offset = int(request.query_params.get('offset', 0))
|
|
25
|
-
except (ValueError, TypeError):
|
|
26
|
-
raise ValueError("Invalid 'limit' or 'offset' parameter. Must be integers.")
|
|
27
|
-
|
|
28
|
-
if limit < 0 or offset < 0:
|
|
29
|
-
raise ValueError("'limit' and 'offset' must be non-negative.")
|
|
30
|
-
|
|
31
|
-
if limit > 100:
|
|
32
|
-
logger.warning(f"Client requested limit of {limit}, capping at 100.")
|
|
33
|
-
limit = 100
|
|
34
|
-
|
|
35
|
-
return limit, offset
|
|
36
|
-
|
|
37
|
-
def get(self, request):
|
|
38
|
-
"""
|
|
39
|
-
List available PDF and video files for anonymization selection.
|
|
40
|
-
|
|
41
|
-
Query Parameters:
|
|
42
|
-
- type: Filter by file type ('pdf' or 'video')
|
|
43
|
-
- status: Filter by anonymization status
|
|
44
|
-
- limit: Number of results to return (default 50, max 100)
|
|
45
|
-
- offset: Offset for pagination (default 0)
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
{
|
|
49
|
-
"pdfs": [...],
|
|
50
|
-
"videos": [...],
|
|
51
|
-
"total_pdfs": N,
|
|
52
|
-
"total_videos": N
|
|
53
|
-
}
|
|
54
|
-
"""
|
|
55
|
-
try:
|
|
56
|
-
limit, offset = self._validate_pagination_params(request)
|
|
57
|
-
file_type = request.query_params.get('type', 'all').lower()
|
|
58
|
-
except ValueError as e:
|
|
59
|
-
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
60
|
-
|
|
61
|
-
try:
|
|
62
|
-
response_data = {}
|
|
63
|
-
|
|
64
|
-
# Get PDFs if requested
|
|
65
|
-
if file_type in ['all', 'pdf']:
|
|
66
|
-
pdf_queryset = RawPdfFile.objects.select_related('sensitive_meta').all()
|
|
67
|
-
total_pdfs = pdf_queryset.count()
|
|
68
|
-
paginated_pdfs = pdf_queryset[offset:offset + limit]
|
|
69
|
-
|
|
70
|
-
pdf_list = []
|
|
71
|
-
for pdf in paginated_pdfs:
|
|
72
|
-
# Safely handle missing file attribute
|
|
73
|
-
file_name = 'Unknown'
|
|
74
|
-
file_path = None
|
|
75
|
-
if hasattr(pdf, 'file') and pdf.file:
|
|
76
|
-
file_name = pdf.file.name.split('/')[-1]
|
|
77
|
-
file_path = pdf.file.name
|
|
78
|
-
pdf_data = {
|
|
79
|
-
'id': pdf.id,
|
|
80
|
-
'filename': file_name,
|
|
81
|
-
'file_path': file_path,
|
|
82
|
-
'sensitive_meta_id': pdf.sensitive_meta_id,
|
|
83
|
-
'anonymized_text': getattr(pdf, 'anonymized_text', None),
|
|
84
|
-
'created_at': pdf.date_created if hasattr(pdf, 'created_at') else None,
|
|
85
|
-
'patient_info': None
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
# Add patient info if available
|
|
89
|
-
if pdf.sensitive_meta:
|
|
90
|
-
pdf_data['patient_info'] = {
|
|
91
|
-
'patient_first_name': pdf.sensitive_meta.patient_first_name,
|
|
92
|
-
'patient_last_name': pdf.sensitive_meta.patient_last_name,
|
|
93
|
-
'patient_dob': pdf.sensitive_meta.patient_dob,
|
|
94
|
-
'examination_date': pdf.sensitive_meta.examination_date,
|
|
95
|
-
'center_name': pdf.sensitive_meta.center.name if pdf.sensitive_meta.center else None
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
pdf_list.append(pdf_data)
|
|
99
|
-
|
|
100
|
-
response_data['pdfs'] = pdf_list
|
|
101
|
-
response_data['total_pdfs'] = total_pdfs
|
|
102
|
-
|
|
103
|
-
# Get Videos if requested
|
|
104
|
-
if file_type in ['all', 'video']:
|
|
105
|
-
video_queryset = VideoFile.objects.select_related('sensitive_meta').all()
|
|
106
|
-
total_videos = video_queryset.count()
|
|
107
|
-
paginated_videos = video_queryset[offset:offset + limit]
|
|
108
|
-
|
|
109
|
-
video_list = []
|
|
110
|
-
for video in paginated_videos:
|
|
111
|
-
# Safely handle missing raw_file attribute
|
|
112
|
-
file_name = 'Unknown'
|
|
113
|
-
file_path = None
|
|
114
|
-
if hasattr(video, 'raw_file') and video.raw_file:
|
|
115
|
-
file_name = video.raw_file.name.split('/')[-1]
|
|
116
|
-
file_path = video.raw_file.name
|
|
117
|
-
video_data = {
|
|
118
|
-
'id': video.id,
|
|
119
|
-
'filename': file_name,
|
|
120
|
-
'file_path': file_path,
|
|
121
|
-
'sensitive_meta_id': video.sensitive_meta_id,
|
|
122
|
-
'patient_info': None
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
# Add patient info if available
|
|
126
|
-
if video.sensitive_meta:
|
|
127
|
-
video_data['patient_info'] = {
|
|
128
|
-
'patient_first_name': video.sensitive_meta.patient_first_name,
|
|
129
|
-
'patient_last_name': video.sensitive_meta.patient_last_name,
|
|
130
|
-
'patient_dob': video.sensitive_meta.patient_dob,
|
|
131
|
-
'examination_date': video.sensitive_meta.examination_date,
|
|
132
|
-
'center_name': video.sensitive_meta.center.name if video.sensitive_meta.center else None
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
video_list.append(video_data)
|
|
136
|
-
|
|
137
|
-
response_data['videos'] = video_list
|
|
138
|
-
response_data['total_videos'] = total_videos
|
|
139
|
-
|
|
140
|
-
return Response(response_data)
|
|
141
|
-
except Exception as e:
|
|
142
|
-
logger.error(f"Error listing available files: {e}", exc_info=True)
|
|
143
|
-
return Response(
|
|
144
|
-
{"error": "An unexpected error occurred while fetching files."},
|
|
145
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
146
|
-
)
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile
|
|
2
|
-
|
|
3
|
-
from django.shortcuts import get_object_or_404
|
|
4
|
-
from rest_framework import status
|
|
5
|
-
from rest_framework.response import Response
|
|
6
|
-
from rest_framework.views import APIView
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
import logging
|
|
9
|
-
|
|
10
|
-
logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
class ReportFileMetadataView(APIView):
|
|
13
|
-
"""
|
|
14
|
-
API-Endpunkt für Report-Datei-Metadaten
|
|
15
|
-
GET /api/reports/{report_id}/file-metadata/
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
def get(self, _request, report_id):
|
|
19
|
-
try:
|
|
20
|
-
report = get_object_or_404(RawPdfFile, id=report_id)
|
|
21
|
-
|
|
22
|
-
if not report.file:
|
|
23
|
-
return Response(
|
|
24
|
-
{"error": "Keine Datei für diesen Report verfügbar"},
|
|
25
|
-
status=status.HTTP_404_NOT_FOUND
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
metadata = self._get_file_metadata(report)
|
|
29
|
-
return Response(metadata)
|
|
30
|
-
|
|
31
|
-
except (ValueError, TypeError) as e:
|
|
32
|
-
logger.error("Fehler beim Laden der Datei-Metadaten: %s", str(e))
|
|
33
|
-
return Response(
|
|
34
|
-
{"error": "Metadaten konnten nicht geladen werden"},
|
|
35
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
def _get_file_metadata(self, report):
|
|
39
|
-
"""Sammelt Datei-Metadaten"""
|
|
40
|
-
file_path = Path(report.file.name)
|
|
41
|
-
|
|
42
|
-
try:
|
|
43
|
-
file_size = report.file.size
|
|
44
|
-
except OSError:
|
|
45
|
-
file_size = 0
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
'filename': file_path.name,
|
|
49
|
-
'file_type': file_path.suffix.lower().lstrip('.'),
|
|
50
|
-
'file_size': file_size,
|
|
51
|
-
'upload_date': report.created_at if hasattr(report, 'created_at') else None,
|
|
52
|
-
'last_modified': report.updated_at if hasattr(report, 'updated_at') else None
|
|
53
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import SensitiveMeta
|
|
2
|
-
from endoreg_db.serializers import SensitiveMetaDetailSerializer, SensitiveMetaUpdateSerializer
|
|
3
|
-
|
|
4
|
-
from django.db import transaction
|
|
5
|
-
from django.shortcuts import get_object_or_404
|
|
6
|
-
from rest_framework import status
|
|
7
|
-
from rest_framework.response import Response
|
|
8
|
-
from rest_framework.views import APIView
|
|
9
|
-
|
|
10
|
-
from endoreg_db.utils.permissions import DEBUG_PERMISSIONS
|
|
11
|
-
import logging
|
|
12
|
-
|
|
13
|
-
logger = logging.getLogger(__name__)
|
|
14
|
-
|
|
15
|
-
class SensitiveMetaDetailView(APIView):
|
|
16
|
-
"""
|
|
17
|
-
API endpoint to retrieve and update SensitiveMeta details with verification state.
|
|
18
|
-
|
|
19
|
-
GET: Returns detailed SensitiveMeta information for annotation/verification
|
|
20
|
-
PATCH: Updates SensitiveMeta fields including verification state
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
@transaction.atomic
|
|
24
|
-
def patch(self, request, sensitive_meta_id=None):
|
|
25
|
-
"""
|
|
26
|
-
Update SensitiveMeta fields including verification state.
|
|
27
|
-
|
|
28
|
-
Accepts partial updates for any field in SensitiveMetaUpdateSerializer.
|
|
29
|
-
Special handling for verification state changes.
|
|
30
|
-
"""
|
|
31
|
-
if not sensitive_meta_id:
|
|
32
|
-
return Response(
|
|
33
|
-
{"error": "sensitive_meta_id is required"},
|
|
34
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
try:
|
|
38
|
-
# Get the SensitiveMeta instance
|
|
39
|
-
sensitive_meta = get_object_or_404(SensitiveMeta, id=sensitive_meta_id)
|
|
40
|
-
|
|
41
|
-
# Validate and update using serializer
|
|
42
|
-
serializer = SensitiveMetaUpdateSerializer(
|
|
43
|
-
sensitive_meta,
|
|
44
|
-
data=request.data,
|
|
45
|
-
partial=True
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
if serializer.is_valid():
|
|
49
|
-
updated_instance = serializer.save()
|
|
50
|
-
|
|
51
|
-
# Return updated data using detail serializer
|
|
52
|
-
response_serializer = SensitiveMetaDetailSerializer(updated_instance)
|
|
53
|
-
|
|
54
|
-
response_data = {
|
|
55
|
-
"message": "SensitiveMeta updated successfully",
|
|
56
|
-
"sensitive_meta": response_serializer.data,
|
|
57
|
-
"updated_fields": list(request.data.keys())
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
logger.info(
|
|
61
|
-
f"Updated SensitiveMeta {sensitive_meta_id} by user {request.user}. "
|
|
62
|
-
f"Fields: {list(request.data.keys())}"
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
return Response(response_data, status=status.HTTP_200_OK)
|
|
66
|
-
else:
|
|
67
|
-
return Response(
|
|
68
|
-
{
|
|
69
|
-
"error": "Validation failed",
|
|
70
|
-
"details": serializer.errors
|
|
71
|
-
},
|
|
72
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
except SensitiveMeta.DoesNotExist:
|
|
76
|
-
return Response(
|
|
77
|
-
{"error": f"SensitiveMeta with ID {sensitive_meta_id} not found"},
|
|
78
|
-
status=status.HTTP_404_NOT_FOUND
|
|
79
|
-
)
|
|
80
|
-
except Exception as e:
|
|
81
|
-
logger.error(f"Error updating SensitiveMeta {sensitive_meta_id}: {e}")
|
|
82
|
-
return Response(
|
|
83
|
-
{"error": "Internal server error occurred"},
|
|
84
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
85
|
-
)
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from django.http import Http404, HttpResponse
|
|
5
|
-
from django.shortcuts import get_object_or_404
|
|
6
|
-
from rest_framework import status
|
|
7
|
-
from rest_framework.response import Response
|
|
8
|
-
from rest_framework.views import APIView
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
import logging
|
|
13
|
-
from ...utils.paths import data_paths # Added for centralized path management
|
|
14
|
-
logger = logging.getLogger(__name__)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class SecureFileServingView(APIView):
|
|
19
|
-
"""
|
|
20
|
-
Serviert Dateien über sichere URLs mit Token-Validierung
|
|
21
|
-
GET /api/reports/{report_id}/secure-file/?token={token}
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def get(self, request, report_id):
|
|
25
|
-
token = request.GET.get('token')
|
|
26
|
-
|
|
27
|
-
if not token:
|
|
28
|
-
return Response(
|
|
29
|
-
{"error": "Token ist erforderlich"},
|
|
30
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
try:
|
|
34
|
-
report = get_object_or_404(RawPdfFile, id=report_id)
|
|
35
|
-
|
|
36
|
-
if not report.file:
|
|
37
|
-
raise Http404("Datei nicht gefunden")
|
|
38
|
-
|
|
39
|
-
# Token validieren (hier würde normalerweise eine Token-Speicherung/Validierung stattfinden)
|
|
40
|
-
# Für diese Implementierung nehmen wir an, dass das Token gültig ist
|
|
41
|
-
|
|
42
|
-
# Datei servieren
|
|
43
|
-
return self._serve_file(report.file)
|
|
44
|
-
|
|
45
|
-
except (ValueError, TypeError, OSError) as e:
|
|
46
|
-
logger.error("Fehler beim Servieren der Datei: %s", str(e))
|
|
47
|
-
raise Http404("Datei konnte nicht geladen werden") from e
|
|
48
|
-
|
|
49
|
-
def _serve_file(self, file_field):
|
|
50
|
-
"""Serviert die Datei als HTTP-Response"""
|
|
51
|
-
try:
|
|
52
|
-
file_path = Path(file_field.path)
|
|
53
|
-
|
|
54
|
-
with open(file_field.path, 'rb') as f:
|
|
55
|
-
response = HttpResponse(
|
|
56
|
-
f.read(),
|
|
57
|
-
content_type=self._get_content_type(file_path.suffix)
|
|
58
|
-
)
|
|
59
|
-
response['Content-Disposition'] = f'inline; filename="{file_path.name}"'
|
|
60
|
-
return response
|
|
61
|
-
|
|
62
|
-
except (OSError, IOError) as e:
|
|
63
|
-
logger.error("Fehler beim Lesen der Datei: %s", str(e))
|
|
64
|
-
raise Http404("Datei konnte nicht gelesen werden") from e
|
|
65
|
-
|
|
66
|
-
def _get_content_type(self, file_extension):
|
|
67
|
-
"""Ermittelt den Content-Type basierend auf der Dateiendung"""
|
|
68
|
-
content_types = {
|
|
69
|
-
'.pdf': 'application/pdf',
|
|
70
|
-
'.jpg': 'image/jpeg',
|
|
71
|
-
'.jpeg': 'image/jpeg',
|
|
72
|
-
'.png': 'image/png',
|
|
73
|
-
'.gif': 'image/gif',
|
|
74
|
-
'.bmp': 'image/bmp',
|
|
75
|
-
'.webp': 'image/webp',
|
|
76
|
-
'.txt': 'text/plain',
|
|
77
|
-
'.doc': 'application/msword',
|
|
78
|
-
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
79
|
-
}
|
|
80
|
-
return content_types.get(file_extension.lower(), 'application/octet-stream')
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
from endoreg_db.models import RawPdfFile
|
|
2
|
-
from endoreg_db.serializers.report.secure_file_url import SecureFileUrlSerializer
|
|
3
|
-
|
|
4
|
-
from django.shortcuts import get_object_or_404
|
|
5
|
-
from django.utils import timezone
|
|
6
|
-
from rest_framework import status
|
|
7
|
-
from rest_framework.response import Response
|
|
8
|
-
from rest_framework.views import APIView
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import uuid
|
|
12
|
-
from datetime import timedelta
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
|
|
15
|
-
import logging
|
|
16
|
-
from ...utils.paths import data_paths # Added for centralized path management
|
|
17
|
-
logger = logging.getLogger(__name__)
|
|
18
|
-
|
|
19
|
-
class SecureFileUrlView(APIView):
|
|
20
|
-
"""
|
|
21
|
-
API-Endpunkt für sichere URL-Generierung
|
|
22
|
-
POST /api/secure-file-urls/
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def post(self, request):
|
|
26
|
-
report_id = request.data.get('report_id')
|
|
27
|
-
file_type = request.data.get('file_type', 'pdf')
|
|
28
|
-
|
|
29
|
-
if not report_id:
|
|
30
|
-
return Response(
|
|
31
|
-
{"error": "report_id ist erforderlich"},
|
|
32
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
try:
|
|
36
|
-
report = get_object_or_404(RawPdfFile, id=report_id)
|
|
37
|
-
|
|
38
|
-
if not report.file:
|
|
39
|
-
return Response(
|
|
40
|
-
{"error": "Keine Datei für diesen Report verfügbar"},
|
|
41
|
-
status=status.HTTP_404_NOT_FOUND
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
# Sichere URL generieren
|
|
45
|
-
secure_url_data = self._generate_secure_url(report, request, file_type)
|
|
46
|
-
serializer = SecureFileUrlSerializer(data=secure_url_data)
|
|
47
|
-
|
|
48
|
-
if serializer.is_valid():
|
|
49
|
-
return Response(serializer.data)
|
|
50
|
-
else:
|
|
51
|
-
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
52
|
-
|
|
53
|
-
except (ValueError, TypeError) as e:
|
|
54
|
-
logger.error("Fehler beim Generieren der sicheren URL: %s", str(e))
|
|
55
|
-
return Response(
|
|
56
|
-
{"error": "Sichere URL konnte nicht generiert werden"},
|
|
57
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
def _generate_secure_url(self, report, request, file_type):
|
|
61
|
-
"""Generiert eine sichere URL mit Token"""
|
|
62
|
-
token = str(uuid.uuid4())
|
|
63
|
-
expires_at = timezone.now() + timedelta(hours=2)
|
|
64
|
-
|
|
65
|
-
secure_url = request.build_absolute_uri(
|
|
66
|
-
f"/api/reports/{report.id}/secure-file/?token={token}"
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
# Dateigröße ermitteln
|
|
70
|
-
file_size = 0
|
|
71
|
-
try:
|
|
72
|
-
if report.file:
|
|
73
|
-
file_size = report.file.size
|
|
74
|
-
except OSError:
|
|
75
|
-
# Datei nicht verfügbar
|
|
76
|
-
file_size = 0
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
'url': secure_url,
|
|
80
|
-
'expires_at': expires_at,
|
|
81
|
-
'file_type': file_type,
|
|
82
|
-
'original_filename': Path(report.file.name).name if report.file else 'unknown',
|
|
83
|
-
'file_size': file_size
|
|
84
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# endoreg_db/views/misc/secure_url_validate.py
|
|
2
|
-
|
|
3
|
-
from urllib.parse import urlparse
|
|
4
|
-
|
|
5
|
-
from django.core.exceptions import ValidationError
|
|
6
|
-
from django.core.validators import URLValidator
|
|
7
|
-
|
|
8
|
-
from rest_framework import status
|
|
9
|
-
from rest_framework.decorators import api_view, throttle_classes
|
|
10
|
-
from rest_framework.response import Response
|
|
11
|
-
from rest_framework.throttling import ScopedRateThrottle
|
|
12
|
-
|
|
13
|
-
import logging
|
|
14
|
-
logger = logging.getLogger(__name__)
|
|
15
|
-
|
|
16
|
-
# Accept only http/https; adjust if you later need custom schemes
|
|
17
|
-
_url_validator = URLValidator(schemes=["http", "https"])
|
|
18
|
-
_MAX_URL_LENGTH = 2048 # pragmatic upper bound to avoid abuse
|
|
19
|
-
|
|
20
|
-
@api_view(['GET'])
|
|
21
|
-
@throttle_classes([ScopedRateThrottle]) # 429s will be returned automatically if exceeded
|
|
22
|
-
def validate_secure_url(request):
|
|
23
|
-
"""
|
|
24
|
-
Validiert eine sichere URL
|
|
25
|
-
GET /api/validate-secure-url/?url={url}
|
|
26
|
-
"""
|
|
27
|
-
url = request.GET.get('url')
|
|
28
|
-
|
|
29
|
-
if not url:
|
|
30
|
-
return Response(
|
|
31
|
-
{"error": "URL Parameter ist erforderlich"},
|
|
32
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
# Basic length guardrails
|
|
36
|
-
if len(url) > _MAX_URL_LENGTH:
|
|
37
|
-
return Response(
|
|
38
|
-
{"error": "URL ist zu lang"},
|
|
39
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
# Syntactic + scheme validation
|
|
43
|
-
try:
|
|
44
|
-
_url_validator(url)
|
|
45
|
-
except ValidationError:
|
|
46
|
-
return Response(
|
|
47
|
-
{"error": "Ungültiges URL-Format (erlaubt sind http/https)"},
|
|
48
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
# Extra cheap sanity checks (netloc must exist, no data/file/javascript, etc.)
|
|
52
|
-
parsed = urlparse(url)
|
|
53
|
-
if not parsed.netloc:
|
|
54
|
-
return Response(
|
|
55
|
-
{"error": "Ungültige URL: Hostname fehlt"},
|
|
56
|
-
status=status.HTTP_400_BAD_REQUEST
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
# Hier würde normalerweise eine Token-Validierung stattfinden
|
|
61
|
-
# Für diese Implementierung geben wir immer True zurück
|
|
62
|
-
is_valid = True
|
|
63
|
-
|
|
64
|
-
return Response({
|
|
65
|
-
"is_valid": is_valid,
|
|
66
|
-
"message": "URL ist gültig" if is_valid else "URL ist ungültig oder abgelaufen"
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
except (ValueError, TypeError) as e:
|
|
70
|
-
logger.error("Fehler bei URL-Validierung: %s", str(e))
|
|
71
|
-
return Response(
|
|
72
|
-
{"error": "URL-Validierung fehlgeschlagen"},
|
|
73
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
# Assign a throttle scope so we can configure a specific rate in settings
|
|
77
|
-
validate_secure_url.throttle_scope = "secure-url-validate"
|
|
78
|
-
|
|
79
|
-
# for update got to base_settings.py
|