[med-svn] [Git][med-team/gnumed-server][upstream] New upstream version 22.30
Emmanuel Arias (@eamanu)
gitlab at salsa.debian.org
Tue Apr 1 21:27:26 BST 2025
Emmanuel Arias pushed to branch upstream at Debian Med / gnumed-server
Commits:
2a7ad897 by Emmanuel Arias at 2025-04-01T17:16:28-03:00
New upstream version 22.30
- - - - -
15 changed files:
- server/bootstrap/fixup_db-v22.conf
- server/bootstrap/update_db-v21_v22.conf
- server/doc/schema/gnumed-entire_schema.html
- server/pycommon/gmCfg2.py
- server/pycommon/gmConnectionPool.py
- server/pycommon/gmCrypto.py
- server/pycommon/gmDateTime.py
- server/pycommon/gmI18N.py
- server/pycommon/gmPG2.py
- server/pycommon/gmTools.py
- + server/sql/v21-v22/fixups/v22-dem-org-permission-fixups.sql
- + server/sql/v21-v22/fixups/v22-dem-unique_named_identity-fixup.sql
- server/sql/v21-v22/fixups/v22-dem-v_message_inbox-fixup.sql
- + server/sql/v21-v22/fixups/v22-dem-v_pat_addresses-fixups.sql
- server/sql/v21-v22/fixups/v22-release_notes-fixup.sql
Changes:
=====================================
server/bootstrap/fixup_db-v22.conf
=====================================
@@ -42,6 +42,9 @@ v22-blobs-reviewed_doc_objs-idx.sql
v22-blobs-v_reviewed_doc_objects-fixup.sql
v22-dem-identity-idx.sql
v22-dem-names-idx.sql
+v22-dem-unique_named_identity-fixup.sql
+v22-dem-v_pat_addresses-fixups.sql
+v22-dem-org-permission-fixups.sql
v22-release_notes-fixup.sql
$schema$
=====================================
server/bootstrap/update_db-v21_v22.conf
=====================================
@@ -174,6 +174,9 @@ v22-blobs-reviewed_doc_objs-idx.sql
v22-blobs-v_reviewed_doc_objects-fixup.sql
v22-dem-identity-idx.sql
v22-dem-names-idx.sql
+v22-dem-unique_named_identity-fixup.sql
+v22-dem-v_pat_addresses-fixups.sql
+v22-dem-org-permission-fixups.sql
v22-release_notes-fixup.sql
$schema$
=====================================
server/doc/schema/gnumed-entire_schema.html
=====================================
@@ -112,7 +112,7 @@
<body>
<!-- Primary Index -->
-<p><br><br>Dumped on 2024-01-28</p>
+<p><br><br>Dumped on 2025-03-30</p>
<h1><a name="index">Index of database - gnumed_v22</a></h1>
<ul>
@@ -143,7 +143,7 @@
<li><a name="clin.schema">clin</a></li><ul>
<li><a href="gnumed-entire_schema.html#clin.table.-enum-allergy-type">_enum_allergy_type</a></li><li><a href="gnumed-entire_schema.html#clin.view.-view-emr-journal-without-suppressed-hints">_view_emr_journal_without_suppressed_hints</a></li><li><a href="gnumed-entire_schema.html#clin.table.allergy">allergy</a></li><li><a href="gnumed-entire_schema.html#clin.table.allergy-state">allergy_state</a></li><li><a href="gnumed-entire_schema.html#clin.table.clin-aux-note">clin_aux_note</a></li><li><a href="gnumed-entire_schema.html#clin.table.clin-diag">clin_diag</a></li><li><a href="gnumed-entire_schema.html#clin.table.clin-item-type">clin_item_type</a></li><li><a href="gnumed-entire_schema.html#clin.table.clin-narrative">clin_narrative</a></li><li><a href="gnumed-entire_schema.html#clin.table.clin-root-item">clin_root_item</a></li><li><a href="gnumed-entire_schema.html#clin.table.encounter">encounter</a></li><li><a href="gnumed-entire_schema.html#clin.table.encounter-type">encounter_type</a></li><li><a href="gnumed-entire_schema.html#clin.table.episode">episode</a></li><li><a href="gnumed-entire_schema.html#clin.table.export-item">export_item</a></li><li><a href="gnumed-entire_schema.html#clin.table.external-care">external_care</a></li><li><a href="gnumed-entire_schema.html#clin.table.family-history">family_history</a></li><li><a href="gnumed-entire_schema.html#clin.table.fhx-relation-type">fhx_relation_type</a></li><li><a href="gnumed-entire_schema.html#clin.table.form-data">form_data</a></li><li><a href="gnumed-entire_schema.html#clin.table.form-instances">form_instances</a></li><li><a href="gnumed-entire_schema.html#clin.table.health-issue">health_issue</a></li><li><a href="gnumed-entire_schema.html#clin.table.hospital-stay">hospital_stay</a></li><li><a href="gnumed-entire_schema.html#clin.table.incoming-data-unmatchable">incoming_data_unmatchable</a></li><li><a href="gnumed-entire_schema.html#clin.table.incoming-data-unmatched">incoming_data_unmatched</a></li><li><a href="gnumed-entire_schema.html#clin.table.lab-request">lab_request</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2aoe">lnk_code2aoe</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2episode">lnk_code2episode</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2fhx">lnk_code2fhx</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2h-issue">lnk_code2h_issue</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2item-root">lnk_code2item_root</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2narrative">lnk_code2narrative</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2procedure">lnk_code2procedure</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2rfe">lnk_code2rfe</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-code2tst-pnl">lnk_code2tst_pnl</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-constraint2vacc-course">lnk_constraint2vacc_course</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-loinc2test-panel">lnk_loinc2test_panel</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-pat2vaccination-course">lnk_pat2vaccination_course</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-substance2episode">lnk_substance2episode</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-tst2norm">lnk_tst2norm</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-type2item">lnk_type2item</a></li><li><a href="gnumed-entire_schema.html#clin.table.lnk-vaccination-course2schedule">lnk_vaccination_course2schedule</a></li><li><a href="gnumed-entire_schema.html#clin.table.meta-test-type">meta_test_type</a></li><li><a href="gnumed-entire_schema.html#clin.table.patient">patient</a></li><li><a href="gnumed-entire_schema.html#clin.table.procedure">procedure</a></li><li><a href="gnumed-entire_schema.html#clin.table.review-root">review_root</a></li><li><a href="gnumed-entire_schema.html#clin.table.reviewed-test-results">reviewed_test_results</a></li><li><a href="gnumed-entire_schema.html#clin.table.soap-cat-ranks">soap_cat_ranks</a></li><li><a href="gnumed-entire_schema.html#clin.table.substance-intake">substance_intake</a></li><li><a href="gnumed-entire_schema.html#clin.table.suppressed-hint">suppressed_hint</a></li><li><a href="gnumed-entire_schema.html#clin.table.test-org">test_org</a></li><li><a href="gnumed-entire_schema.html#clin.table.test-panel">test_panel</a></li><li><a href="gnumed-entire_schema.html#clin.table.test-result">test_result</a></li><li><a href="gnumed-entire_schema.html#clin.table.test-type">test_type</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-candidate-diagnoses">v_candidate_diagnoses</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-edc-journal">v_edc_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-emr-journal">v_emr_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-export-items">v_export_items</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-external-care">v_external_care</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-external-care-journal">v_external_care_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-family-history">v_family_history</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-family-history-journal">v_family_history_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-health-issues">v_health_issues</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-health-issues-journal">v_health_issues_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-hospital-stays">v_hospital_stays</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-hospital-stays-journal">v_hospital_stays_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-hospital-stays-journal-multi-day-adm">v_hospital_stays_journal_multi_day_adm</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-hospital-stays-journal-multi-day-dis">v_hospital_stays_journal_multi_day_dis</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-hospital-stays-journal-no-discharge">v_hospital_stays_journal_no_discharge</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-hospital-stays-journal-one-day">v_hospital_stays_journal_one_day</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-incoming-data-unmatched">v_incoming_data_unmatched</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-linked-codes">v_linked_codes</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-most-recent-encounters">v_most_recent_encounters</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-narrative">v_narrative</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-allergies">v_pat_allergies</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-allergies-journal">v_pat_allergies_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-allergy-state">v_pat_allergy_state</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-allergy-state-journal">v_pat_allergy_state_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-encounters">v_pat_encounters</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-encounters-journal">v_pat_encounters_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-episodes">v_pat_episodes</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-episodes-journal">v_pat_episodes_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-items">v_pat_items</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-last-vacc4indication">v_pat_last_vacc4indication</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-narrative-journal">v_pat_narrative_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-pat-vaccs4indication">v_pat_vaccs4indication</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-potential-problem-list">v_potential_problem_list</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-problem-list">v_problem_list</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-procedures">v_procedures</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-procedures-at-hospital">v_procedures_at_hospital</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-procedures-at-hospital-journal">v_procedures_at_hospital_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-procedures-journal">v_procedures_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-procedures-not-at-hospital">v_procedures_not_at_hospital</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-procedures-not-at-hospital-journal">v_procedures_not_at_hospital_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-reminders-journal">v_reminders_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-reviewed-items">v_reviewed_items</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-subst-intake4narr-search">v_subst_intake4narr_search</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-substance-intake-journal">v_substance_intake_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-substance-intakes">v_substance_intakes</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-suppressed-hints">v_suppressed_hints</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-suppressed-hints-journal">v_suppressed_hints_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-test-orgs">v_test_orgs</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-test-panels">v_test_panels</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-test-results">v_test_results</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-test-results-journal">v_test_results_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-test-types">v_test_types</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-test-types4test-panel">v_test_types4test_panel</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-vaccination-courses-in-schedule">v_vaccination_courses_in_schedule</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-vaccinations">v_vaccinations</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-vaccinations-journal">v_vaccinations_journal</a></li><li><a href="gnumed-entire_schema.html#clin.view.v-waiting-list">v_waiting_list</a></li><li><a href="gnumed-entire_schema.html#clin.table.vaccination">vaccination</a></li><li><a href="gnumed-entire_schema.html#clin.table.vaccination-course">vaccination_course</a></li><li><a href="gnumed-entire_schema.html#clin.table.vaccination-course-constraint">vaccination_course_constraint</a></li><li><a href="gnumed-entire_schema.html#clin.table.vaccination-definition">vaccination_definition</a></li><li><a href="gnumed-entire_schema.html#clin.table.vaccination-schedule">vaccination_schedule</a></li><li><a href="gnumed-entire_schema.html#clin.table.waiting-list">waiting_list</a></li>
- <li><a href="gnumed-entire_schema.html#clin.function.-get-recommendation-for-patient-hint-text-integer">_get_recommendation_for_patient_hint(text, integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.add-coded-phrase-text-text-text">add_coded_phrase(text, text, text)</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-del-booster-must-have-base-immunity">f_del_booster_must_have_base_immunity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-fk-reviewer-default">f_fk_reviewer_default()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-ins-booster-must-have-base-immunity">f_ins_booster_must_have_base_immunity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-protect-clin-root-item">f_protect_clin_root_item()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-upd-booster-must-have-base-immunity">f_upd_booster_must_have_base_immunity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.get-dob-integer">get_dob(integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.get-dod-integer">get_dod(integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.get-hints-for-patient-pk-identity-integer">get_hints_for_patient(_pk_identity integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.hint-suppression-exists-pk-identity-integer-pk-hint-integer">hint_suppression_exists(_pk_identity integer, _pk_hint integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.move-waiting-list-entry-integer-integer">move_waiting_list_entry(integer, integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.remove-old-empty-encounters-integer">remove_old_empty_encounters(integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.remove-old-empty-encounters-integer-interval">remove_old_empty_encounters(integer, interval)</a></li><li><a href="gnumed-entire_schema.html#clin.function.run-hint-query-title-text-query-text">run_hint_query(_title text, _query text)</a></li><li><a href="gnumed-entire_schema.html#clin.function.transfer-all-encounter-data-pk-source-encounter-integer-pk-target-encounter-integer">transfer_all_encounter_data(_pk_source_encounter integer, _pk_target_encounter integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-activate-issue-on-opening-episode">trf_activate_issue_on_opening_episode()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-announce-active-substance-mod-no-pk">trf_announce_active_substance_mod_no_pk()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-announce-consumed-substance-mod-no-pk">trf_announce_consumed_substance_mod_no_pk()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-check-ext-care-uniq-issue-per-enc-and-unit-ins-upd">trf_check_ext_care_uniq_issue_per_enc_and_unit_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-del-intake-document-deleted">trf_del_intake_document_deleted()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-del-intake-must-unlink-all-drug-components">trf_del_intake_must_unlink_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ensure-one-allergy-state-per-patient">trf_ensure_one_allergy_state_per_patient()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ins-intake-prevent-duplicate-component-links">trf_ins_intake_prevent_duplicate_component_links()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ins-lc2sth-fk-generic-code">trf_ins_lc2sth_fk_generic_code()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ins-upd-export-item-normalize-fk-identity">trf_ins_upd_export_item_normalize_fk_identity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-insert-intake-links-all-drug-components">trf_insert_intake_links_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-invalidate-review-on-result-change">trf_invalidate_review_on_result_change()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-normalize-proc-is-ongoing">trf_normalize_proc_is_ongoing()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-notify-reviewer-of-review-change">trf_notify_reviewer_of_review_change()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-enc-epi-ins-upd">trf_sanity_check_enc_epi_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-enc-issue-ins-upd">trf_sanity_check_enc_issue_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-enc-vs-issue-on-epi">trf_sanity_check_enc_vs_issue_on_epi()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-procedure-episode">trf_sanity_check_procedure_episode()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-uniq-hint-per-pat-ins-upd">trf_sanity_check_uniq_hint_per_pat_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sync-allergic-state-on-allergies-modified">trf_sync_allergic_state_on_allergies_modified()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-undiscontinue-unsets-reason">trf_undiscontinue_unsets_reason()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-unique-indication-in-schedule">trf_unique_indication_in_schedule()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-intake-must-link-all-drug-components">trf_upd_intake_must_link_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-intake-prevent-duplicate-component-links">trf_upd_intake_prevent_duplicate_component_links()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-intake-updates-all-drug-components">trf_upd_intake_updates_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-lc2sth-fk-generic-code">trf_upd_lc2sth_fk_generic_code()</a></li>
+ <li><a href="gnumed-entire_schema.html#clin.function.-get-recommendation-for-patient-hint-text-integer">_get_recommendation_for_patient_hint(text, integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.add-coded-phrase-text-text-text">add_coded_phrase(text, text, text)</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-del-booster-must-have-base-immunity">f_del_booster_must_have_base_immunity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-fk-reviewer-default">f_fk_reviewer_default()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-ins-booster-must-have-base-immunity">f_ins_booster_must_have_base_immunity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-protect-clin-root-item">f_protect_clin_root_item()</a></li><li><a href="gnumed-entire_schema.html#clin.function.f-upd-booster-must-have-base-immunity">f_upd_booster_must_have_base_immunity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.get-dob-integer">get_dob(integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.get-dod-integer">get_dod(integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.get-hints-for-patient-pk-identity-integer">get_hints_for_patient(_pk_identity integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.hint-suppression-exists-pk-identity-integer-pk-hint-integer">hint_suppression_exists(_pk_identity integer, _pk_hint integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.move-waiting-list-entry-wl-pos-src-integer-wl-pos-dest-integer">move_waiting_list_entry(_wl_pos_src integer, _wl_pos_dest integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.remove-old-empty-encounters-integer">remove_old_empty_encounters(integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.remove-old-empty-encounters-integer-interval">remove_old_empty_encounters(integer, interval)</a></li><li><a href="gnumed-entire_schema.html#clin.function.run-hint-query-title-text-query-text">run_hint_query(_title text, _query text)</a></li><li><a href="gnumed-entire_schema.html#clin.function.transfer-all-encounter-data-pk-source-encounter-integer-pk-target-encounter-integer">transfer_all_encounter_data(_pk_source_encounter integer, _pk_target_encounter integer)</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-activate-issue-on-opening-episode">trf_activate_issue_on_opening_episode()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-announce-active-substance-mod-no-pk">trf_announce_active_substance_mod_no_pk()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-announce-consumed-substance-mod-no-pk">trf_announce_consumed_substance_mod_no_pk()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-check-ext-care-uniq-issue-per-enc-and-unit-ins-upd">trf_check_ext_care_uniq_issue_per_enc_and_unit_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-del-intake-document-deleted">trf_del_intake_document_deleted()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-del-intake-must-unlink-all-drug-components">trf_del_intake_must_unlink_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ensure-one-allergy-state-per-patient">trf_ensure_one_allergy_state_per_patient()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ins-intake-prevent-duplicate-component-links">trf_ins_intake_prevent_duplicate_component_links()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ins-lc2sth-fk-generic-code">trf_ins_lc2sth_fk_generic_code()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-ins-upd-export-item-normalize-fk-identity">trf_ins_upd_export_item_normalize_fk_identity()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-insert-intake-links-all-drug-components">trf_insert_intake_links_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-invalidate-review-on-result-change">trf_invalidate_review_on_result_change()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-normalize-proc-is-ongoing">trf_normalize_proc_is_ongoing()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-notify-reviewer-of-review-change">trf_notify_reviewer_of_review_change()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-enc-epi-ins-upd">trf_sanity_check_enc_epi_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-enc-issue-ins-upd">trf_sanity_check_enc_issue_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-enc-vs-issue-on-epi">trf_sanity_check_enc_vs_issue_on_epi()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-procedure-episode">trf_sanity_check_procedure_episode()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sanity-check-uniq-hint-per-pat-ins-upd">trf_sanity_check_uniq_hint_per_pat_ins_upd()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-sync-allergic-state-on-allergies-modified">trf_sync_allergic_state_on_allergies_modified()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-undiscontinue-unsets-reason">trf_undiscontinue_unsets_reason()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-unique-indication-in-schedule">trf_unique_indication_in_schedule()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-intake-must-link-all-drug-components">trf_upd_intake_must_link_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-intake-prevent-duplicate-component-links">trf_upd_intake_prevent_duplicate_component_links()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-intake-updates-all-drug-components">trf_upd_intake_updates_all_drug_components()</a></li><li><a href="gnumed-entire_schema.html#clin.function.trf-upd-lc2sth-fk-generic-code">trf_upd_lc2sth_fk_generic_code()</a></li>
</ul>
<li><a name="de-de.schema">de_de</a></li><ul>
@@ -50900,6 +50900,16 @@ there will always be one "sender".
<ul class="indexes">
<!-- Indexes -->
+ <li><b>idx_doc_med_fk_encounter</b> fk_encounter</li>
+
+ <li><b>idx_doc_med_fk_episode</b> fk_episode</li>
+
+ <li><b>idx_doc_med_fk_hospital_stay</b> fk_hospital_stay</li>
+
+ <li><b>idx_doc_med_fk_org_unit</b> fk_org_unit</li>
+
+ <li><b>idx_doc_med_fk_type</b> fk_type</li>
+
</ul>
<!-- View Definition -->
@@ -51175,6 +51185,10 @@ impossible to secure, etc.
<ul class="indexes">
<!-- Indexes -->
+ <li><b>idx_doc_obj_fk_doc</b> fk_doc</li>
+
+ <li><b>idx_doc_obj_fk_intended_reviewer</b> fk_intended_reviewer</li>
+
</ul>
<!-- View Definition -->
@@ -51782,6 +51796,10 @@ impossible to secure, etc.
<ul class="indexes">
<!-- Indexes -->
+ <li><b>idx_rev_doc_objs_fk_reviewed_row</b> fk_reviewed_row</li>
+
+ <li><b>idx_rev_doc_objs_fk_reviewer</b> fk_reviewer</li>
+
</ul>
<!-- View Definition -->
@@ -54476,103 +54494,86 @@ WHERE (b_vdm.pk_doc = b_do.fk_doc);</pre>
<!-- View Definition -->
<pre>
-SELECT rdo.fk_reviewed_row AS pk_doc_obj
+SELECT b_rdo.fk_reviewed_row AS pk_doc_obj
,
COALESCE
-(
- (
- SELECT staff.short_alias
-
- FROM dem.staff
-
- WHERE (staff.pk = rdo.fk_reviewer)
- )
+(d_s.short_alias
, (
- ('<#'::text || rdo.fk_reviewer) || '>'::text
+ ('<#'::text || b_rdo.fk_reviewer) || '>'::text
)
) AS reviewer
,
- rdo.is_technically_abnormal
+ b_rdo.is_technically_abnormal
,
- rdo.clinically_relevant
+ b_rdo.clinically_relevant
,
-(EXISTS
- (
- SELECT 1
-
- FROM blobs.doc_obj
-
- WHERE (
- (doc_obj.pk = rdo.fk_reviewed_row)
- AND (doc_obj.fk_intended_reviewer = rdo.fk_reviewer)
- )
- )
-) AS is_review_by_responsible_reviewer
+(b_rdo.fk_reviewer = b_do.fk_intended_reviewer) AS is_review_by_responsible_reviewer
,
-(EXISTS
+(b_rdo.fk_reviewer =
(
- SELECT 1
+ SELECT staff.pk
FROM dem.staff
- WHERE (
- (staff.pk = rdo.fk_reviewer)
- AND (staff.db_user = "current_user"
- ()
- )
- )
+ WHERE (staff.db_user = CURRENT_USER)
)
) AS is_your_review
,
- rdo.comment
+ b_rdo.comment
,
- rdo.modified_when AS reviewed_when
+ b_rdo.modified_when AS reviewed_when
,
- rdo.modified_by
+ b_rdo.modified_by
,
- rdo.pk AS pk_review_root
+ b_rdo.pk AS pk_review_root
,
- rdo.fk_reviewer AS pk_reviewer
+ b_rdo.fk_reviewer AS pk_reviewer
,
-
-(
-SELECT v_obj4doc_no_data.pk_patient
-
- FROM blobs.v_obj4doc_no_data
-
- WHERE (v_obj4doc_no_data.pk_obj = rdo.fk_reviewed_row)
-) AS pk_patient
+ c_enc.fk_patient AS pk_patient
,
-
-(
-SELECT v_obj4doc_no_data.pk_encounter
-
- FROM blobs.v_obj4doc_no_data
-
- WHERE (v_obj4doc_no_data.pk_obj = rdo.fk_reviewed_row)
-) AS pk_encounter
+ b_dm.fk_encounter AS pk_encounter
,
-
-(
-SELECT v_obj4doc_no_data.pk_episode
-
- FROM blobs.v_obj4doc_no_data
-
- WHERE (v_obj4doc_no_data.pk_obj = rdo.fk_reviewed_row)
-) AS pk_episode
+ b_dm.fk_episode AS pk_episode
,
-
-(
-SELECT v_obj4doc_no_data.pk_health_issue
-
- FROM blobs.v_obj4doc_no_data
-
- WHERE (v_obj4doc_no_data.pk_obj = rdo.fk_reviewed_row)
-) AS pk_health_issue
+ c_epi.fk_health_issue AS pk_health_issue
-FROM blobs.reviewed_doc_objs rdo;</pre>
+FROM (
+ (
+ (
+ (
+ (blobs.reviewed_doc_objs b_rdo
+
+ LEFT JOIN dem.staff d_s
+ ON (
+ (d_s.pk = b_rdo.fk_reviewer)
+ )
+ )
+
+ LEFT JOIN blobs.doc_obj b_do
+ ON (
+ (b_do.pk = b_rdo.fk_reviewed_row)
+ )
+ )
+
+ LEFT JOIN blobs.doc_med b_dm
+ ON (
+ (b_do.fk_doc = b_dm.pk)
+ )
+ )
+
+ LEFT JOIN clin.episode c_epi
+ ON (
+ (b_dm.fk_episode = c_epi.pk)
+ )
+ )
+
+LEFT JOIN clin.encounter c_enc
+ ON (
+ (c_epi.fk_encounter = c_enc.pk)
+ )
+);</pre>
<!-- List off permissions -->
@@ -106865,7 +106866,7 @@ END;</pre>
<hr>
<h2>Function:
- <a href="gnumed-entire_schema.html#clin.schema">clin</a>.<a name="clin.function.move-waiting-list-entry-integer-integer">move_waiting_list_entry(integer, integer)</a>
+ <a href="gnumed-entire_schema.html#clin.schema">clin</a>.<a name="clin.function.move-waiting-list-entry-wl-pos-src-integer-wl-pos-dest-integer">move_waiting_list_entry(_wl_pos_src integer, _wl_pos_dest integer)</a>
</h2>
<h3>Returns: boolean</h3>
<h3>Language: PLPGSQL</h3>
@@ -106874,8 +106875,6 @@ END;</pre>
Fails if there is no row with position $1.</p>
<pre>
DECLARE
- _wl_pos_src alias for $1;
- _wl_pos_dest alias for $2;
_tmp_pos integer;
_curr_max_pos integer;
BEGIN
@@ -106897,7 +106896,7 @@ BEGIN
-- does the source row exist ?
perform 1 from clin.waiting_list where list_position = _wl_pos_src;
if not found then
- raise notice 'clin.move_waiting_list_entry(): Cannot move entry [%] to [%]. Entry does not exist.', _wl_pos_src, wl_pos_dest ;
+ raise notice 'clin.move_waiting_list_entry(): Cannot move entry [%] to [%]. Entry does not exist.', _wl_pos_src, _wl_pos_dest ;
return false;
end if;
-- load destination row
@@ -111144,6 +111143,12 @@ not-quite-so-bad: occupation
<ul class="indexes">
<!-- Indexes -->
+ <li><b>idx_dem_identity_fk_emergency_contact</b> fk_emergency_contact</li>
+
+ <li><b>idx_dem_identity_fk_marital_status</b> fk_marital_status</li>
+
+ <li><b>idx_dem_identity_fk_primary_provider</b> fk_primary_provider</li>
+
<li><b>idx_identity_dob_ymd</b> dem.date_trunc_utc('day'::text, dob)</li>
</ul>
@@ -114636,7 +114641,21 @@ FROM dem.lnk_person_org_address;</pre>
<ul class="indexes">
<!-- Indexes -->
- <li><b>idx_names_firstnames</b> firstnames</li>
+ <li><b>idx_dem_names_active_names</b> id_identity, active) WHERE (active IS TRUE</li>
+
+ <li><b>idx_dem_names_firstnames</b> firstnames</li>
+
+ <li><b>idx_dem_names_firstnames_lower</b> lower(firstnames)</li>
+
+ <li><b>idx_dem_names_firstnames_trgm</b> firstnames pgtrgm.gin_trgm_ops</li>
+
+ <li><b>idx_dem_names_id_identity</b> id_identity</li>
+
+ <li><b>idx_dem_names_lastnames</b> lastnames</li>
+
+ <li><b>idx_dem_names_lastnames_lower</b> lower(lastnames)</li>
+
+ <li><b>idx_dem_names_lastnames_trgm</b> lastnames pgtrgm.gin_trgm_ops</li>
<li><b>idx_names_last_first</b> lastnames, firstnames</li>
@@ -129076,10 +129095,10 @@ begin
(select
tbl.contype,
'CONSTRAINT:type='
- || tbl.contype || ':'
+ || tbl.contype::TEXT || ':'
|| replace(pg_catalog.pg_get_constraintdef(tbl.oid, true), ' ', '_')
|| '::active='
- || tbl.convalidated
+ || tbl.convalidated::TEXT
as condef
from pg_catalog.pg_constraint tbl
where
=====================================
server/pycommon/gmCfg2.py
=====================================
@@ -37,13 +37,13 @@ def __set_opt_in_INI_file(src=None, sink=None, group=None, option=None, value=No
continue
# start of list ?
- if regex.match('(?P<list_name>.+)(\s|\t)*=(\s|\t)*\$(?P=list_name)\$', line) is not None:
+ if regex.match(r'(?P<list_name>.+)(\s|\t)*=(\s|\t)*\$(?P=list_name)\$', line) is not None:
in_list = True
sink.write(line)
continue
# end of list ?
- if regex.match('\$.+\$.*', line) is not None:
+ if regex.match(r'\$.+\$.*', line) is not None:
in_list = False
sink.write(line)
continue
@@ -55,7 +55,7 @@ def __set_opt_in_INI_file(src=None, sink=None, group=None, option=None, value=No
continue
# another group ?
- if regex.match('\[.+\].*', line) is not None:
+ if regex.match(r'\[.+\].*', line) is not None:
# next group but option not seen yet ?
if group_seen and not option_seen:
sink.write('%s = %s\n\n\n' % (option, value))
@@ -64,7 +64,7 @@ def __set_opt_in_INI_file(src=None, sink=None, group=None, option=None, value=No
continue
# our option ?
- if regex.match('%s(\s|\t)*=' % option, line) is not None:
+ if regex.match(r'%s(\s|\t)*=' % option, line) is not None:
if group_seen:
sink.write('%s = %s\n' % (option, value))
option_seen = True
@@ -103,7 +103,7 @@ def __set_list_in_INI_file(src=None, sink=None, group=None, option=None, value=N
if inside_our_list: # can only be true if already inside our group
# new list has been written already
# so now at end of our (old) list ?
- if regex.match('\$%s\$' % option, line.strip()) is not None:
+ if regex.match(r'\$%s\$' % option, line.strip()) is not None:
inside_our_list = False
continue
# skip old list entries
@@ -111,7 +111,7 @@ def __set_list_in_INI_file(src=None, sink=None, group=None, option=None, value=N
if inside_our_group:
# our option ?
- if regex.match('%s(\s|\t)*=(\s|\t)*\$%s\$' % (option, option), line.strip()) is not None:
+ if regex.match(r'%s(\s|\t)*=(\s|\t)*\$%s\$' % (option, option), line.strip()) is not None:
sink.write(line) # list header
sink.write('\n'.join(value))
sink.write('\n')
@@ -121,7 +121,7 @@ def __set_list_in_INI_file(src=None, sink=None, group=None, option=None, value=N
continue
# next group (= end of our group) ?
- if regex.match('\[.+\]', line.strip()) is not None:
+ if regex.match(r'\[.+\]', line.strip()) is not None:
# our list already handled ? (if so must already be finished)
if not our_list_seen:
# no, so need to add our list to the group before ...
@@ -175,7 +175,7 @@ def __set_list_in_INI_file_old(src=None, sink=None, group=None, option=None, val
# found option but still in (old) list ?
if option_seen and in_list:
# end of (old) list ?
- if regex.match('\$.+\$.*', line) is not None:
+ if regex.match(r'\$.+\$.*', line) is not None:
in_list = False
sink.write(line)
continue
@@ -187,7 +187,7 @@ def __set_list_in_INI_file_old(src=None, sink=None, group=None, option=None, val
continue
# at start of a list ?
- match = regex.match('(?P<list_name>.+)(\s|\t)*=(\s|\t)*\$(?P=list_name)\$', line)
+ match = regex.match(r'(?P<list_name>.+)(\s|\t)*=(\s|\t)*\$(?P=list_name)\$', line)
if match is not None:
in_list = True
# our list ?
@@ -201,7 +201,7 @@ def __set_list_in_INI_file_old(src=None, sink=None, group=None, option=None, val
continue
# at end of a list ?
- if regex.match('\$.+\$.*', line) is not None:
+ if regex.match(r'\$.+\$.*', line) is not None:
in_list = False
sink.write(line)
continue
@@ -213,7 +213,7 @@ def __set_list_in_INI_file_old(src=None, sink=None, group=None, option=None, val
continue
# another group ?
- if regex.match('\[%s\].*' % group, line) is not None:
+ if regex.match(r'\[%s\].*' % group, line) is not None:
# next group but option not seen yet ?
if our_group_seen and not option_seen:
option_seen = True
@@ -322,7 +322,7 @@ def parse_INI_stream(stream=None, encoding=None):
_log.error(line)
continue
- name, remainder = regex.split('\s*[=:]\s*', line, maxsplit = 1)
+ name, remainder = regex.split(r'\s*[=:]\s*', line, maxsplit = 1)
if name == '':
_log.error('option name empty, aborting')
_log.error(line)
=====================================
server/pycommon/gmConnectionPool.py
=====================================
@@ -631,19 +631,19 @@ class gmConnectionPool(gmBorg.cBorg):
if 'fe_sendauth' in msg:
return True
- if regex.search('user ".*" does not exist', msg) is not None:
+ if regex.search(r'user ".*" does not exist', msg) is not None:
return True
if 'uthenti' in msg:
return True
if ((
- (regex.search('user ".*"', msg) is not None)
+ (regex.search(r'user ".*"', msg) is not None)
or
- (regex.search('(R|r)ol{1,2}e', msg) is not None)
+ (regex.search(r'(R|r)ol{1,2}e', msg) is not None)
)
and ('exist' in msg)
- and (regex.search('n(o|ich)t', msg) is not None)
+ and (regex.search(r'n(o|ich)t', msg) is not None)
):
return True
=====================================
server/pycommon/gmCrypto.py
=====================================
@@ -17,6 +17,7 @@ import sys
import os
import logging
import tempfile
+import shutil
# GNUmed libs
@@ -69,8 +70,8 @@ def create_encrypted_zip_archive_from_dir(source_dir, comment=None, overwrite=Tr
if len(passphrase) < 5:
_log.error('<passphrase> must be at least 5 characters/signs/digits')
return None
- gmLog2.add_word2hide(passphrase)
+ gmLog2.add_word2hide(passphrase)
source_dir = os.path.abspath(source_dir)
if not os.path.isdir(source_dir):
_log.error('<source_dir> does not exist or is not a directory: %s', source_dir)
@@ -84,32 +85,42 @@ def create_encrypted_zip_archive_from_dir(source_dir, comment=None, overwrite=Tr
_log.warning('no 7z binary found')
return None
- sandbox_dir = gmTools.mk_sandbox_dir()
- archive_path_inner = os.path.join(sandbox_dir, 'data')
- if not gmTools.mkdir(archive_path_inner):
- _log.error('cannot create scratch space for inner achive: %s', archive_path_inner)
- archive_fname_inner = 'data.zip'
- archive_name_inner = os.path.join(archive_path_inner, archive_fname_inner)
- archive_path_outer = gmTools.gmPaths().tmp_dir
- archive_fname_outer = 'datawrapper.zip'
- archive_name_outer = os.path.join(archive_path_outer, archive_fname_outer)
+ _log.debug('source directory: %s', source_dir)
+ archive_sandbox = gmTools.mk_sandbox_dir()
+ _log.debug('archive creation sandbox: %s', archive_sandbox)
+ inner_archive_dir = os.path.join(archive_sandbox, 'inner')
+ if not gmTools.mkdir(inner_archive_dir):
+ _log.error('cannot create scratch space for inner archive: %s', inner_archive_dir)
+ return None
+
+ outer_archive_dir = os.path.join(archive_sandbox, 'outer')
+ if not gmTools.mkdir(outer_archive_dir):
+ _log.error('cannot create scratch space for outer archive: %s', outer_archive_dir)
+ return None
+
+ inner_archive_name = os.path.join(inner_archive_dir, 'data.zip')
+ outer_archive_name = os.path.join(outer_archive_dir, 'datawrapper.zip')
# remove existing archives so they don't get *updated* rather than newly created
if overwrite:
- if not gmTools.remove_file(archive_name_inner, force = True):
- _log.error('cannot remove existing archive [%s]', archive_name_inner)
+ if not gmTools.remove_file(inner_archive_name, force = True):
+ _log.error('cannot remove existing archive [%s]', inner_archive_name)
return False
- if not gmTools.remove_file(archive_name_outer, force = True):
- _log.error('cannot remove existing archive [%s]', archive_name_outer)
+ if not gmTools.remove_file(outer_archive_name, force = True):
+ _log.error('cannot remove existing archive [%s]', outer_archive_name)
return False
+ tmp = gmTools.copy_tree_content(source_dir, inner_archive_dir)
+ if not tmp:
+ _log.error('cannot move source data to inner archive creation scratch dir')
+ return False
+
# 7z does not support ZIP comments so create a text file holding the comment
if comment is not None:
tmp, fname = os.path.split(source_dir.rstrip(os.sep))
- comment_filename = os.path.join(sandbox_dir, '000-%s-comment.txt' % fname)
+ comment_filename = os.path.join(inner_archive_dir, '000-%s-comment.txt' % fname)
with open(comment_filename, mode = 'wt', encoding = 'utf8', errors = 'replace') as comment_file:
comment_file.write(comment)
-
# create inner (data) archive: uncompressed, unencrypted, similar to a tar archive
args = [
binary,
@@ -118,7 +129,8 @@ def create_encrypted_zip_archive_from_dir(source_dir, comment=None, overwrite=Tr
'-bd', # no progress indicator
'-mx0', # no compression (only store files)
'-mcu=on', # UTF8 filenames
- '-l', # store content of links, not links
+ # now the default and switch not supported anymore
+ #'-l', # store content of links, not links
'-scsUTF-8', # console charset
'-tzip' # force ZIP format
]
@@ -127,19 +139,41 @@ def create_encrypted_zip_archive_from_dir(source_dir, comment=None, overwrite=Tr
args.append('-bt')
else:
args.append('-bb1')
- args.append(archive_name_inner)
- args.append(source_dir)
- if comment is not None:
- args.append(comment_filename)
+ args.append(inner_archive_name)
+ args.append(os.path.join(inner_archive_dir, '.'))
+ _log.debug(args)
+ old_cwd = os.getcwd()
+ os.chdir(inner_archive_dir)
success, exit_code, stdout = gmShellAPI.run_process(cmd_line = args, encoding = 'utf8', verbose = verbose)
+ os.chdir(old_cwd)
if not success:
_log.error('cannot create inner archive')
return None
+ # test
+ args = [
+ binary,
+ 't', # test archive
+ '-bd', # no progress indicator
+ '-scsUTF-8' # console charset
+ ]
+ if verbose:
+ args.append('-bb3')
+ args.append('-bt')
+ else:
+ args.append('-bb1')
+ args.append(inner_archive_name)
+ _log.debug(args)
+ success, exit_code, stdout = gmShellAPI.run_process(cmd_line = args, encoding = 'utf8', verbose = verbose)
+ if not success:
+ _log.error('cannot verify integrity of inner zip archive')
+ return None
+
+ # FIXME: needs error handling
+ shutil.move(inner_archive_name, outer_archive_dir)
# create "decompress instructions" file
- instructions_filename = os.path.join(archive_path_inner, '000-on_Windows-open_with-WinZip_or_7z_tools')
+ instructions_filename = os.path.join(outer_archive_dir, '000-on_Windows-open_with-WinZip_or_7z_tools')
open(instructions_filename, mode = 'wt').close()
-
# create outer (wrapper) archive: compressed, encrypted
args = [
binary,
@@ -148,7 +182,8 @@ def create_encrypted_zip_archive_from_dir(source_dir, comment=None, overwrite=Tr
'-bd', # no progress indicator
'-mx9', # best available zip compression ratio
'-mcu=on', # UTF8 filenames
- '-l', # store content of links, not links
+ # now the default and switch not supported anymore
+ #'-l', # store content of links, not links
'-scsUTF-8', # console charset
'-tzip', # force ZIP format
'-mem=AES256', # force useful encryption
@@ -159,13 +194,38 @@ def create_encrypted_zip_archive_from_dir(source_dir, comment=None, overwrite=Tr
args.append('-bt')
else:
args.append('-bb1')
- args.append(archive_name_outer)
- args.append(archive_path_inner)
+ args.append(outer_archive_name)
+ args.append(os.path.join(outer_archive_dir, '.'))
+ _log.debug(args)
+ old_cwd = os.getcwd()
+ os.chdir(outer_archive_dir)
success, exit_code, stdout = gmShellAPI.run_process(cmd_line = args, encoding = 'utf8', verbose = verbose)
- if success:
- return archive_name_outer
- _log.error('cannot create outer archive')
- return None
+ os.chdir(old_cwd)
+ if not success:
+ _log.error('cannot create wrapper archive')
+ return None
+
+ # test
+ args = [
+ binary,
+ 't', # test archive
+ '-bd', # no progress indicator
+ '-scsUTF-8', # console charset
+ '-p%s' % passphrase # set passphrase
+ ]
+ if verbose:
+ args.append('-bb3')
+ args.append('-bt')
+ else:
+ args.append('-bb1')
+ args.append(outer_archive_name)
+ _log.debug(args)
+ success, exit_code, stdout = gmShellAPI.run_process(cmd_line = args, encoding = 'utf8', verbose = verbose)
+ if not success:
+ _log.error('cannot verify integrity of outer zip archive')
+ return None
+
+ return outer_archive_name
#---------------------------------------------------------------------------
def create_zip_archive_from_dir(source_dir, archive_name=None, comment=None, overwrite=True, verbose=False):
@@ -205,7 +265,6 @@ def create_zip_archive_from_dir(source_dir, archive_name=None, comment=None, ove
else:
_log.error('cannot remove existing archive comment file [%s]', comment_filename)
comment = None
-
# compress
args = [
binary,
@@ -214,7 +273,8 @@ def create_zip_archive_from_dir(source_dir, archive_name=None, comment=None, ove
'-bd', # no progress indicator
'-mx9', # best available zip compression ratio
'-mcu=on', # UTF8 filenames
- '-l', # store content of links, not links
+ # now the default and switch not supported anymore:
+ #'-l', # store content of links, not links
'-scsUTF-8', # console charset
'-tzip' # force ZIP format
]
@@ -227,13 +287,34 @@ def create_zip_archive_from_dir(source_dir, archive_name=None, comment=None, ove
args.append(source_dir)
if comment is not None:
args.append(comment_filename)
+ _log.debug(args)
success, exit_code, stdout = gmShellAPI.run_process(cmd_line = args, encoding = 'utf8', verbose = verbose)
if comment is not None:
gmTools.remove_file(comment_filename)
- if success:
- return archive_name
+ if not success:
+ _log.error('cannot create zip archive')
+ return None
- return None
+ # test
+ args = [
+ binary,
+ 't', # test archive
+ '-bd', # no progress indicator
+ '-scsUTF-8' # console charset
+ ]
+ if verbose:
+ args.append('-bb3')
+ args.append('-bt')
+ else:
+ args.append('-bb1')
+ args.append(archive_name)
+ _log.debug(args)
+ success, exit_code, stdout = gmShellAPI.run_process(cmd_line = args, encoding = 'utf8', verbose = verbose)
+ if not success:
+ _log.error('cannot verify zip archive integrity')
+ return None
+
+ return archive_name
#===========================================================================
# file decryption methods
@@ -261,7 +342,6 @@ def gpg_decrypt_file(filename=None, passphrase=None, verbose=False, target_ext=N
'--enable-progress-filter',
'--decrypt',
'--output', filename_decrypted
- ##'--use-embedded-filename' # not all encrypted files carry a filename
]
if verbose:
args.extend ([
@@ -419,6 +499,7 @@ def encrypt_pdf(filename=None, passphrase=None, verbose=False, remove_unencrypte
filename,
filename_encrypted
]
+ _log.debug(args)
success, exit_code, stdout = gmShellAPI.run_process(cmd_line = args, encoding = 'utf8', verbose = verbose)
if not success:
return None
@@ -564,6 +645,8 @@ if __name__ == '__main__':
gmI18N.activate_locale()
gmI18N.install_domain()
+ gmLog2.print_logfile_name()
+
#-----------------------------------------------------------------------
def test_gpg_decrypt():
print(gpg_decrypt_file(filename = sys.argv[2], verbose = True))
@@ -579,6 +662,7 @@ if __name__ == '__main__':
#-----------------------------------------------------------------------
def test_encrypt_pdf():
print(encrypt_pdf(filename = sys.argv[2], passphrase = sys.argv[3], verbose = True))
+ #print(encrypt_pdf(filename = sys.argv[2], passphrase = 'PW mit Leerzeichen', verbose = True))
#-----------------------------------------------------------------------
def test_encrypt_file():
@@ -601,6 +685,7 @@ if __name__ == '__main__':
comment = 'GNUmed test archive',
overwrite = True,
passphrase = sys.argv[3],
+# passphrase = 'PW mit Leerzeichen',
verbose = True
))
=====================================
server/pycommon/gmDateTime.py
=====================================
@@ -977,62 +977,62 @@ def str2interval(str_interval=None):
# "(~)35(yY)" - at age 35 years
keys = '|'.join(list(unit_keys['year'].replace('_keys_year', '')))
- if regex.match('^~*(\s|\t)*\d+(%s)*$' % keys, str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(days = (int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]) * avg_days_per_gregorian_year))
+ if regex.match(r'^~*(\s|\t)*\d+(%s)*$' % keys, str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(days = (int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]) * avg_days_per_gregorian_year))
# "(~)12mM" - at age 12 months
keys = '|'.join(list(unit_keys['month'].replace('_keys_month', '')))
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
years, months = divmod (
- int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]),
+ int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]),
12
)
return pyDT.timedelta(days = ((years * avg_days_per_gregorian_year) + (months * avg_days_per_gregorian_month)))
# weeks
keys = '|'.join(list(unit_keys['week'].replace('_keys_week', '')))
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(weeks = int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]))
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(weeks = int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]))
# days
keys = '|'.join(list(unit_keys['day'].replace('_keys_day', '')))
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(days = int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]))
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(days = int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]))
# hours
keys = '|'.join(list(unit_keys['hour'].replace('_keys_hour', '')))
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(hours = int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]))
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*(%s)+$' % keys, str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(hours = int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]))
# x/12 - months
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*12$', str_interval, flags = regex.UNICODE):
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*12$', str_interval, flags = regex.UNICODE):
years, months = divmod (
- int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]),
+ int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]),
12
)
return pyDT.timedelta(days = ((years * avg_days_per_gregorian_year) + (months * avg_days_per_gregorian_month)))
# x/52 - weeks
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*52$', str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(weeks = int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]))
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*52$', str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(weeks = int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]))
# x/7 - days
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*7$', str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(days = int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]))
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*7$', str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(days = int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]))
# x/24 - hours
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*24$', str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(hours = int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]))
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*24$', str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(hours = int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]))
# x/60 - minutes
- if regex.match('^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*60$', str_interval, flags = regex.UNICODE):
- return pyDT.timedelta(minutes = int(regex.findall('\d+', str_interval, flags = regex.UNICODE)[0]))
+ if regex.match(r'^~*(\s|\t)*\d+(\s|\t)*/(\s|\t)*60$', str_interval, flags = regex.UNICODE):
+ return pyDT.timedelta(minutes = int(regex.findall(r'\d+', str_interval, flags = regex.UNICODE)[0]))
# nYnM - years, months
keys_year = '|'.join(list(unit_keys['year'].replace('_keys_year', '')))
keys_month = '|'.join(list(unit_keys['month'].replace('_keys_month', '')))
- if regex.match('^~*(\s|\t)*\d+(%s|\s|\t)+\d+(\s|\t)*(%s)+$' % (keys_year, keys_month), str_interval, flags = regex.UNICODE):
- parts = regex.findall('\d+', str_interval, flags = regex.UNICODE)
+ if regex.match(r'^~*(\s|\t)*\d+(%s|\s|\t)+\d+(\s|\t)*(%s)+$' % (keys_year, keys_month), str_interval, flags = regex.UNICODE):
+ parts = regex.findall(r'\d+', str_interval, flags = regex.UNICODE)
years, months = divmod(int(parts[1]), 12)
years += int(parts[0])
return pyDT.timedelta(days = ((years * avg_days_per_gregorian_year) + (months * avg_days_per_gregorian_month)))
@@ -1040,8 +1040,8 @@ def str2interval(str_interval=None):
# nMnW - months, weeks
keys_month = '|'.join(list(unit_keys['month'].replace('_keys_month', '')))
keys_week = '|'.join(list(unit_keys['week'].replace('_keys_week', '')))
- if regex.match('^~*(\s|\t)*\d+(%s|\s|\t)+\d+(\s|\t)*(%s)+$' % (keys_month, keys_week), str_interval, flags = regex.UNICODE):
- parts = regex.findall('\d+', str_interval, flags = regex.UNICODE)
+ if regex.match(r'^~*(\s|\t)*\d+(%s|\s|\t)+\d+(\s|\t)*(%s)+$' % (keys_month, keys_week), str_interval, flags = regex.UNICODE):
+ parts = regex.findall(r'\d+', str_interval, flags = regex.UNICODE)
months, weeks = divmod(int(parts[1]), 4)
months += int(parts[0])
return pyDT.timedelta(days = ((months * avg_days_per_gregorian_month) + (weeks * days_per_week)))
@@ -1615,8 +1615,8 @@ def __single_slash(str2parse):
matches = []
now = pydt_now_here()
# "xx/yyyy"
- if regex.match("^(\s|\t)*\d{1,2}(\s|\t)*/+(\s|\t)*\d{4}(\s|\t)*$", str2parse, flags = regex.UNICODE):
- parts = regex.findall('\d+', str2parse, flags = regex.UNICODE)
+ if regex.match(r"^(\s|\t)*\d{1,2}(\s|\t)*/+(\s|\t)*\d{4}(\s|\t)*$", str2parse, flags = regex.UNICODE):
+ parts = regex.findall(r'\d+', str2parse, flags = regex.UNICODE)
month = int(parts[0])
if month in range(1, 13):
fts = cFuzzyTimestamp (
@@ -1628,8 +1628,8 @@ def __single_slash(str2parse):
'label': fts.format_accurately()
})
# "xx/"
- elif regex.match("^(\s|\t)*\d{1,2}(\s|\t)*/+(\s|\t)*$", str2parse, flags = regex.UNICODE):
- val = int(regex.findall('\d+', str2parse, flags = regex.UNICODE)[0])
+ elif regex.match(r"^(\s|\t)*\d{1,2}(\s|\t)*/+(\s|\t)*$", str2parse, flags = regex.UNICODE):
+ val = int(regex.findall(r'\d+', str2parse, flags = regex.UNICODE)[0])
if val < 100 and val >= 0:
matches.append ({
@@ -1697,10 +1697,10 @@ def __numbers_only(str2parse):
Spaces or tabs are discarded.
"""
- if not regex.match("^(\s|\t)*\d{1,4}(\s|\t)*$", str2parse, flags = regex.UNICODE):
+ if not regex.match(r"^(\s|\t)*\d{1,4}(\s|\t)*$", str2parse, flags = regex.UNICODE):
return []
- val = int(regex.findall('\d{1,4}', str2parse, flags = regex.UNICODE)[0])
+ val = int(regex.findall(r'\d{1,4}', str2parse, flags = regex.UNICODE)[0])
if val == 0:
return []
=====================================
server/pycommon/gmI18N.py
=====================================
@@ -98,9 +98,9 @@ def __split_locale_into_levels():
global system_locale_level
system_locale_level['full'] = system_locale
# trim '@<variant>' part
- system_locale_level['country'] = regex.split('@|:|\.', system_locale, 1)[0]
+ system_locale_level['country'] = regex.split(r'@|:|\.', system_locale, 1)[0]
# trim '_<COUNTRY>@<variant>' part
- system_locale_level['language'] = system_locale.split('_', 1)[0]
+ system_locale_level['language'] = system_locale.split(r'_', 1)[0]
_log.debug('system locale levels: %s', system_locale_level)
=====================================
server/pycommon/gmPG2.py
=====================================
@@ -696,9 +696,19 @@ def get_db_fingerprint(conn=None, fname=None, with_dump=False, eol=None):
except KeyError:
lines.append('%20s: %s' % ('Schema hash', md5_sum))
for cmd, label in queries:
- curs.execute(cmd)
- rows = curs.fetchall()
- lines.append('%20s: %s' % (label, rows[0][0]))
+ try:
+ curs.execute(cmd)
+ rows = curs.fetchall()
+ val = rows[0][0]
+ except PG_ERROR_EXCEPTION as pg_exc:
+ if pg_exc.pgcode != sql_error_codes.INSUFFICIENT_PRIVILEGE:
+ raise
+
+ if pg_exc.pgerror is None:
+ val = '[%s]: insufficient privileges' % pg_exc.pgcode
+ else:
+ val = '[%s]: %s' % (pg_exc.pgcode, pg_exc.pgerror)
+ lines.append('%20s: %s' % (label, val))
if with_dump:
lines.append('')
lines.append(str(get_schema_structure(link_obj = curs)))
=====================================
server/pycommon/gmTools.py
=====================================
@@ -726,14 +726,14 @@ def fname_sanitize(filename):
name_part = unicodedata.normalize('NFKD', name_part)
# remove everything not in group []
name_part = regex.sub (
- '[^.\w\s[\]()%§+-]',
+ r'[^.\w\s[\]()%§+-]',
'',
name_part,
flags = regex.UNICODE
).strip()
# translate whitespace to underscore
name_part = regex.sub (
- '\s+',
+ r'\s+',
'_',
name_part,
flags = regex.UNICODE
@@ -1288,7 +1288,7 @@ def shorten_words_in_line(text=None, max_length=None, min_word_length=None, igno
else:
if len(text) <= max_length:
return text
- old_words = regex.split('\s+', text, flags = regex.UNICODE)
+ old_words = regex.split(r'\s+', text, flags = regex.UNICODE)
no_old_words = len(old_words)
max_word_length = max(min_word_length, (max_length // no_old_words))
words = []
=====================================
server/sql/v21-v22/fixups/v22-dem-org-permission-fixups.sql
=====================================
@@ -0,0 +1,46 @@
+-- ==============================================================
+-- GNUmed database schema change script
+--
+-- License: GPL v2 or later
+-- Author: Karsten Hilbert
+--
+-- ==============================================================
+\set ON_ERROR_STOP 1
+--set default_transaction_read_only to off;
+
+-- --------------------------------------------------------------
+revoke all on dem.org from public;
+revoke all on dem.org from "gm-public";
+grant select on dem.org to group "gm-public";
+revoke all on dem.org from "gm-staff";
+grant select, insert, update, delete on dem.org to group "gm-staff";
+revoke all on dem.org from "gm-doctors";
+grant select, insert, update, delete on dem.org to group "gm-doctors";
+
+
+revoke all on dem.org_unit from public;
+revoke all on dem.org_unit from "gm-public";
+grant select on dem.org_unit to group "gm-public";
+revoke all on dem.org_unit from "gm-staff";
+grant select, insert, update, delete on dem.org_unit to group "gm-staff";
+revoke all on dem.org_unit from "gm-doctors";
+grant select, insert, update, delete on dem.org_unit to group "gm-doctors";
+
+
+revoke all on dem.org_category from public;
+revoke all on dem.org_category from "gm-public";
+grant select on dem.org_category to group "gm-public";
+revoke all on dem.org_category from "gm-staff";
+grant select, insert, update, delete on dem.org_category to group "gm-staff";
+revoke all on dem.org_category from "gm-doctors";
+grant select, insert, update, delete on dem.org_category to group "gm-doctors";
+
+
+revoke all on dem.v_org_unit_comms from public;
+revoke all on dem.v_org_unit_comms from "gm-public";
+revoke all on dem.v_org_unit_comms from "gm-staff";
+revoke all on dem.v_org_unit_comms from "gm-doctors";
+grant select on dem.v_org_unit_comms to group "gm-public";
+
+-- --------------------------------------------------------------
+select gm.log_script_insertion('v22-dem-org-permission-fixups.sql', '22.30');
=====================================
server/sql/v21-v22/fixups/v22-dem-unique_named_identity-fixup.sql
=====================================
@@ -0,0 +1,129 @@
+-- ==============================================================
+-- GNUmed database schema change script
+--
+-- License: GPL v2 or later
+-- Author: karsten.hilbert at gmx.net
+--
+-- ==============================================================
+\set ON_ERROR_STOP 1
+--set default_transaction_read_only to off;
+set check_function_bodies to on;
+
+-- --------------------------------------------------------------
+drop function if exists dem.assert_unique_named_identity() cascade;
+
+
+-- create function and trigger
+create function dem.assert_unique_named_identity()
+ returns trigger
+ language 'plpgsql'
+ as '
+DECLARE
+ _identity_row record;
+ _names_row record;
+ _names_pks integer[];
+ _other_identities integer[];
+BEGIN
+ -- working on dem.identity
+ if TG_TABLE_NAME = ''identity'' then
+ _identity_row := NEW;
+ select array_agg(id) into _names_pks from dem.names where id_identity = NEW.pk;
+ -- working on dem.names
+ else
+ select * into _identity_row from dem.identity where pk = NEW.id_identity;
+ select ARRAY[NEW.id] into _names_pks;
+ end if;
+
+ -- loop over names rows belonging to identity
+ FOR _names_row IN
+ SELECT * FROM dem.names
+ WHERE id = ANY(_names_pks)
+ LOOP
+ -- there must not be any combination of identical
+ -- (dob, firstname, lastname, identity.comment)
+ -- so, look for clashing rows
+ SELECT array_agg(pk_identity) INTO _other_identities FROM
+ dem.v_person_names d_vpn
+ join dem.identity d_i on (d_i.pk = d_vpn.pk_identity)
+ WHERE
+ -- same firstname
+ d_vpn.firstnames = _names_row.firstnames
+ AND
+ -- same lastname
+ d_vpn.lastnames = _names_row.lastnames
+ AND
+ -- same gender
+ d_i.gender is not distinct from _identity_row.gender
+ AND
+ -- same dob (day)
+ date_trunc(''day'', d_i.dob) is not distinct from date_trunc(''day'', _identity_row.dob)
+ AND
+ -- same discriminator
+ d_i.comment is not distinct from _identity_row.comment
+ AND
+ -- but not the currently updated or inserted row
+ d_i.pk != _identity_row.pk
+ ;
+
+ if coalesce(array_length(_other_identities, 1), 0) > 0 then
+ RAISE EXCEPTION
+ ''[dem.assert_unique_named_identity] % on %.%: More than one person with (firstnames=%), (lastnames=%), (dob=%), (comment=%): % & %'',
+ TG_OP,
+ TG_TABLE_SCHEMA,
+ TG_TABLE_NAME,
+ _names_row.firstnames,
+ _names_row.lastnames,
+ _identity_row.dob,
+ _identity_row.comment,
+ _identity_row.pk,
+ _other_identities
+ USING ERRCODE = ''unique_violation''
+ ;
+ RETURN NULL;
+ end if;
+ END LOOP;
+ return NEW;
+END;';
+
+
+comment on function dem.assert_unique_named_identity() is
+ 'Ensures unique(identity.dob, names.firstnames, names.lastnames, identity.comment)';
+
+
+-- attach to dem.identity
+create constraint trigger tr_ins_d_i_assert_unique_named_identity
+ after insert on
+ dem.identity
+ deferrable
+ initially deferred
+ for
+ each row
+ execute procedure
+ dem.assert_unique_named_identity();
+
+create constraint trigger tr_upd_d_i_assert_unique_named_identity
+ after update on
+ dem.identity
+ deferrable
+ initially deferred
+ for
+ each row
+ when
+ (NEW.comment IS DISTINCT FROM OLD.comment)
+ execute procedure
+ dem.assert_unique_named_identity();
+
+
+-- attach to dem.names
+create constraint trigger tr_d_n_assert_unique_named_identity
+ after insert or update on
+ dem.names
+ deferrable
+ initially deferred
+ for
+ each row
+ execute procedure
+ dem.assert_unique_named_identity();
+
+-- --------------------------------------------------------------
+select gm.log_script_insertion('v22-dem-unique_named_identity-fixup.sql', '22.30');
=====================================
server/sql/v21-v22/fixups/v22-dem-v_message_inbox-fixup.sql
=====================================
@@ -248,6 +248,7 @@ Using UNION makes sure we get the right level of uniqueness.';
grant select on dem.v_message_inbox to group "gm-doctors";
+grant select on dem.v_message_inbox to group "gm-staff";
-- ==============================================================
-select gm.log_script_insertion('v22-dem-v_message_inbox-fixup.sql', '22.5');
+select gm.log_script_insertion('v22-dem-v_message_inbox-fixup.sql', '22.30');
=====================================
server/sql/v21-v22/fixups/v22-dem-v_pat_addresses-fixups.sql
=====================================
@@ -0,0 +1,17 @@
+-- ==============================================================
+-- GNUmed database schema change script
+--
+-- License: GPL v2 or later
+-- Author: Karsten Hilbert
+--
+-- ==============================================================
+\set ON_ERROR_STOP 1
+--set default_transaction_read_only to off;
+
+-- --------------------------------------------------------------
+revoke all on dem.v_pat_addresses from public;
+grant select on dem.v_pat_addresses to group "gm-doctors";
+grant select on dem.v_pat_addresses to group "gm-staff";
+
+-- --------------------------------------------------------------
+select gm.log_script_insertion('v22-dem-v_pat_addresses-fixups.sql', '22.30');
=====================================
server/sql/v21-v22/fixups/v22-release_notes-fixup.sql
=====================================
@@ -17,21 +17,21 @@ INSERT INTO dem.message_inbox (
) VALUES (
(select pk from dem.staff where db_user = 'any-doc'),
(select pk_type from dem.v_inbox_item_type where type = 'memo' and category = 'administrative'),
- 'Release Notes for GNUmed 1.8.18 (database v22.28)',
- 'GNUmed 1.8.18 Release Notes:
+ 'Release Notes for GNUmed 1.8.20 (database v22.30)',
+ 'GNUmed 1.8.20 Release Notes:
- 1.8.18
+ 1.8.20
-IMPROVED: new-patient: dialog layout
-IMPROVED: phrasewheels: in-focus signalling
-IMPROVED: less diagnostic GTK output on console
+FIX: startup: crash on fingerprinting episodes in DB if gm-staff [thanks Maria]
+FIX: patient search: gm-staff shall not ensure patient-ness [thanks Maria]
- 22.28
+ 22.30
-FIX: concatenation of the database schema structure
-
-IMPROVED: documentation for backup systemd .service file
+FIX: unique constraint on identity+name with multiple names per identity [thanks Maria]
+FIX: gm-staff permissions on dem.v_pat_addresses [thanks Maria]
+FIX: gm-staff permissions on dem.v_message_inbox [thanks Maria]
+FIX: permissions on org/unit tables/views
');
-- --------------------------------------------------------------
-select gm.log_script_insertion('v22-release_notes-fixup.sql', '22.28 at 1.8.18');
+select gm.log_script_insertion('v22-release_notes-fixup.sql', '22.30 at 1.8.20');
View it on GitLab: https://salsa.debian.org/med-team/gnumed-server/-/commit/2a7ad89760fdd3fbc74f009bea9328a781b1bec6
--
View it on GitLab: https://salsa.debian.org/med-team/gnumed-server/-/commit/2a7ad89760fdd3fbc74f009bea9328a781b1bec6
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20250401/d539e94b/attachment-0001.htm>
More information about the debian-med-commit
mailing list