From 9b697e8be6d1ceece2fb1633b0706da77fb2afb6 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Tue, 10 Sep 2024 18:02:31 +0200 Subject: [PATCH 01/37] release/24.10 --- openimis.json | 324 +++++++++++++++++++++++++------------------------- 1 file changed, 162 insertions(+), 162 deletions(-) diff --git a/openimis.json b/openimis.json index c84e177..73f367e 100644 --- a/openimis.json +++ b/openimis.json @@ -1,164 +1,164 @@ { - "modules": [ - { - "name": "core", - "pip": "git+https://github.com/openimis/openimis-be-core_py.git@develop#egg=openimis-be-core" - }, - { - "name": "individual", - "pip": "git+https://github.com/openimis/openimis-be-individual_py.git@develop#egg=openimis-be-individual" - }, - { - "name": "workflow", - "pip": "git+https://github.com/openimis/openimis-be-workflow_py.git@develop#egg=openimis-be-workflow" - }, - { - "name": "tasks_management", - "pip": "git+https://github.com/openimis/openimis-be-tasks_management_py.git@develop#egg=openimis-be-tasks_management" - }, - { - "name": "report", - "pip": "git+https://github.com/openimis/openimis-be-report_py.git@develop#egg=openimis-be-report" - }, - { - "name": "location", - "pip": "git+https://github.com/openimis/openimis-be-location_py.git@develop#egg=openimis-be-location" - }, - { - "name": "medical", - "pip": "git+https://github.com/openimis/openimis-be-medical_py.git@develop#egg=openimis-be-medical" - }, - { - "name": "medical_pricelist", - "pip": "git+https://github.com/openimis/openimis-be-medical_pricelist_py.git@develop#egg=openimis-be-medical_pricelist" - }, - { - "name": "product", - "pip": "git+https://github.com/openimis/openimis-be-product_py.git@develop#egg=openimis-be-product" - }, - { - "name": "insuree", - "pip": "git+https://github.com/openimis/openimis-be-insuree_py.git@develop#egg=openimis-be-insuree" - }, - { - "name": "policy", - "pip": "git+https://github.com/openimis/openimis-be-policy_py.git@develop#egg=openimis-be-policy" - }, - { - "name": "contribution", - "pip": "git+https://github.com/openimis/openimis-be-contribution_py.git@develop#egg=openimis-be-contribution" - }, - { - "name": "payer", - "pip": "git+https://github.com/openimis/openimis-be-payer_py.git@develop#egg=openimis-be-payer" - }, - { - "name": "payment", - "pip": "git+https://github.com/openimis/openimis-be-payment_py.git@develop#egg=openimis-be-payment" - }, - { - "name": "claim", - "pip": "git+https://github.com/openimis/openimis-be-claim_py.git@develop#egg=openimis-be-claim" - }, - { - "name": "claim_batch", - "pip": "git+https://github.com/openimis/openimis-be-claim_batch_py.git@develop#egg=openimis-be-claim_batch" - }, - { - "name": "tools", - "pip": "git+https://github.com/openimis/openimis-be-tools_py.git@develop#egg=openimis-be-tools" - }, - { - "name": "api_fhir_r4", - "pip": "git+https://github.com/openimis/openimis-be-api_fhir_r4_py.git@develop#egg=openimis-be-api_fhir_r4" - }, - { - "name": "calculation", - "pip": "git+https://github.com/openimis/openimis-be-calculation_py.git@develop#egg=openimis-be-calculation" - }, - { - "name": "contribution_plan", - "pip": "git+https://github.com/openimis/openimis-be-contribution_plan_py.git@develop#egg=openimis-be-contribution_plan" - }, - { - "name": "policyholder", - "pip": "git+https://github.com/openimis/openimis-be-policyholder_py.git@develop#egg=openimis-be-policyholder" - }, - { - "name": "contract", - "pip": "git+https://github.com/openimis/openimis-be-contract_py.git@develop#egg=openimis-be-contract" - }, - { - "name": "invoice", - "pip": "git+https://github.com/openimis/openimis-be-invoice_py.git@develop#egg=openimis-be-invoice" - }, - { - "name": "calcrule_contribution_legacy", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_contribution_legacy_py.git@develop#egg=openimis-be-calcrule_contribution_legacy" - }, - { - "name": "calcrule_third_party_payment", - "pip": "git+https://github.com/openimis/openimis-be-calcrule-third_party_payment_py.git@develop#egg=openimis-be-calcrule_third_party_payment" - }, - { - "name": "calcrule_capitation_payment", - "pip": "git+https://github.com/openimis/openimis-be-calcrule-capitation_payment_py.git@develop#egg=openimis-be-calcrule-capitation_payment" - }, - { - "name": "calcrule_commission", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_commission_py.git@develop#egg=openimis-be-calcrule_commission" - }, - { - "name": "calcrule_contribution_income_percentage", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_contribution_income_percentage_py.git@develop#egg=openimis-be-calcrule_contribution_income_percentage" - }, - { - "name": "calcrule_fees", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_fees_py.git@develop#egg=openimis-be-calcrule_fees" - }, - { - "name":"calcrule_unconditional_cash_payment", - "pip":"git+https://github.com/openimis/openimis-be-calcrule_unconditional_cash_payment_py.git@develop#egg=openimis-be-calcrule_unconditional_cash_payment" - }, - { - "name":"im_export", - "pip":"git+https://github.com/openimis/openimis-be-im_export_py.git@develop#egg=openimis-be-im_export" - }, - { - "name":"dhis2_etl", - "pip":"git+https://github.com/openimis/openimis-be-dhis2_etl_py.git@develop#egg=openimis-be-dhis2_etl" - }, - { - "name": "social_protection", - "pip": "git+https://github.com/openimis/openimis-be-social_protection_py.git@develop#egg=openimis-be-social_protection" - }, - { - "name": "opensearch_reports", - "pip": "git+https://github.com/openimis/openimis-be-opensearch_reports_py.git@develop#egg=openimis-be-opensearch_reports" - }, - { - "name": "payment_cycle", - "pip": "git+https://github.com/openimis/openimis-be-payment_cycle_py.git@develop#egg=openimis-be-payment_cycle" - }, - { - "name": "calcrule_social_protection", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_social_protection_py.git@develop#egg=openimis-be-calcrule_social_protection" - }, - { - "name": "payroll", - "pip": "git+https://github.com/openimis/openimis-be-payroll_py.git@develop#egg=openimis-be-payroll" - }, - { - "name": "controls", - "pip": "git+https://github.com/openimis/openimis-be-controls_py.git@develop#egg=openimis-be-controls" - }, - { - "name": "grievance_social_protection", - "pip": "git+https://github.com/openimis/openimis-be-grievance_social_protection_py.git@develop#egg=openimis-be-grievance_social_protection" - }, - { - "name": "claim_sampling", - "pip": "git+https://github.com/openimis/openimis-be-claim_sampling_py.git@develop#egg=openimis-be-claim_sampling" - } - ] + "modules": [ + { + "name": "core", + "pip": " 'git+https://github.com/openimis/openimis-be-core_py.git@release/24.10#egg=openimis-be-core" + }, + { + "name": "individual", + "pip": " 'git+https://github.com/openimis/openimis-be-individual_py.git@release/24.10#egg=openimis-be-individual" + }, + { + "name": "workflow", + "pip": " 'git+https://github.com/openimis/openimis-be-workflow_py.git@release/24.10#egg=openimis-be-workflow" + }, + { + "name": "tasks_management", + "pip": " 'git+https://github.com/openimis/openimis-be-tasks_management_py.git@release/24.10#egg=openimis-be-tasks_management" + }, + { + "name": "report", + "pip": " 'git+https://github.com/openimis/openimis-be-report_py.git@release/24.10#egg=openimis-be-report" + }, + { + "name": "location", + "pip": " 'git+https://github.com/openimis/openimis-be-location_py.git@release/24.10#egg=openimis-be-location" + }, + { + "name": "medical", + "pip": " 'git+https://github.com/openimis/openimis-be-medical_py.git@release/24.10#egg=openimis-be-medical" + }, + { + "name": "medical_pricelist", + "pip": " 'git+https://github.com/openimis/openimis-be-medical_pricelist_py.git@release/24.10#egg=openimis-be-medical_pricelist" + }, + { + "name": "product", + "pip": " 'git+https://github.com/openimis/openimis-be-product_py.git@release/24.10#egg=openimis-be-product" + }, + { + "name": "insuree", + "pip": " 'git+https://github.com/openimis/openimis-be-insuree_py.git@release/24.10#egg=openimis-be-insuree" + }, + { + "name": "policy", + "pip": " 'git+https://github.com/openimis/openimis-be-policy_py.git@release/24.10#egg=openimis-be-policy" + }, + { + "name": "contribution", + "pip": " 'git+https://github.com/openimis/openimis-be-contribution_py.git@release/24.10#egg=openimis-be-contribution" + }, + { + "name": "payer", + "pip": " 'git+https://github.com/openimis/openimis-be-payer_py.git@release/24.10#egg=openimis-be-payer" + }, + { + "name": "payment", + "pip": " 'git+https://github.com/openimis/openimis-be-payment_py.git@release/24.10#egg=openimis-be-payment" + }, + { + "name": "claim", + "pip": " 'git+https://github.com/openimis/openimis-be-claim_py.git@release/24.10#egg=openimis-be-claim" + }, + { + "name": "claim_batch", + "pip": " 'git+https://github.com/openimis/openimis-be-claim_batch_py.git@release/24.10#egg=openimis-be-claim_batch" + }, + { + "name": "tools", + "pip": " 'git+https://github.com/openimis/openimis-be-tools_py.git@release/24.10#egg=openimis-be-tools" + }, + { + "name": "api_fhir_r4", + "pip": " 'git+https://github.com/openimis/openimis-be-api_fhir_r4_py.git@release/24.10#egg=openimis-be-api_fhir_r4" + }, + { + "name": "calculation", + "pip": " 'git+https://github.com/openimis/openimis-be-calculation_py.git@release/24.10#egg=openimis-be-calculation" + }, + { + "name": "contribution_plan", + "pip": " 'git+https://github.com/openimis/openimis-be-contribution_plan_py.git@release/24.10#egg=openimis-be-contribution_plan" + }, + { + "name": "policyholder", + "pip": " 'git+https://github.com/openimis/openimis-be-policyholder_py.git@release/24.10#egg=openimis-be-policyholder" + }, + { + "name": "contract", + "pip": " 'git+https://github.com/openimis/openimis-be-contract_py.git@release/24.10#egg=openimis-be-contract" + }, + { + "name": "invoice", + "pip": " 'git+https://github.com/openimis/openimis-be-invoice_py.git@release/24.10#egg=openimis-be-invoice" + }, + { + "name": "calcrule_contribution_legacy", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_contribution_legacy_py.git@release/24.10#egg=openimis-be-calcrule_contribution_legacy" + }, + { + "name": "calcrule_third_party_payment", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_third_party_payment_py.git@release/24.10#egg=openimis-be-calcrule_third_party_payment" + }, + { + "name": "calcrule_capitation_payment", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_capitation_payment_py.git@release/24.10#egg=openimis-be-calcrule_capitation_payment" + }, + { + "name": "calcrule_commission", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_commission_py.git@release/24.10#egg=openimis-be-calcrule_commission" + }, + { + "name": "calcrule_contribution_income_percentage", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_contribution_income_percentage_py.git@release/24.10#egg=openimis-be-calcrule_contribution_income_percentage" + }, + { + "name": "calcrule_fees", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_fees_py.git@release/24.10#egg=openimis-be-calcrule_fees" + }, + { + "name": "calcrule_unconditional_cash_payment", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_unconditional_cash_payment_py.git@release/24.10#egg=openimis-be-calcrule_unconditional_cash_payment" + }, + { + "name": "im_export", + "pip": " 'git+https://github.com/openimis/openimis-be-im_export_py.git@release/24.10#egg=openimis-be-im_export" + }, + { + "name": "dhis2_etl", + "pip": " 'git+https://github.com/openimis/openimis-be-dhis2_etl_py.git@release/24.10#egg=openimis-be-dhis2_etl" + }, + { + "name": "social_protection", + "pip": " 'git+https://github.com/openimis/openimis-be-social_protection_py.git@release/24.10#egg=openimis-be-social_protection" + }, + { + "name": "opensearch_reports", + "pip": " 'git+https://github.com/openimis/openimis-be-opensearch_reports_py.git@release/24.10#egg=openimis-be-opensearch_reports" + }, + { + "name": "payment_cycle", + "pip": " 'git+https://github.com/openimis/openimis-be-payment_cycle_py.git@release/24.10#egg=openimis-be-payment_cycle" + }, + { + "name": "calcrule_social_protection", + "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_social_protection_py.git@release/24.10#egg=openimis-be-calcrule_social_protection" + }, + { + "name": "payroll", + "pip": " 'git+https://github.com/openimis/openimis-be-payroll_py.git@release/24.10#egg=openimis-be-payroll" + }, + { + "name": "controls", + "pip": " 'git+https://github.com/openimis/openimis-be-controls_py.git@release/24.10#egg=openimis-be-controls" + }, + { + "name": "grievance_social_protection", + "pip": " 'git+https://github.com/openimis/openimis-be-grievance_social_protection_py.git@release/24.10#egg=openimis-be-grievance_social_protection" + }, + { + "name": "claim_sampling", + "pip": " 'git+https://github.com/openimis/openimis-be-claim_sampling_py.git@release/24.10#egg=openimis-be-claim_sampling" + } + ] } From 9619a143442aab90e176fbbbab0b345003884e3f Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Tue, 10 Sep 2024 22:49:38 +0200 Subject: [PATCH 02/37] Update openimis.json --- openimis.json | 80 +++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/openimis.json b/openimis.json index 73f367e..8195bf1 100644 --- a/openimis.json +++ b/openimis.json @@ -2,163 +2,163 @@ "modules": [ { "name": "core", - "pip": " 'git+https://github.com/openimis/openimis-be-core_py.git@release/24.10#egg=openimis-be-core" + "pip": "git+https://github.com/openimis/openimis-be-core_py.git@release/24.10#egg=openimis-be-core" }, { "name": "individual", - "pip": " 'git+https://github.com/openimis/openimis-be-individual_py.git@release/24.10#egg=openimis-be-individual" + "pip": "git+https://github.com/openimis/openimis-be-individual_py.git@release/24.10#egg=openimis-be-individual" }, { "name": "workflow", - "pip": " 'git+https://github.com/openimis/openimis-be-workflow_py.git@release/24.10#egg=openimis-be-workflow" + "pip": "git+https://github.com/openimis/openimis-be-workflow_py.git@release/24.10#egg=openimis-be-workflow" }, { "name": "tasks_management", - "pip": " 'git+https://github.com/openimis/openimis-be-tasks_management_py.git@release/24.10#egg=openimis-be-tasks_management" + "pip": "git+https://github.com/openimis/openimis-be-tasks_management_py.git@release/24.10#egg=openimis-be-tasks_management" }, { "name": "report", - "pip": " 'git+https://github.com/openimis/openimis-be-report_py.git@release/24.10#egg=openimis-be-report" + "pip": "git+https://github.com/openimis/openimis-be-report_py.git@release/24.10#egg=openimis-be-report" }, { "name": "location", - "pip": " 'git+https://github.com/openimis/openimis-be-location_py.git@release/24.10#egg=openimis-be-location" + "pip": "git+https://github.com/openimis/openimis-be-location_py.git@release/24.10#egg=openimis-be-location" }, { "name": "medical", - "pip": " 'git+https://github.com/openimis/openimis-be-medical_py.git@release/24.10#egg=openimis-be-medical" + "pip": "git+https://github.com/openimis/openimis-be-medical_py.git@release/24.10#egg=openimis-be-medical" }, { "name": "medical_pricelist", - "pip": " 'git+https://github.com/openimis/openimis-be-medical_pricelist_py.git@release/24.10#egg=openimis-be-medical_pricelist" + "pip": "git+https://github.com/openimis/openimis-be-medical_pricelist_py.git@release/24.10#egg=openimis-be-medical_pricelist" }, { "name": "product", - "pip": " 'git+https://github.com/openimis/openimis-be-product_py.git@release/24.10#egg=openimis-be-product" + "pip": "git+https://github.com/openimis/openimis-be-product_py.git@release/24.10#egg=openimis-be-product" }, { "name": "insuree", - "pip": " 'git+https://github.com/openimis/openimis-be-insuree_py.git@release/24.10#egg=openimis-be-insuree" + "pip": "git+https://github.com/openimis/openimis-be-insuree_py.git@release/24.10#egg=openimis-be-insuree" }, { "name": "policy", - "pip": " 'git+https://github.com/openimis/openimis-be-policy_py.git@release/24.10#egg=openimis-be-policy" + "pip": "git+https://github.com/openimis/openimis-be-policy_py.git@release/24.10#egg=openimis-be-policy" }, { "name": "contribution", - "pip": " 'git+https://github.com/openimis/openimis-be-contribution_py.git@release/24.10#egg=openimis-be-contribution" + "pip": "git+https://github.com/openimis/openimis-be-contribution_py.git@release/24.10#egg=openimis-be-contribution" }, { "name": "payer", - "pip": " 'git+https://github.com/openimis/openimis-be-payer_py.git@release/24.10#egg=openimis-be-payer" + "pip": "git+https://github.com/openimis/openimis-be-payer_py.git@release/24.10#egg=openimis-be-payer" }, { "name": "payment", - "pip": " 'git+https://github.com/openimis/openimis-be-payment_py.git@release/24.10#egg=openimis-be-payment" + "pip": "git+https://github.com/openimis/openimis-be-payment_py.git@release/24.10#egg=openimis-be-payment" }, { "name": "claim", - "pip": " 'git+https://github.com/openimis/openimis-be-claim_py.git@release/24.10#egg=openimis-be-claim" + "pip": "git+https://github.com/openimis/openimis-be-claim_py.git@release/24.10#egg=openimis-be-claim" }, { "name": "claim_batch", - "pip": " 'git+https://github.com/openimis/openimis-be-claim_batch_py.git@release/24.10#egg=openimis-be-claim_batch" + "pip": "git+https://github.com/openimis/openimis-be-claim_batch_py.git@release/24.10#egg=openimis-be-claim_batch" }, { "name": "tools", - "pip": " 'git+https://github.com/openimis/openimis-be-tools_py.git@release/24.10#egg=openimis-be-tools" + "pip": "git+https://github.com/openimis/openimis-be-tools_py.git@release/24.10#egg=openimis-be-tools" }, { "name": "api_fhir_r4", - "pip": " 'git+https://github.com/openimis/openimis-be-api_fhir_r4_py.git@release/24.10#egg=openimis-be-api_fhir_r4" + "pip": "git+https://github.com/openimis/openimis-be-api_fhir_r4_py.git@release/24.10#egg=openimis-be-api_fhir_r4" }, { "name": "calculation", - "pip": " 'git+https://github.com/openimis/openimis-be-calculation_py.git@release/24.10#egg=openimis-be-calculation" + "pip": "git+https://github.com/openimis/openimis-be-calculation_py.git@release/24.10#egg=openimis-be-calculation" }, { "name": "contribution_plan", - "pip": " 'git+https://github.com/openimis/openimis-be-contribution_plan_py.git@release/24.10#egg=openimis-be-contribution_plan" + "pip": "git+https://github.com/openimis/openimis-be-contribution_plan_py.git@release/24.10#egg=openimis-be-contribution_plan" }, { "name": "policyholder", - "pip": " 'git+https://github.com/openimis/openimis-be-policyholder_py.git@release/24.10#egg=openimis-be-policyholder" + "pip": "git+https://github.com/openimis/openimis-be-policyholder_py.git@release/24.10#egg=openimis-be-policyholder" }, { "name": "contract", - "pip": " 'git+https://github.com/openimis/openimis-be-contract_py.git@release/24.10#egg=openimis-be-contract" + "pip": "git+https://github.com/openimis/openimis-be-contract_py.git@release/24.10#egg=openimis-be-contract" }, { "name": "invoice", - "pip": " 'git+https://github.com/openimis/openimis-be-invoice_py.git@release/24.10#egg=openimis-be-invoice" + "pip": "git+https://github.com/openimis/openimis-be-invoice_py.git@release/24.10#egg=openimis-be-invoice" }, { "name": "calcrule_contribution_legacy", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_contribution_legacy_py.git@release/24.10#egg=openimis-be-calcrule_contribution_legacy" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_contribution_legacy_py.git@release/24.10#egg=openimis-be-calcrule_contribution_legacy" }, { "name": "calcrule_third_party_payment", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_third_party_payment_py.git@release/24.10#egg=openimis-be-calcrule_third_party_payment" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_third_party_payment_py.git@release/24.10#egg=openimis-be-calcrule_third_party_payment" }, { "name": "calcrule_capitation_payment", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_capitation_payment_py.git@release/24.10#egg=openimis-be-calcrule_capitation_payment" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_capitation_payment_py.git@release/24.10#egg=openimis-be-calcrule_capitation_payment" }, { "name": "calcrule_commission", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_commission_py.git@release/24.10#egg=openimis-be-calcrule_commission" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_commission_py.git@release/24.10#egg=openimis-be-calcrule_commission" }, { "name": "calcrule_contribution_income_percentage", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_contribution_income_percentage_py.git@release/24.10#egg=openimis-be-calcrule_contribution_income_percentage" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_contribution_income_percentage_py.git@release/24.10#egg=openimis-be-calcrule_contribution_income_percentage" }, { "name": "calcrule_fees", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_fees_py.git@release/24.10#egg=openimis-be-calcrule_fees" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_fees_py.git@release/24.10#egg=openimis-be-calcrule_fees" }, { "name": "calcrule_unconditional_cash_payment", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_unconditional_cash_payment_py.git@release/24.10#egg=openimis-be-calcrule_unconditional_cash_payment" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_unconditional_cash_payment_py.git@release/24.10#egg=openimis-be-calcrule_unconditional_cash_payment" }, { "name": "im_export", - "pip": " 'git+https://github.com/openimis/openimis-be-im_export_py.git@release/24.10#egg=openimis-be-im_export" + "pip": "git+https://github.com/openimis/openimis-be-im_export_py.git@release/24.10#egg=openimis-be-im_export" }, { "name": "dhis2_etl", - "pip": " 'git+https://github.com/openimis/openimis-be-dhis2_etl_py.git@release/24.10#egg=openimis-be-dhis2_etl" + "pip": "git+https://github.com/openimis/openimis-be-dhis2_etl_py.git@release/24.10#egg=openimis-be-dhis2_etl" }, { "name": "social_protection", - "pip": " 'git+https://github.com/openimis/openimis-be-social_protection_py.git@release/24.10#egg=openimis-be-social_protection" + "pip": "git+https://github.com/openimis/openimis-be-social_protection_py.git@release/24.10#egg=openimis-be-social_protection" }, { "name": "opensearch_reports", - "pip": " 'git+https://github.com/openimis/openimis-be-opensearch_reports_py.git@release/24.10#egg=openimis-be-opensearch_reports" + "pip": "git+https://github.com/openimis/openimis-be-opensearch_reports_py.git@release/24.10#egg=openimis-be-opensearch_reports" }, { "name": "payment_cycle", - "pip": " 'git+https://github.com/openimis/openimis-be-payment_cycle_py.git@release/24.10#egg=openimis-be-payment_cycle" + "pip": "git+https://github.com/openimis/openimis-be-payment_cycle_py.git@release/24.10#egg=openimis-be-payment_cycle" }, { "name": "calcrule_social_protection", - "pip": " 'git+https://github.com/openimis/openimis-be-calcrule_social_protection_py.git@release/24.10#egg=openimis-be-calcrule_social_protection" + "pip": "git+https://github.com/openimis/openimis-be-calcrule_social_protection_py.git@release/24.10#egg=openimis-be-calcrule_social_protection" }, { "name": "payroll", - "pip": " 'git+https://github.com/openimis/openimis-be-payroll_py.git@release/24.10#egg=openimis-be-payroll" + "pip": "git+https://github.com/openimis/openimis-be-payroll_py.git@release/24.10#egg=openimis-be-payroll" }, { "name": "controls", - "pip": " 'git+https://github.com/openimis/openimis-be-controls_py.git@release/24.10#egg=openimis-be-controls" + "pip": "git+https://github.com/openimis/openimis-be-controls_py.git@release/24.10#egg=openimis-be-controls" }, { "name": "grievance_social_protection", - "pip": " 'git+https://github.com/openimis/openimis-be-grievance_social_protection_py.git@release/24.10#egg=openimis-be-grievance_social_protection" + "pip": "git+https://github.com/openimis/openimis-be-grievance_social_protection_py.git@release/24.10#egg=openimis-be-grievance_social_protection" }, { "name": "claim_sampling", - "pip": " 'git+https://github.com/openimis/openimis-be-claim_sampling_py.git@release/24.10#egg=openimis-be-claim_sampling" + "pip": "git+https://github.com/openimis/openimis-be-claim_sampling_py.git@release/24.10#egg=openimis-be-claim_sampling" } ] } From 00cc9ad4b71cd6787fc40c78ac804b6a902055a9 Mon Sep 17 00:00:00 2001 From: delcroip Date: Thu, 19 Sep 2024 15:49:36 +0200 Subject: [PATCH 03/37] using empty db --- .github/workflows/ci_assembly.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index d2c7e82..d86fbad 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -95,7 +95,6 @@ jobs: PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/03_views.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/04_functions.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/05_stored_procs.sql | grep . | uniq -c - PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/demo_db.sql | grep . | uniq -c env: DB_HOST: localhost DB_PORT: 5432 @@ -123,7 +122,7 @@ jobs: /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "DROP DATABASE IF EXISTS $DB_NAME_TEST" /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "CREATE DATABASE $DB_NAME_TEST" - /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullDemoDatabase.sql | grep . | uniq -c + /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullEmptyDatabase.sql | grep . | uniq -c env: DB_HOST: localhost DB_PORT: 1433 From c166e9a61149fc9a67d1c15252c7de88f47e74c3 Mon Sep 17 00:00:00 2001 From: delcroip Date: Thu, 19 Sep 2024 15:51:10 +0200 Subject: [PATCH 04/37] use empty for ci --- .github/workflows/ci_module.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index b13567c..daf1f8d 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -185,7 +185,7 @@ jobs: /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "DROP DATABASE IF EXISTS $DB_NAME_TEST" /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "CREATE DATABASE $DB_NAME_TEST" - /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullDemoDatabase.sql | grep . | uniq -c + /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullEmptyDatabase.sql | grep . | uniq -c env: DB_HOST: localhost DB_PORT: 1433 @@ -292,7 +292,6 @@ jobs: PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/03_views.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/04_functions.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/05_stored_procs.sql | grep . | uniq -c - PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/demo_db.sql | grep . | uniq -c env: DB_HOST: localhost @@ -396,7 +395,6 @@ jobs: PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/03_views.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/04_functions.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/05_stored_procs.sql | grep . | uniq -c - PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/demo_db.sql | grep . | uniq -c env: DB_HOST: localhost From 7809cecc3118dbcd4817ea9d3dea139badc45ef4 Mon Sep 17 00:00:00 2001 From: delcroip Date: Thu, 19 Sep 2024 17:08:14 +0200 Subject: [PATCH 05/37] reveret empty --- .github/workflows/ci_assembly.yml | 3 ++- .github/workflows/ci_module.yml | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index d86fbad..d2c7e82 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -95,6 +95,7 @@ jobs: PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/03_views.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/04_functions.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/05_stored_procs.sql | grep . | uniq -c + PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/demo_db.sql | grep . | uniq -c env: DB_HOST: localhost DB_PORT: 5432 @@ -122,7 +123,7 @@ jobs: /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "DROP DATABASE IF EXISTS $DB_NAME_TEST" /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "CREATE DATABASE $DB_NAME_TEST" - /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullEmptyDatabase.sql | grep . | uniq -c + /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullDemoDatabase.sql | grep . | uniq -c env: DB_HOST: localhost DB_PORT: 1433 diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index daf1f8d..b13567c 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -185,7 +185,7 @@ jobs: /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "DROP DATABASE IF EXISTS $DB_NAME_TEST" /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -Q "CREATE DATABASE $DB_NAME_TEST" - /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullEmptyDatabase.sql | grep . | uniq -c + /opt/mssql-tools/bin/sqlcmd -S $DB_HOST -U $DB_USER -P $DB_PASSWORD -d $DB_NAME_TEST -i ./sql_mssql/output/fullDemoDatabase.sql | grep . | uniq -c env: DB_HOST: localhost DB_PORT: 1433 @@ -292,6 +292,7 @@ jobs: PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/03_views.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/04_functions.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/05_stored_procs.sql | grep . | uniq -c + PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/demo_db.sql | grep . | uniq -c env: DB_HOST: localhost @@ -395,6 +396,7 @@ jobs: PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/03_views.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/04_functions.sql | grep . | uniq -c PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/05_stored_procs.sql | grep . | uniq -c + PGPASSWORD=GitHub999 psql -U $DB_USER -h $DB_HOST -d $DB_NAME_TEST -f ./sql_psql/database\ scripts/demo_db.sql | grep . | uniq -c env: DB_HOST: localhost From 782478cce64d7689915c2c6be7f997841a242fab Mon Sep 17 00:00:00 2001 From: delcroip Date: Mon, 23 Sep 2024 09:01:56 +0200 Subject: [PATCH 06/37] better pull --- script/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/utils.py b/script/utils.py index f7158e4..25d48aa 100644 --- a/script/utils.py +++ b/script/utils.py @@ -10,7 +10,7 @@ def parse_pip(pip_str): def parse_pip_branch(pip_str): if "https://github.com" in pip_str: - match = re.search(r'github.com/.+.git@([\w_-]+).*',pip_str ) + match = re.search(r'github.com/.+.git@([\w_\-\/\.]+).*',pip_str ) return match.group(1) else: print("Error branch not found") From c4ccfe56ae3ff3befa550ea35a8d742f0dba78b1 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 23 Sep 2024 17:38:02 +0200 Subject: [PATCH 07/37] Update openimis.json (#292) --- openimis.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openimis.json b/openimis.json index 8195bf1..acb02fc 100644 --- a/openimis.json +++ b/openimis.json @@ -159,6 +159,10 @@ { "name": "claim_sampling", "pip": "git+https://github.com/openimis/openimis-be-claim_sampling_py.git@release/24.10#egg=openimis-be-claim_sampling" + }, + { + "name": "deduplication", + "pip": "git+https://github.com/openimis/openimis-be-deduplication_py.git@release/24.10#egg=openimis-be-deduplication" } ] } From a2e0833d60684299dc7f5443903e20d4478ce41c Mon Sep 17 00:00:00 2001 From: delcroip Date: Thu, 3 Oct 2024 12:10:41 +0200 Subject: [PATCH 08/37] correct http code in case of error --- openIMIS/openIMIS/openimisapps.py | 2 +- openIMIS/openIMIS/views.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openIMIS/openIMIS/openimisapps.py b/openIMIS/openIMIS/openimisapps.py index c504da8..aa78ad4 100644 --- a/openIMIS/openIMIS/openimisapps.py +++ b/openIMIS/openIMIS/openimisapps.py @@ -28,7 +28,7 @@ def get_locale_folders(): with resources.path(mod_name, "__init__.py") as path: apps.append(path.parent.parent) except ModuleNotFoundError: - raise logger.error(f"Module \"{mod_name}\" not found.") + logger.error(f"Module \"{mod_name}\" not found.") for topdir in ["."] + apps: for dirpath, dirnames, filenames in os.walk(topdir, topdown=True): diff --git a/openIMIS/openIMIS/views.py b/openIMIS/openIMIS/views.py index a359883..ad6d94e 100644 --- a/openIMIS/openIMIS/views.py +++ b/openIMIS/openIMIS/views.py @@ -46,6 +46,7 @@ def _get_response(self, request, data, show_graphiql=False): response["errors"] = [ self.format_error(e) for e in execution_result.errors ] + status_code = 500 if execution_result.invalid: status_code = 400 From 13a65b7cb4c426b54305fe69e23a3966193c5fa4 Mon Sep 17 00:00:00 2001 From: delcroip Date: Tue, 15 Oct 2024 13:41:45 +0200 Subject: [PATCH 09/37] use right gettext in calcrule template --- openIMIS/developer_tools/skeletons/calculation_rule.py.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openIMIS/developer_tools/skeletons/calculation_rule.py.template b/openIMIS/developer_tools/skeletons/calculation_rule.py.template index 5511e52..2fc7576 100644 --- a/openIMIS/developer_tools/skeletons/calculation_rule.py.template +++ b/openIMIS/developer_tools/skeletons/calculation_rule.py.template @@ -2,7 +2,7 @@ import uuid ##from {{module_name}}.apps import AbsCalculationRule ##from {{module_name}}.config import CLASS_RULE_PARAM_VALIDATION, DESCRIPTION_CONTRIBUTION_VALUATION, FROM_TO from django.core.exceptions import ValidationError -from gettext import gettext as _ +from django.utils.translation import gettext as _ ##from core.signals import * ##from core import datetime from django.contrib.contenttypes.models import ContentType From feca4bda9a866c0b72662d95356f4f498f3a8086 Mon Sep 17 00:00:00 2001 From: delcroip Date: Tue, 15 Oct 2024 13:42:06 +0200 Subject: [PATCH 10/37] add calcrule_validations --- .vscode/launch.json | 2 ++ openimis.json | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index 274fe3c..2224202 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,6 +21,7 @@ "product", "insuree", "policy", + "calcrule_validations", "contribution", "payer", "payment", @@ -213,6 +214,7 @@ "opensearch_reports", "payment_cycle", "calcrule_social_protection", + "calcrule_validations", "payroll" ], "django": true, diff --git a/openimis.json b/openimis.json index acb02fc..5d30c80 100644 --- a/openimis.json +++ b/openimis.json @@ -108,6 +108,10 @@ "name": "calcrule_commission", "pip": "git+https://github.com/openimis/openimis-be-calcrule_commission_py.git@release/24.10#egg=openimis-be-calcrule_commission" }, + { + "name": "calcrule_validations", + "pip": "git+https://github.com/openimis/openimis-be-calcrule_validations_py.git@release/24.10#egg=openimis-be-calcrule_validations" + }, { "name": "calcrule_contribution_income_percentage", "pip": "git+https://github.com/openimis/openimis-be-calcrule_contribution_income_percentage_py.git@release/24.10#egg=openimis-be-calcrule_contribution_income_percentage" From d9fd172ce52a15c0567bfee8607c6a52e45477cd Mon Sep 17 00:00:00 2001 From: delcroip Date: Thu, 17 Oct 2024 12:27:46 +0200 Subject: [PATCH 11/37] correct http code in case of error --- openIMIS/developer_tools/skeletons/calculation_rule.py.template | 2 +- openIMIS/openIMIS/openimisapps.py | 2 +- openIMIS/openIMIS/views.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openIMIS/developer_tools/skeletons/calculation_rule.py.template b/openIMIS/developer_tools/skeletons/calculation_rule.py.template index 5511e52..2fc7576 100644 --- a/openIMIS/developer_tools/skeletons/calculation_rule.py.template +++ b/openIMIS/developer_tools/skeletons/calculation_rule.py.template @@ -2,7 +2,7 @@ import uuid ##from {{module_name}}.apps import AbsCalculationRule ##from {{module_name}}.config import CLASS_RULE_PARAM_VALIDATION, DESCRIPTION_CONTRIBUTION_VALUATION, FROM_TO from django.core.exceptions import ValidationError -from gettext import gettext as _ +from django.utils.translation import gettext as _ ##from core.signals import * ##from core import datetime from django.contrib.contenttypes.models import ContentType diff --git a/openIMIS/openIMIS/openimisapps.py b/openIMIS/openIMIS/openimisapps.py index c504da8..aa78ad4 100644 --- a/openIMIS/openIMIS/openimisapps.py +++ b/openIMIS/openIMIS/openimisapps.py @@ -28,7 +28,7 @@ def get_locale_folders(): with resources.path(mod_name, "__init__.py") as path: apps.append(path.parent.parent) except ModuleNotFoundError: - raise logger.error(f"Module \"{mod_name}\" not found.") + logger.error(f"Module \"{mod_name}\" not found.") for topdir in ["."] + apps: for dirpath, dirnames, filenames in os.walk(topdir, topdown=True): diff --git a/openIMIS/openIMIS/views.py b/openIMIS/openIMIS/views.py index a359883..34dca7c 100644 --- a/openIMIS/openIMIS/views.py +++ b/openIMIS/openIMIS/views.py @@ -46,6 +46,7 @@ def _get_response(self, request, data, show_graphiql=False): response["errors"] = [ self.format_error(e) for e in execution_result.errors ] + # status_code = 500 per spec GQL must return 200 even for error if execution_result.invalid: status_code = 400 From f4851a08f4adc601bbef3ec1782f4de89f3f9642 Mon Sep 17 00:00:00 2001 From: delcroip Date: Mon, 21 Oct 2024 09:17:33 +0200 Subject: [PATCH 12/37] add cache for coverage and locations --- openIMIS/openIMIS/settings.py | 42 +++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/openIMIS/openIMIS/settings.py b/openIMIS/openIMIS/settings.py index 5ea2d0c..faaf152 100644 --- a/openIMIS/openIMIS/settings.py +++ b/openIMIS/openIMIS/settings.py @@ -10,6 +10,7 @@ from datetime import timedelta from cryptography.hazmat.primitives import serialization + load_dotenv() # Makes openimis_apps available to other modules @@ -453,14 +454,41 @@ def SITE_URL(): if 'CELERY_RESULT_BACKEND' in os.environ: CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND") -if 'CACHE_BACKEND' in os.environ and 'CACHE_URL' in os.environ: - CACHES = { - 'default': { - 'BACKEND': os.environ.get('CACHE_BACKEND'), - 'LOCATION': os.environ.get("CACHE_URL"), - 'OPTIONS': json.loads(os.environ.get("CACHE_OPTIONS", "")) - } +if 'CACHE_BACKEND' in os.environ and 'CACHE_URL' in os.environ: + CACHE_BACKEND = os.environ.get('CACHE_BACKEND') + CACHE_URL = os.environ.get("CACHE_URL") + CACHE_OPTIONS = os.environ.get("CACHE_OPTIONS", None) + if CACHE_OPTIONS: + CACHE_OPTIONS = json.loads(CACHE_OPTIONS) +else: + CACHE_BACKEND = 'django.core.cache.backends.locmem.LocMemCache' + CACHE_URL = None + CACHE_OPTIONS = None + +CACHE_PARAM = {} +CACHE_PARAM['BACKEND'] = CACHE_BACKEND +if CACHE_URL: + CACHE_PARAM['LOCATION'] = CACHE_URL + +if CACHE_OPTIONS: + CACHE_PARAM['OPTIONS'] = CACHE_OPTIONS + + +CACHES = { + 'default': { + **CACHE_PARAM, + 'KEY_PREFIX': "oi" + }, + 'location': { + **CACHE_PARAM, + 'KEY_PREFIX': "loc" + }, + 'coverage': { + **CACHE_PARAM, + 'KEY_PREFIX': "cov" + } +} # This scheduler config will: # - Store jobs in the project database From 2832841a999172d22883ca8e2c03e45492c05f73 Mon Sep 17 00:00:00 2001 From: delcroip Date: Wed, 23 Oct 2024 11:56:36 +0200 Subject: [PATCH 13/37] add error logging for graphen --- openIMIS/openIMIS/tracer.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/openIMIS/openIMIS/tracer.py b/openIMIS/openIMIS/tracer.py index 1be613c..c274fd0 100644 --- a/openIMIS/openIMIS/tracer.py +++ b/openIMIS/openIMIS/tracer.py @@ -1,6 +1,7 @@ import logging from contextlib import contextmanager -from .settings import IS_SENTRY_ENABLED +from .settings import IS_SENTRY_ENABLED, DEBUG +import traceback logger = logging.getLogger(__name__) @@ -30,6 +31,21 @@ def trace(*args, **kwargs): class TracerMiddleware: def resolve(self, next, root, info, **kwargs): path = ".".join([str(x) for x in info.path]) + # Start tracing with trace(op="graphql.resolve") as span: - span.set_tag("path", path) - return next(root, info, **kwargs) + span.set_tag("path", path) + try: + # Proceed with the next middleware or resolver + return next(root, info, **kwargs) + except Exception as e: + # Log the exception with its traceback + if DEBUG: + logger.error("An error occurred: %s", str(e)) + logger.error("Traceback: %s", traceback.format_exc()) + + # Optionally add error information to the trace + span.set_tag("error", True) + span.log_kv({"exception": str(e), "traceback": traceback.format_exc()}) + + # Re-raise the exception to allow GraphQL to handle it + raise e \ No newline at end of file From f1ca8c5a6fa87bfe2da635be33dfe0795945ba2d Mon Sep 17 00:00:00 2001 From: sniedzielski Date: Wed, 23 Oct 2024 12:54:27 +0200 Subject: [PATCH 14/37] added etl api module --- openimis.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openimis.json b/openimis.json index 5d30c80..9bb5119 100644 --- a/openimis.json +++ b/openimis.json @@ -167,6 +167,10 @@ { "name": "deduplication", "pip": "git+https://github.com/openimis/openimis-be-deduplication_py.git@release/24.10#egg=openimis-be-deduplication" - } + }, + { + "name": "api_etl", + "pip": "git+https://github.com/openimis/openimis-be-api_etl_py.git@release/24.10#egg=openimis-be-api_etl" + } ] } From ab5e49e134d39fab52bbcbb042415a666437821c Mon Sep 17 00:00:00 2001 From: sniedzielski Date: Wed, 23 Oct 2024 12:57:12 +0200 Subject: [PATCH 15/37] added etl --- openimis.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openimis.json b/openimis.json index 9bb5119..9d9f49c 100644 --- a/openimis.json +++ b/openimis.json @@ -169,8 +169,8 @@ "pip": "git+https://github.com/openimis/openimis-be-deduplication_py.git@release/24.10#egg=openimis-be-deduplication" }, { - "name": "api_etl", - "pip": "git+https://github.com/openimis/openimis-be-api_etl_py.git@release/24.10#egg=openimis-be-api_etl" - } + "name": "api_etl", + "pip": "git+https://github.com/openimis/openimis-be-api_etl_py.git@release/24.10#egg=openimis-be-api_etl" + } ] } From 56cb3d8cb04096449a46334d9ccd310b090824d4 Mon Sep 17 00:00:00 2001 From: sniedzielski Date: Mon, 28 Oct 2024 11:50:45 +0100 Subject: [PATCH 16/37] hotfix: added missing opensearch dsl config --- openIMIS/openIMIS/settings.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openIMIS/openIMIS/settings.py b/openIMIS/openIMIS/settings.py index faaf152..32515f0 100644 --- a/openIMIS/openIMIS/settings.py +++ b/openIMIS/openIMIS/settings.py @@ -173,6 +173,7 @@ def SITE_URL(): "developer_tools", "drf_spectacular", # Swagger UI for FHIR API "axes", + "django_opensearch_dsl", ] INSTALLED_APPS += OPENIMIS_APPS INSTALLED_APPS += ["apscheduler_runner", "signal_binding"] # Signal binding should be last installed module @@ -631,6 +632,17 @@ def SITE_URL(): USE_X_FORWARDED_HOST = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +OPENSEARCH_DSL = { + 'default': { + 'hosts': os.environ.get("OPENSEARCH_HOST", '0.0.0.0:9200'), + 'http_auth': ( + f"{os.environ.get('OPENSEARCH_ADMIN')}", + f"{os.environ.get('OPENSEARCH_PASSWORD')}" + ), + 'timeout': 120, + } +} + PASSWORD_MIN_LENGTH = int(os.getenv('PASSWORD_MIN_LENGTH', 8)) PASSWORD_UPPERCASE = int(os.getenv('PASSWORD_UPPERCASE', 1)) PASSWORD_LOWERCASE = int(os.getenv('PASSWORD_LOWERCASE', 1)) From beb4157fe439241250476c604bcb811ac544586d Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 13:08:46 +0100 Subject: [PATCH 17/37] adding opensearch service to CI --- .github/workflows/ci_assembly.yml | 10 ++++++++++ .github/workflows/ci_module.yml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index d2c7e82..6065bd2 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -44,6 +44,16 @@ jobs: --health-interval 10s --health-timeout 5s --health-retries 10 + opensearch: + image: opensearchproject/opensearch:latest + ports: + - 9200:9200 + env: + discovery.type: single-node + cluster.name: my_opensearch_local + http.port: 9200 + plugins.security.ssl.http.enabled: false + plugins.security.disabled: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index b13567c..0deff13 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -124,6 +124,16 @@ jobs: runs-on: ubuntu-20.04 needs: build_backend services: + opensearch: + image: opensearchproject/opensearch:latest + ports: + - 9200:9200 + env: + discovery.type: single-node + cluster.name: my_opensearch_local + http.port: 9200 + plugins.security.ssl.http.enabled: false + plugins.security.disabled: true mssql: image: mcr.microsoft.com/mssql/server:2017-latest env: @@ -233,6 +243,16 @@ jobs: runs-on: ubuntu-20.04 needs: build_backend services: + opensearch: + image: opensearchproject/opensearch:latest + ports: + - 9200:9200 + env: + discovery.type: single-node + cluster.name: my_opensearch_local + http.port: 9200 + plugins.security.ssl.http.enabled: false + plugins.security.disabled: true pgsql: image: postgres env: @@ -337,6 +357,16 @@ jobs: runs-on: ubuntu-20.04 needs: build_backend services: + opensearch: + image: opensearchproject/opensearch:latest + ports: + - 9200:9200 + env: + discovery.type: single-node + cluster.name: my_opensearch_local + http.port: 9200 + plugins.security.ssl.http.enabled: false + plugins.security.disabled: true pgsql: image: postgres env: From 831b53f3f8c8fba7c9ae5983386be43fcdfeffa1 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 13:23:05 +0100 Subject: [PATCH 18/37] adding OS credentials --- .env.example | 4 ++++ .github/workflows/ci_assembly.yml | 5 +++++ .github/workflows/ci_module.yml | 12 ++++++++++++ 3 files changed, 21 insertions(+) diff --git a/.env.example b/.env.example index b87daf7..f93edc3 100644 --- a/.env.example +++ b/.env.example @@ -61,3 +61,7 @@ RATELIMIT_RATE=150/m # Rate limit (150 requests per minute) RATELIMIT_METHOD=ALL # HTTP methods to rate limit; 'ALL' means all methods RATELIMIT_GROUP=graphql # Group name for the rate limit RATELIMIT_SKIP_TIMEOUT=False # Whether to skip rate limiting during c + + +OPENSEARCH_ADMIN=admin +OPENSEARCH_PASSWORD=admin \ No newline at end of file diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 6065bd2..3fee55c 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -54,6 +54,9 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true + OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin + OPENSEARCH_ADMIN_USER: admin + steps: - uses: actions/checkout@v2 @@ -166,6 +169,8 @@ jobs: #DEV_SERVER: true SITE_ROOT: api CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} + OPENSEARCH_ADMIN: admin + OPENSEARCH_PASSWORD: admin - name: Django tests MSSQL working-directory: ./openIMIS diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index 0deff13..657ccd4 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -134,6 +134,8 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true + OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin + OPENSEARCH_ADMIN_USER: admin mssql: image: mcr.microsoft.com/mssql/server:2017-latest env: @@ -238,6 +240,8 @@ jobs: #REMOTE_USER_AUTHENTICATION: False CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV + OPENSEARCH_ADMIN: admin + OPENSEARCH_PASSWORD: admin ci_module_psql_test_module_only: name: Run Module Tests (PSQL) runs-on: ubuntu-20.04 @@ -253,6 +257,8 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true + OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin + OPENSEARCH_ADMIN_USER: admin pgsql: image: postgres env: @@ -352,6 +358,8 @@ jobs: SITE_ROOT: api CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV + OPENSEARCH_ADMIN: admin + OPENSEARCH_PASSWORD: admin ci_module_psql_test: name: Run All Tests (PSQL) runs-on: ubuntu-20.04 @@ -367,6 +375,8 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true + OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin + OPENSEARCH_ADMIN_USER: admin pgsql: image: postgres env: @@ -465,6 +475,8 @@ jobs: SITE_ROOT: api CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV + OPENSEARCH_ADMIN: admin + OPENSEARCH_PASSWORD: admin - name: Generate Coverage Report if: always() working-directory: ./openimis/openIMIS From 703674e2c01bdca7eeac6b10e7e04c491537d54e Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 13:33:26 +0100 Subject: [PATCH 19/37] using default pass --- .github/workflows/ci_assembly.yml | 2 -- .github/workflows/ci_module.yml | 9 +++------ docker-compose.yml | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 3fee55c..632a3a9 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -54,8 +54,6 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true - OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin - OPENSEARCH_ADMIN_USER: admin steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index 657ccd4..37cc121 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -134,8 +134,7 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true - OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin - OPENSEARCH_ADMIN_USER: admin + mssql: image: mcr.microsoft.com/mssql/server:2017-latest env: @@ -257,8 +256,7 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true - OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin - OPENSEARCH_ADMIN_USER: admin + pgsql: image: postgres env: @@ -375,8 +373,7 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false plugins.security.disabled: true - OPENSEARCH_INITIAL_ADMIN_PASSWORD: admin - OPENSEARCH_ADMIN_USER: admin + pgsql: image: postgres env: diff --git a/docker-compose.yml b/docker-compose.yml index 1b3f7e7..2a6e70d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,6 +41,21 @@ services: - database-mssql:/var/opt/mssql/data ports: - 1433:1433 + opensearch: + image: opensearchproject/opensearch:latest + env_file: + - ".env.openSearch" + environment: + - "discovery.type=single-node" + - "cluster.name=${CLUSTER_NAME:-my_opensearch_local}" + - "http.port=${OPEN_SEARCH_HTTP_PORT:-9200}" + - "plugins.security.ssl.http.enabled=${SLL_HTTP_ENABLED:-false}" + - "plugins.security.disabled=true" + + volumes: + - "opensearch-data1:/usr/share/opensearch/data" + networks: + openimis-net: volumes: database: database-mssql: From 4a014337554e073b05d881f9e89c3e8dd15a9c10 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 14:18:02 +0100 Subject: [PATCH 20/37] enforce pasword --- .github/workflows/ci_assembly.yml | 4 ++-- .github/workflows/ci_module.yml | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 632a3a9..3cb2ec3 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -53,8 +53,6 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - plugins.security.disabled: true - steps: - uses: actions/checkout@v2 @@ -196,3 +194,5 @@ jobs: SITE_ROOT: api #REMOTE_USER_AUTHENTICATION: False CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} + OPENSEARCH_ADMIN: admin + OPENSEARCH_PASSWORD: admin diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index 37cc121..7ea3190 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -133,7 +133,6 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - plugins.security.disabled: true mssql: image: mcr.microsoft.com/mssql/server:2017-latest @@ -255,7 +254,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - plugins.security.disabled: true + pgsql: image: postgres @@ -372,7 +371,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - plugins.security.disabled: true + pgsql: image: postgres From bd2567eb720c77102fdc1a1239f89d79db5f0324 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 14:36:27 +0100 Subject: [PATCH 21/37] right URL --- .github/workflows/ci_assembly.yml | 11 +++++++++++ .github/workflows/ci_module.yml | 8 +++++++- openIMIS/openIMIS/settings.py | 7 +++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 3cb2ec3..7a48bd9 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -53,6 +53,11 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false + options: >- + --health-cmd="curl -f http://localhost:9200/_cluster/health || exit 1" + --health-interval=10s + --health-timeout=5s + --health-retries=5 steps: - uses: actions/checkout@v2 @@ -167,6 +172,9 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: admin + OPEN_SEARCH_HTTP_PORT: 9200 + OPENSEARCH_HOST: opensearch + OPENSEARCH_HOSTS: http://opensearch:9200 - name: Django tests MSSQL working-directory: ./openIMIS @@ -196,3 +204,6 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: admin + OPEN_SEARCH_HTTP_PORT: 9200 + OPENSEARCH_HOST: opensearch + OPENSEARCH_HOSTS: http://opensearch:9200 diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index 7ea3190..f9e5185 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -357,6 +357,9 @@ jobs: MODE: DEV OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: admin + OPEN_SEARCH_HTTP_PORT: 9200 + OPENSEARCH_HOST: opensearch + OPENSEARCH_HOSTS: http://opensearch:9200 ci_module_psql_test: name: Run All Tests (PSQL) runs-on: ubuntu-20.04 @@ -473,6 +476,9 @@ jobs: MODE: DEV OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: admin + OPEN_SEARCH_HTTP_PORT: 9200 + OPENSEARCH_HOST: opensearch + OPENSEARCH_HOSTS: http://opensearch:9200 - name: Generate Coverage Report if: always() working-directory: ./openimis/openIMIS @@ -530,7 +536,7 @@ jobs: # Flake8 Report export MODULE_NAME="$(echo $GITHUB_REPOSITORY | sed 's#^openimis/openimis-be-\(.*\)_py$#\1#')" MOD_DIR="../current-module/$MODULE_NAME" - python -m flake8 --output-file=flake8-report.txt $MOD_DIR --exit-zero + python -m flake8 --output-file=flake8-report.txt $MOD_DIR --exit-zero --ignore W503 sed -i 's|\.\./current-module/||g' flake8-report.txt python -m flake8 $MOD_DIR diff --git a/openIMIS/openIMIS/settings.py b/openIMIS/openIMIS/settings.py index 32515f0..9cce155 100644 --- a/openIMIS/openIMIS/settings.py +++ b/openIMIS/openIMIS/settings.py @@ -632,9 +632,12 @@ def SITE_URL(): USE_X_FORWARDED_HOST = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +OPENSEARCH_HOST = os.environ.get("OPENSEARCH_HOST", "0.0.0.0") +OPEN_SEARCH_HTTP_PORT = os.environ.get("OPEN_SEARCH_HTTP_PORT", "9200") + OPENSEARCH_DSL = { 'default': { - 'hosts': os.environ.get("OPENSEARCH_HOST", '0.0.0.0:9200'), + 'hosts': f"{OPENSEARCH_HOST}:{OPEN_SEARCH_HTTP_PORT}", 'http_auth': ( f"{os.environ.get('OPENSEARCH_ADMIN')}", f"{os.environ.get('OPENSEARCH_PASSWORD')}" @@ -647,4 +650,4 @@ def SITE_URL(): PASSWORD_UPPERCASE = int(os.getenv('PASSWORD_UPPERCASE', 1)) PASSWORD_LOWERCASE = int(os.getenv('PASSWORD_LOWERCASE', 1)) PASSWORD_DIGITS = int(os.getenv('PASSWORD_DIGITS', 1)) -PASSWORD_SYMBOLS = int(os.getenv('PASSWORD_SYMBOLS', 1)) +PASSWORD_SYMBOLS = int(os.getenv('PASSWORD_SYMBOLS', 1)) \ No newline at end of file From d7b2d33a3c85b8ebaeb45ce4008a611990ecb0ad Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 14:40:30 +0100 Subject: [PATCH 22/37] quoting urls --- .github/workflows/ci_assembly.yml | 12 ++++++------ .github/workflows/ci_module.yml | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 7a48bd9..7bee722 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -159,8 +159,8 @@ jobs: SECRET_KEY: secret MODE: DEV DB_DEFAULT: postgresql - CELERY_BROKER_URL": "memory://openIMIS-test//" - CELERY_RESULT_BACKEND": "cache+memory://openIMIS-test//" + CELERY_BROKER_URL: "memory://openIMIS-test//" + CELERY_RESULT_BACKEND: "cache+memory://openIMIS-test//" #DJANGO_SETTINGS_MODULE: hat.settings DB_HOST: localhost DB_PORT: 5432 @@ -174,7 +174,7 @@ jobs: OPENSEARCH_PASSWORD: admin OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: http://opensearch:9200 + OPENSEARCH_HOSTS: "http://opensearch:9200" - name: Django tests MSSQL working-directory: ./openIMIS @@ -190,8 +190,8 @@ jobs: SECRET_KEY: secret MODE: DEV DB_DEFAULT: mssql - CELERY_BROKER_URL": "memory://openIMIS-test//" - CELERY_RESULT_BACKEND": "cache+memory://openIMIS-test//" + CELERY_BROKER_URL: "memory://openIMIS-test//" + CELERY_RESULT_BACKEND: "cache+memory://openIMIS-test//" #DJANGO_SETTINGS_MODULE: hat.settings DB_HOST: localhost DB_PORT: 1433 @@ -206,4 +206,4 @@ jobs: OPENSEARCH_PASSWORD: admin OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: http://opensearch:9200 + OPENSEARCH_HOSTS: "http://opensearch:9200" diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index f9e5185..4cf2fa8 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -359,7 +359,7 @@ jobs: OPENSEARCH_PASSWORD: admin OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: http://opensearch:9200 + OPENSEARCH_HOSTS: "http://opensearch:9200" ci_module_psql_test: name: Run All Tests (PSQL) runs-on: ubuntu-20.04 @@ -478,7 +478,7 @@ jobs: OPENSEARCH_PASSWORD: admin OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: http://opensearch:9200 + OPENSEARCH_HOSTS: "http://opensearch:9200" - name: Generate Coverage Report if: always() working-directory: ./openimis/openIMIS From df1761874f1d35dbd3711579f0e1fd06b7b27b1f Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 14:48:41 +0100 Subject: [PATCH 23/37] fixing health checks --- .github/workflows/ci_assembly.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 7bee722..0a8f37f 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -54,10 +54,10 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false options: >- - --health-cmd="curl -f http://localhost:9200/_cluster/health || exit 1" - --health-interval=10s - --health-timeout=5s - --health-retries=5 + --health-cmd "curl -f http://localhost:9200/_cluster/health || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 5 steps: - uses: actions/checkout@v2 From 7a7c378d11067b8557761aea6f276e222e809f00 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 14:51:58 +0100 Subject: [PATCH 24/37] fixing indent --- .github/workflows/ci_assembly.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 0a8f37f..a72651f 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -53,11 +53,11 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - options: >- - --health-cmd "curl -f http://localhost:9200/_cluster/health || exit 1" - --health-interval 10s - --health-timeout 5s - --health-retries 5 + options: >- + --health-cmd "curl -f http://localhost:9200/_cluster/health || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 5 steps: - uses: actions/checkout@v2 From 143cf060aee42a113127dd9bc6b4fb261df1def2 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 14:57:37 +0100 Subject: [PATCH 25/37] default pass --- .env.example | 2 +- .github/workflows/ci_assembly.yml | 5 +++-- .github/workflows/ci_module.yml | 9 ++++++--- docker-compose.yml | 1 + 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index f93edc3..6bb5e2c 100644 --- a/.env.example +++ b/.env.example @@ -64,4 +64,4 @@ RATELIMIT_SKIP_TIMEOUT=False # Whether to skip rate limiting during c OPENSEARCH_ADMIN=admin -OPENSEARCH_PASSWORD=admin \ No newline at end of file +OPENSEARCH_PASSWORD=ThisIs4ü \ No newline at end of file diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index a72651f..f2ef673 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -53,6 +53,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false + OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü options: >- --health-cmd "curl -f http://localhost:9200/_cluster/health || exit 1" --health-interval 10s @@ -171,7 +172,7 @@ jobs: SITE_ROOT: api CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: admin + OPENSEARCH_PASSWORD: ThisIs4ü OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" @@ -203,7 +204,7 @@ jobs: #REMOTE_USER_AUTHENTICATION: False CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: admin + OPENSEARCH_PASSWORD: ThisIs4ü OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index 4cf2fa8..bc73bd0 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -133,6 +133,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false + OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü mssql: image: mcr.microsoft.com/mssql/server:2017-latest @@ -239,7 +240,7 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: admin + OPENSEARCH_PASSWORD: ThisIs4ü ci_module_psql_test_module_only: name: Run Module Tests (PSQL) runs-on: ubuntu-20.04 @@ -254,6 +255,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false + OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü pgsql: @@ -356,7 +358,7 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: admin + OPENSEARCH_PASSWORD: ThisIs4ü OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" @@ -374,6 +376,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false + OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü pgsql: @@ -475,7 +478,7 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: admin + OPENSEARCH_PASSWORD: ThisIs4ü OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" diff --git a/docker-compose.yml b/docker-compose.yml index 2a6e70d..61e70c0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -51,6 +51,7 @@ services: - "http.port=${OPEN_SEARCH_HTTP_PORT:-9200}" - "plugins.security.ssl.http.enabled=${SLL_HTTP_ENABLED:-false}" - "plugins.security.disabled=true" + - "OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_PASSWORD}" volumes: - "opensearch-data1:/usr/share/opensearch/data" From 54e5c785e5d4de3704b7843c8731a382c7ab3abd Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 15:00:40 +0100 Subject: [PATCH 26/37] test new pass --- .env.example | 2 +- .github/workflows/ci_assembly.yml | 6 +++--- .github/workflows/ci_module.yml | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 6bb5e2c..46dda2e 100644 --- a/.env.example +++ b/.env.example @@ -64,4 +64,4 @@ RATELIMIT_SKIP_TIMEOUT=False # Whether to skip rate limiting during c OPENSEARCH_ADMIN=admin -OPENSEARCH_PASSWORD=ThisIs4ü \ No newline at end of file +OPENSEARCH_PASSWORD=B9wc9VrqX7pY \ No newline at end of file diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index f2ef673..2d013cb 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -53,7 +53,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü + OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY options: >- --health-cmd "curl -f http://localhost:9200/_cluster/health || exit 1" --health-interval 10s @@ -172,7 +172,7 @@ jobs: SITE_ROOT: api CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: ThisIs4ü + OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" @@ -204,7 +204,7 @@ jobs: #REMOTE_USER_AUTHENTICATION: False CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: ThisIs4ü + OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index bc73bd0..df47421 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -133,7 +133,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü + OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY mssql: image: mcr.microsoft.com/mssql/server:2017-latest @@ -240,7 +240,7 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: ThisIs4ü + OPENSEARCH_PASSWORD: B9wc9VrqX7pY ci_module_psql_test_module_only: name: Run Module Tests (PSQL) runs-on: ubuntu-20.04 @@ -255,7 +255,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü + OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY pgsql: @@ -358,7 +358,7 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: ThisIs4ü + OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" @@ -376,7 +376,7 @@ jobs: cluster.name: my_opensearch_local http.port: 9200 plugins.security.ssl.http.enabled: false - OPENSEARCH_INITIAL_ADMIN_PASSWORD: ThisIs4ü + OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY pgsql: @@ -478,7 +478,7 @@ jobs: CI_EXCLUDED_MODULE: ${{ vars.CI_EXCLUDED_MODULE }} MODE: DEV OPENSEARCH_ADMIN: admin - OPENSEARCH_PASSWORD: ThisIs4ü + OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 OPENSEARCH_HOST: opensearch OPENSEARCH_HOSTS: "http://opensearch:9200" From bd2573054e20bcf5ed11a582462eba2f7a91c737 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 15:05:30 +0100 Subject: [PATCH 27/37] wait longer --- .github/workflows/ci_assembly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 2d013cb..b560e96 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -58,7 +58,7 @@ jobs: --health-cmd "curl -f http://localhost:9200/_cluster/health || exit 1" --health-interval 10s --health-timeout 5s - --health-retries 5 + --health-retries 10 steps: - uses: actions/checkout@v2 From 0f62075b2dd16be5589344161087fe80ecbb0c0a Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 15:10:09 +0100 Subject: [PATCH 28/37] fixing health check --- .github/workflows/ci_assembly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index b560e96..7277251 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -55,7 +55,7 @@ jobs: plugins.security.ssl.http.enabled: false OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY options: >- - --health-cmd "curl -f http://localhost:9200/_cluster/health || exit 1" + --health-cmd "curl -f -u admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} http://localhost:9200/_cluster/health || exit 1" --health-interval 10s --health-timeout 5s --health-retries 10 From 15a3dc4b11559317e34895f51d936d706af9caaa Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Mon, 28 Oct 2024 15:19:42 +0100 Subject: [PATCH 29/37] change os host --- .github/workflows/ci_assembly.yml | 8 ++++---- .github/workflows/ci_module.yml | 23 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci_assembly.yml b/.github/workflows/ci_assembly.yml index 7277251..a634581 100755 --- a/.github/workflows/ci_assembly.yml +++ b/.github/workflows/ci_assembly.yml @@ -174,8 +174,8 @@ jobs: OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 - OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: "http://opensearch:9200" + OPENSEARCH_HOST: localhost + OPENSEARCH_HOSTS: "http://localhost:9200" - name: Django tests MSSQL working-directory: ./openIMIS @@ -206,5 +206,5 @@ jobs: OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 - OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: "http://opensearch:9200" + OPENSEARCH_HOST: localhost + OPENSEARCH_HOSTS: "http://localhost:9200" diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index df47421..ce48bfc 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -134,6 +134,11 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY + options: >- + --health-cmd "curl -f -u admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} http://localhost:9200/_cluster/health || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 10 mssql: image: mcr.microsoft.com/mssql/server:2017-latest @@ -256,6 +261,11 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY + options: >- + --health-cmd "curl -f -u admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} http://localhost:9200/_cluster/health || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 10 pgsql: @@ -360,8 +370,8 @@ jobs: OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 - OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: "http://opensearch:9200" + OPENSEARCH_HOST: localhost + OPENSEARCH_HOSTS: "http://localhost:9200" ci_module_psql_test: name: Run All Tests (PSQL) runs-on: ubuntu-20.04 @@ -377,6 +387,11 @@ jobs: http.port: 9200 plugins.security.ssl.http.enabled: false OPENSEARCH_INITIAL_ADMIN_PASSWORD: B9wc9VrqX7pY + options: >- + --health-cmd "curl -f -u admin:${OPENSEARCH_INITIAL_ADMIN_PASSWORD} http://localhost:9200/_cluster/health || exit 1" + --health-interval 10s + --health-timeout 5s + --health-retries 10 pgsql: @@ -480,8 +495,8 @@ jobs: OPENSEARCH_ADMIN: admin OPENSEARCH_PASSWORD: B9wc9VrqX7pY OPEN_SEARCH_HTTP_PORT: 9200 - OPENSEARCH_HOST: opensearch - OPENSEARCH_HOSTS: "http://opensearch:9200" + OPENSEARCH_HOST: localhost + OPENSEARCH_HOSTS: "http://localhost:9200" - name: Generate Coverage Report if: always() working-directory: ./openimis/openIMIS From ce41b9edfc3568a229833a53c58e5eb48fb836cd Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Wed, 30 Oct 2024 15:05:23 +0100 Subject: [PATCH 30/37] test CI on release branch --- .github/workflows/ci_module.yml | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_module.yml b/.github/workflows/ci_module.yml index ce48bfc..947f55b 100755 --- a/.github/workflows/ci_module.yml +++ b/.github/workflows/ci_module.yml @@ -50,8 +50,32 @@ jobs: - name: Pull openIMIS Backend run: | - rm ./openimis -rf - git clone --depth=1 --branch=${{ inputs.branchName }} https://github.com/openimis/openimis-be_py.git ./openimis + # Determine the target branch + if [ "${{ github.event_name }}" == "pull_request" ]; then + TARGET_BRANCH="${{ github.event.pull_request.base.ref }}" + else + TARGET_BRANCH="${{ github.event.ref }}" + TARGET_BRANCH=${TARGET_BRANCH#refs/heads/} + fi + + # Use 'develop' as fallback if TARGET_BRANCH is empty or not a release branch + if [[ -z "$TARGET_BRANCH" ]]; then + TARGET_BRANCH="develop" + fi + + echo "Target branch: $TARGET_BRANCH" + + # Clone the repository + rm -rf ./openimis + git clone --depth=1 --branch=$TARGET_BRANCH https://github.com/openimis/openimis-be_py.git ./openimis || { + echo "Failed to clone $TARGET_BRANCH, falling back to develop" + git clone --depth=1 --branch=develop https://github.com/openimis/openimis-be_py.git ./openimis + } + + # Verify the cloned branch + cd ./openimis + CLONED_BRANCH=$(git rev-parse --abbrev-ref HEAD) + echo "Cloned branch: $CLONED_BRANCH" - name: Copy Current branch uses: actions/checkout@v2 From 5875193aced9c5ff8148ac5cda156dc0015c63e3 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Thu, 31 Oct 2024 17:10:37 +0100 Subject: [PATCH 31/37] Update openimis.json --- openimis.json | 172 +++++++++++++++++++++++--------------------------- 1 file changed, 80 insertions(+), 92 deletions(-) diff --git a/openimis.json b/openimis.json index 9d9f49c..7458e4c 100644 --- a/openimis.json +++ b/openimis.json @@ -1,176 +1,164 @@ { "modules": [ - { + { "name": "core", - "pip": "git+https://github.com/openimis/openimis-be-core_py.git@release/24.10#egg=openimis-be-core" + "pip": "openimis-be-core==v1.8.0" }, - { + { "name": "individual", - "pip": "git+https://github.com/openimis/openimis-be-individual_py.git@release/24.10#egg=openimis-be-individual" + "pip": "openimis-be-individual==v1.2.0" }, - { + { "name": "workflow", - "pip": "git+https://github.com/openimis/openimis-be-workflow_py.git@release/24.10#egg=openimis-be-workflow" + "pip": "openimis-be-workflow==v1.0.1" }, - { + { "name": "tasks_management", - "pip": "git+https://github.com/openimis/openimis-be-tasks_management_py.git@release/24.10#egg=openimis-be-tasks_management" + "pip": "openimis-be-tasks_management==v1.2.0" }, - { + { "name": "report", - "pip": "git+https://github.com/openimis/openimis-be-report_py.git@release/24.10#egg=openimis-be-report" + "pip": "openimis-be-report==v1.6.2" }, - { + { "name": "location", - "pip": "git+https://github.com/openimis/openimis-be-location_py.git@release/24.10#egg=openimis-be-location" + "pip": "openimis-be-location==v1.8.0" }, - { + { "name": "medical", - "pip": "git+https://github.com/openimis/openimis-be-medical_py.git@release/24.10#egg=openimis-be-medical" + "pip": "openimis-be-medical==v1.8.0" }, - { + { "name": "medical_pricelist", - "pip": "git+https://github.com/openimis/openimis-be-medical_pricelist_py.git@release/24.10#egg=openimis-be-medical_pricelist" + "pip": "openimis-be-medical_pricelist==v1.7.0" }, - { + { "name": "product", - "pip": "git+https://github.com/openimis/openimis-be-product_py.git@release/24.10#egg=openimis-be-product" + "pip": "openimis-be-product==v1.7.0" }, - { + { "name": "insuree", - "pip": "git+https://github.com/openimis/openimis-be-insuree_py.git@release/24.10#egg=openimis-be-insuree" + "pip": "openimis-be-insuree==v1.8.0" }, - { + { "name": "policy", - "pip": "git+https://github.com/openimis/openimis-be-policy_py.git@release/24.10#egg=openimis-be-policy" + "pip": "openimis-be-policy==v1.8.0" }, - { + { "name": "contribution", - "pip": "git+https://github.com/openimis/openimis-be-contribution_py.git@release/24.10#egg=openimis-be-contribution" + "pip": "openimis-be-contribution==v1.8.0" }, - { + { "name": "payer", - "pip": "git+https://github.com/openimis/openimis-be-payer_py.git@release/24.10#egg=openimis-be-payer" + "pip": "openimis-be-payer==v1.6.1" }, - { + { "name": "payment", - "pip": "git+https://github.com/openimis/openimis-be-payment_py.git@release/24.10#egg=openimis-be-payment" + "pip": "openimis-be-payment==v1.8.0" }, - { + { "name": "claim", - "pip": "git+https://github.com/openimis/openimis-be-claim_py.git@release/24.10#egg=openimis-be-claim" + "pip": "openimis-be-claim==v1.8.0" }, - { + { "name": "claim_batch", - "pip": "git+https://github.com/openimis/openimis-be-claim_batch_py.git@release/24.10#egg=openimis-be-claim_batch" + "pip": "openimis-be-claim_batch==v1.8.0" }, - { + { "name": "tools", - "pip": "git+https://github.com/openimis/openimis-be-tools_py.git@release/24.10#egg=openimis-be-tools" + "pip": "openimis-be-tools==v1.8.0" }, - { + { "name": "api_fhir_r4", - "pip": "git+https://github.com/openimis/openimis-be-api_fhir_r4_py.git@release/24.10#egg=openimis-be-api_fhir_r4" + "pip": "openimis-be-api_fhir_r4==v1.8.0" }, - { + { "name": "calculation", - "pip": "git+https://github.com/openimis/openimis-be-calculation_py.git@release/24.10#egg=openimis-be-calculation" + "pip": "openimis-be-calculation==v1.8.0" }, - { + { "name": "contribution_plan", - "pip": "git+https://github.com/openimis/openimis-be-contribution_plan_py.git@release/24.10#egg=openimis-be-contribution_plan" + "pip": "openimis-be-contribution-plan==v1.8.0" }, - { + { "name": "policyholder", - "pip": "git+https://github.com/openimis/openimis-be-policyholder_py.git@release/24.10#egg=openimis-be-policyholder" + "pip": "openimis-be-policyholder==v1.8.0" }, - { + { "name": "contract", - "pip": "git+https://github.com/openimis/openimis-be-contract_py.git@release/24.10#egg=openimis-be-contract" + "pip": "openimis-be-contract==v1.8.0" }, - { + { "name": "invoice", - "pip": "git+https://github.com/openimis/openimis-be-invoice_py.git@release/24.10#egg=openimis-be-invoice" + "pip": "openimis-be-invoice==v1.8.0" }, - { + { "name": "calcrule_contribution_legacy", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_contribution_legacy_py.git@release/24.10#egg=openimis-be-calcrule_contribution_legacy" + "pip": "openimis-be-calcrule-contribution-legacy==v1.7.0" }, - { + { "name": "calcrule_third_party_payment", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_third_party_payment_py.git@release/24.10#egg=openimis-be-calcrule_third_party_payment" + "pip": "openimis-be-calcrule-third_party_payment==v1.8.0" }, - { + { "name": "calcrule_capitation_payment", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_capitation_payment_py.git@release/24.10#egg=openimis-be-calcrule_capitation_payment" + "pip": "openimis-be-calcrule-capitation_payment==v1.8.0" }, - { + { "name": "calcrule_commission", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_commission_py.git@release/24.10#egg=openimis-be-calcrule_commission" + "pip": "openimis-be-calcrule_commission==v1.6.1" }, - { - "name": "calcrule_validations", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_validations_py.git@release/24.10#egg=openimis-be-calcrule_validations" - }, - { + { "name": "calcrule_contribution_income_percentage", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_contribution_income_percentage_py.git@release/24.10#egg=openimis-be-calcrule_contribution_income_percentage" + "pip": "openimis-be-calcrule_contribution_income_percentage==v1.7.0" }, - { + { "name": "calcrule_fees", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_fees_py.git@release/24.10#egg=openimis-be-calcrule_fees" + "pip": "openimis-be-calcrule_fees==v1.6.1" }, - { + { "name": "calcrule_unconditional_cash_payment", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_unconditional_cash_payment_py.git@release/24.10#egg=openimis-be-calcrule_unconditional_cash_payment" + "pip": "openimis-be-calcrule_unconditional_cash_payment==v1.6.1" }, - { + { "name": "im_export", - "pip": "git+https://github.com/openimis/openimis-be-im_export_py.git@release/24.10#egg=openimis-be-im_export" + "pip": "openimis-be-im_export==v1.3.0" }, - { + { "name": "dhis2_etl", - "pip": "git+https://github.com/openimis/openimis-be-dhis2_etl_py.git@release/24.10#egg=openimis-be-dhis2_etl" + "pip": "openimis-be-dhis2_etl==v1.3.1" }, - { + { "name": "social_protection", - "pip": "git+https://github.com/openimis/openimis-be-social_protection_py.git@release/24.10#egg=openimis-be-social_protection" + "pip": "openimis-be-social_protection==v1.2.0" }, - { + { "name": "opensearch_reports", - "pip": "git+https://github.com/openimis/openimis-be-opensearch_reports_py.git@release/24.10#egg=openimis-be-opensearch_reports" + "pip": "openimis-be-opensearch_reports==v1.2.0" }, - { + { "name": "payment_cycle", - "pip": "git+https://github.com/openimis/openimis-be-payment_cycle_py.git@release/24.10#egg=openimis-be-payment_cycle" + "pip": "openimis-be-payment_cycle==v1.2.0" }, - { + { "name": "calcrule_social_protection", - "pip": "git+https://github.com/openimis/openimis-be-calcrule_social_protection_py.git@release/24.10#egg=openimis-be-calcrule_social_protection" + "pip": "openimis-be-calcrule_social_protection==v1.2.0" }, - { + { "name": "payroll", - "pip": "git+https://github.com/openimis/openimis-be-payroll_py.git@release/24.10#egg=openimis-be-payroll" + "pip": "openimis-be-payroll==v1.2.0" }, - { + { "name": "controls", - "pip": "git+https://github.com/openimis/openimis-be-controls_py.git@release/24.10#egg=openimis-be-controls" + "pip": "openimis-be-controls==v1.2.0" }, - { + { "name": "grievance_social_protection", - "pip": "git+https://github.com/openimis/openimis-be-grievance_social_protection_py.git@release/24.10#egg=openimis-be-grievance_social_protection" + "pip": "openimis-be-grievance_social_protection==1.0.0" }, - { + { "name": "claim_sampling", - "pip": "git+https://github.com/openimis/openimis-be-claim_sampling_py.git@release/24.10#egg=openimis-be-claim_sampling" - }, - { - "name": "deduplication", - "pip": "git+https://github.com/openimis/openimis-be-deduplication_py.git@release/24.10#egg=openimis-be-deduplication" - }, - { - "name": "api_etl", - "pip": "git+https://github.com/openimis/openimis-be-api_etl_py.git@release/24.10#egg=openimis-be-api_etl" + "pip": "openimis-be-claim_sampling==1.0.0" } ] } From 6b5ccd354b19f0b48700191fe91dc4e7434d148f Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Thu, 31 Oct 2024 17:22:59 +0100 Subject: [PATCH 32/37] Update openimis.json --- openimis.json | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/openimis.json b/openimis.json index 7458e4c..ee5d33e 100644 --- a/openimis.json +++ b/openimis.json @@ -1,6 +1,6 @@ { "modules": [ - { + { "name": "core", "pip": "openimis-be-core==v1.8.0" }, @@ -39,7 +39,90 @@ { "name": "insuree", "pip": "openimis-be-insuree==v1.8.0" + },{ + "name": "contribution_plan", + "pip": "openimis-be-contribution-plan==v1.8.0" + }, + { + "name": "policyholder", + "pip": "openimis-be-policyholder==v1.8.0" + }, + { + "name": "contract", + "pip": "openimis-be-contract==v1.8.0" + }, + { + "name": "invoice", + "pip": "openimis-be-invoice==v1.8.0" + }, + { + "name": "calcrule_contribution_legacy", + "pip": "openimis-be-calcrule-contribution-legacy==v1.7.0" + }, + { + "name": "calcrule_third_party_payment", + "pip": "openimis-be-calcrule-third_party_payment==v1.8.0" + }, + { + "name": "calcrule_capitation_payment", + "pip": "openimis-be-calcrule-capitation_payment==v1.8.0" + }, + { + "name": "calcrule_commission", + "pip": "openimis-be-calcrule_commission==v1.6.1" + }, + { + "name": "calcrule_contribution_income_percentage", + "pip": "openimis-be-calcrule_contribution_income_percentage==v1.7.0" + }, + { + "name": "calcrule_fees", + "pip": "openimis-be-calcrule_fees==v1.6.1" + }, + { + "name": "calcrule_unconditional_cash_payment", + "pip": "openimis-be-calcrule_unconditional_cash_payment==v1.6.1" + }, + { + "name": "im_export", + "pip": "openimis-be-im_export==v1.3.0" + }, + { + "name": "dhis2_etl", + "pip": "openimis-be-dhis2_etl==v1.3.1" + }, + { + "name": "social_protection", + "pip": "openimis-be-social_protection==v1.2.0" + }, + { + "name": "opensearch_reports", + "pip": "openimis-be-opensearch_reports==v1.2.0" + }, + { + "name": "payment_cycle", + "pip": "openimis-be-payment_cycle==v1.2.0" + }, + { + "name": "calcrule_social_protection", + "pip": "openimis-be-calcrule_social_protection==v1.2.0" }, + { + "name": "payroll", + "pip": "openimis-be-payroll==v1.2.0" + }, + { + "name": "controls", + "pip": "openimis-be-controls==v1.2.0" + }, + { + "name": "grievance_social_protection", + "pip": "openimis-be-grievance_social_protection==1.0.0" + }, + { + "name": "claim_sampling", + "pip": "openimis-be-claim_sampling==1.0.0" + } { "name": "policy", "pip": "openimis-be-policy==v1.8.0" @@ -107,6 +190,10 @@ { "name": "calcrule_commission", "pip": "openimis-be-calcrule_commission==v1.6.1" + }, + { + "name": "calcrule_validations", + "pip": "openimis-be-calcrule_validations==v1.1.0" }, { "name": "calcrule_contribution_income_percentage", @@ -159,6 +246,14 @@ { "name": "claim_sampling", "pip": "openimis-be-claim_sampling==1.0.0" + }, + { + "name": "deduplication", + "pip": "openimis-be-deduplication==v1.1.0" + }, + { + "name": "api_etl", + "pip": "openimis-be-api_etl==1.0.0" } ] } From b57581a630ce738b705765718191d2875eb35866 Mon Sep 17 00:00:00 2001 From: Patrick Delcroix Date: Thu, 31 Oct 2024 17:24:47 +0100 Subject: [PATCH 33/37] Update openimis.json --- openimis.json | 167 +++++++++++++------------------------------------- 1 file changed, 42 insertions(+), 125 deletions(-) diff --git a/openimis.json b/openimis.json index ee5d33e..6c81953 100644 --- a/openimis.json +++ b/openimis.json @@ -4,254 +4,171 @@ "name": "core", "pip": "openimis-be-core==v1.8.0" }, - { + { "name": "individual", "pip": "openimis-be-individual==v1.2.0" }, - { + { "name": "workflow", "pip": "openimis-be-workflow==v1.0.1" }, - { + { "name": "tasks_management", "pip": "openimis-be-tasks_management==v1.2.0" }, - { + { "name": "report", "pip": "openimis-be-report==v1.6.2" }, - { + { "name": "location", "pip": "openimis-be-location==v1.8.0" }, - { + { "name": "medical", "pip": "openimis-be-medical==v1.8.0" }, - { + { "name": "medical_pricelist", "pip": "openimis-be-medical_pricelist==v1.7.0" }, - { + { "name": "product", "pip": "openimis-be-product==v1.7.0" }, - { + { "name": "insuree", "pip": "openimis-be-insuree==v1.8.0" - },{ - "name": "contribution_plan", - "pip": "openimis-be-contribution-plan==v1.8.0" - }, - { - "name": "policyholder", - "pip": "openimis-be-policyholder==v1.8.0" - }, - { - "name": "contract", - "pip": "openimis-be-contract==v1.8.0" - }, - { - "name": "invoice", - "pip": "openimis-be-invoice==v1.8.0" - }, - { - "name": "calcrule_contribution_legacy", - "pip": "openimis-be-calcrule-contribution-legacy==v1.7.0" - }, - { - "name": "calcrule_third_party_payment", - "pip": "openimis-be-calcrule-third_party_payment==v1.8.0" - }, - { - "name": "calcrule_capitation_payment", - "pip": "openimis-be-calcrule-capitation_payment==v1.8.0" - }, - { - "name": "calcrule_commission", - "pip": "openimis-be-calcrule_commission==v1.6.1" - }, - { - "name": "calcrule_contribution_income_percentage", - "pip": "openimis-be-calcrule_contribution_income_percentage==v1.7.0" - }, - { - "name": "calcrule_fees", - "pip": "openimis-be-calcrule_fees==v1.6.1" - }, - { - "name": "calcrule_unconditional_cash_payment", - "pip": "openimis-be-calcrule_unconditional_cash_payment==v1.6.1" - }, - { - "name": "im_export", - "pip": "openimis-be-im_export==v1.3.0" - }, - { - "name": "dhis2_etl", - "pip": "openimis-be-dhis2_etl==v1.3.1" - }, - { - "name": "social_protection", - "pip": "openimis-be-social_protection==v1.2.0" - }, - { - "name": "opensearch_reports", - "pip": "openimis-be-opensearch_reports==v1.2.0" - }, - { - "name": "payment_cycle", - "pip": "openimis-be-payment_cycle==v1.2.0" - }, - { - "name": "calcrule_social_protection", - "pip": "openimis-be-calcrule_social_protection==v1.2.0" - }, - { - "name": "payroll", - "pip": "openimis-be-payroll==v1.2.0" - }, - { - "name": "controls", - "pip": "openimis-be-controls==v1.2.0" }, - { - "name": "grievance_social_protection", - "pip": "openimis-be-grievance_social_protection==1.0.0" - }, - { - "name": "claim_sampling", - "pip": "openimis-be-claim_sampling==1.0.0" - } - { + { "name": "policy", "pip": "openimis-be-policy==v1.8.0" }, - { + { "name": "contribution", "pip": "openimis-be-contribution==v1.8.0" }, - { + { "name": "payer", "pip": "openimis-be-payer==v1.6.1" }, - { + { "name": "payment", "pip": "openimis-be-payment==v1.8.0" }, - { + { "name": "claim", "pip": "openimis-be-claim==v1.8.0" }, - { + { "name": "claim_batch", "pip": "openimis-be-claim_batch==v1.8.0" }, - { + { "name": "tools", "pip": "openimis-be-tools==v1.8.0" }, - { + { "name": "api_fhir_r4", "pip": "openimis-be-api_fhir_r4==v1.8.0" }, - { + { "name": "calculation", "pip": "openimis-be-calculation==v1.8.0" }, - { + { "name": "contribution_plan", "pip": "openimis-be-contribution-plan==v1.8.0" }, - { + { "name": "policyholder", "pip": "openimis-be-policyholder==v1.8.0" }, - { + { "name": "contract", "pip": "openimis-be-contract==v1.8.0" }, - { + { "name": "invoice", "pip": "openimis-be-invoice==v1.8.0" }, - { + { "name": "calcrule_contribution_legacy", "pip": "openimis-be-calcrule-contribution-legacy==v1.7.0" }, - { + { "name": "calcrule_third_party_payment", "pip": "openimis-be-calcrule-third_party_payment==v1.8.0" }, - { + { "name": "calcrule_capitation_payment", "pip": "openimis-be-calcrule-capitation_payment==v1.8.0" }, - { + { "name": "calcrule_commission", "pip": "openimis-be-calcrule_commission==v1.6.1" }, - { + { "name": "calcrule_validations", "pip": "openimis-be-calcrule_validations==v1.1.0" }, - { + { "name": "calcrule_contribution_income_percentage", "pip": "openimis-be-calcrule_contribution_income_percentage==v1.7.0" }, - { + { "name": "calcrule_fees", "pip": "openimis-be-calcrule_fees==v1.6.1" }, - { + { "name": "calcrule_unconditional_cash_payment", "pip": "openimis-be-calcrule_unconditional_cash_payment==v1.6.1" }, - { + { "name": "im_export", "pip": "openimis-be-im_export==v1.3.0" }, - { + { "name": "dhis2_etl", "pip": "openimis-be-dhis2_etl==v1.3.1" }, - { + { "name": "social_protection", "pip": "openimis-be-social_protection==v1.2.0" }, - { + { "name": "opensearch_reports", "pip": "openimis-be-opensearch_reports==v1.2.0" }, - { + { "name": "payment_cycle", "pip": "openimis-be-payment_cycle==v1.2.0" }, - { + { "name": "calcrule_social_protection", "pip": "openimis-be-calcrule_social_protection==v1.2.0" }, - { + { "name": "payroll", "pip": "openimis-be-payroll==v1.2.0" }, - { + { "name": "controls", "pip": "openimis-be-controls==v1.2.0" }, - { + { "name": "grievance_social_protection", "pip": "openimis-be-grievance_social_protection==1.0.0" }, - { + { "name": "claim_sampling", "pip": "openimis-be-claim_sampling==1.0.0" }, - { + { "name": "deduplication", "pip": "openimis-be-deduplication==v1.1.0" }, - { + { "name": "api_etl", "pip": "openimis-be-api_etl==1.0.0" } From 73b992d53c780eaeb5b039b58812cb0666250da1 Mon Sep 17 00:00:00 2001 From: delcroip Date: Fri, 1 Nov 2024 11:20:55 +0100 Subject: [PATCH 34/37] split setting and update prod --- openIMIS/openIMIS/settings.py | 653 ---------------------- openIMIS/openIMIS/settings/__init__.py | 38 ++ openIMIS/openIMIS/settings/base.py | 195 +++++++ openIMIS/openIMIS/settings/common.py | 10 + openIMIS/openIMIS/settings/database.py | 95 ++++ openIMIS/openIMIS/settings/dev.py | 13 + openIMIS/openIMIS/settings/logging.py | 52 ++ openIMIS/openIMIS/settings/opensearch.py | 17 + openIMIS/openIMIS/settings/prod.py | 56 ++ openIMIS/openIMIS/settings/queue_cache.py | 55 ++ openIMIS/openIMIS/settings/scheduler.py | 46 ++ openIMIS/openIMIS/settings/security.py | 108 ++++ openIMIS/openIMIS/settings/sentry.py | 32 ++ openIMIS/openIMIS/settings/trad.py | 18 + requirements.txt | 3 +- 15 files changed, 737 insertions(+), 654 deletions(-) delete mode 100644 openIMIS/openIMIS/settings.py create mode 100644 openIMIS/openIMIS/settings/__init__.py create mode 100644 openIMIS/openIMIS/settings/base.py create mode 100644 openIMIS/openIMIS/settings/common.py create mode 100644 openIMIS/openIMIS/settings/database.py create mode 100644 openIMIS/openIMIS/settings/dev.py create mode 100644 openIMIS/openIMIS/settings/logging.py create mode 100644 openIMIS/openIMIS/settings/opensearch.py create mode 100644 openIMIS/openIMIS/settings/prod.py create mode 100644 openIMIS/openIMIS/settings/queue_cache.py create mode 100644 openIMIS/openIMIS/settings/scheduler.py create mode 100644 openIMIS/openIMIS/settings/security.py create mode 100644 openIMIS/openIMIS/settings/sentry.py create mode 100644 openIMIS/openIMIS/settings/trad.py diff --git a/openIMIS/openIMIS/settings.py b/openIMIS/openIMIS/settings.py deleted file mode 100644 index 9cce155..0000000 --- a/openIMIS/openIMIS/settings.py +++ /dev/null @@ -1,653 +0,0 @@ -""" -Django settings for openIMIS project. -""" -import json -import logging -import os - -from dotenv import load_dotenv -from .openimisapps import openimis_apps, get_locale_folders -from datetime import timedelta -from cryptography.hazmat.primitives import serialization - - -load_dotenv() - -# Makes openimis_apps available to other modules -OPENIMIS_APPS = openimis_apps() - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - - - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = os.environ.get("MODE", "PROD") == "DEV" -DEFAULT_LOGGING_HANDLER = os.getenv("DJANGO_LOG_HANDLER", "console") -DEFAULT_DB_LOGGING_HANDLER = os.getenv("DJANGO_DB_LOG_HANDLER", "db-queries") -LOGGING_LEVEL = os.getenv("DJANGO_LOG_LEVEL", "DEBUG" if DEBUG else "WARNING") -if DEBUG: - EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - - - - - -LOGGING = { - "version": 1, - "disable_existing_loggers": False, - "formatters": { - "standard": {"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"}, - "short": {"format": "%(name)s: %(message)s"}, - }, - "handlers": { - "db-queries": { - "level": LOGGING_LEVEL, - "class": "logging.handlers.RotatingFileHandler", - "filename": os.environ.get("DB_QUERIES_LOG_FILE", "db-queries.log"), - "maxBytes": 1024 * 1024 * 5, # 5 MB - "backupCount": 10, - "formatter": "standard", - }, - "debug-log": { - "level": LOGGING_LEVEL, - "class": "logging.handlers.RotatingFileHandler", - "filename": os.environ.get("DEBUG_LOG_FILE", "debug.log"), - "maxBytes": 1024 * 1024 * 5, # 5 MB - "backupCount": 3, - "formatter": "standard", - }, - "console": {"class": "logging.StreamHandler", "formatter": "short"}, - }, - "loggers": { - "": { - "level": LOGGING_LEVEL, - "handlers": [DEFAULT_LOGGING_HANDLER], - }, - "django.db.backends": { - "level": LOGGING_LEVEL, - "propagate": False, - "handlers": [DEFAULT_DB_LOGGING_HANDLER], - }, - "openIMIS": { - "level": LOGGING_LEVEL, - "handlers": [DEFAULT_LOGGING_HANDLER], - }, - }, -} - -SENTRY_DSN = os.environ.get("SENTRY_DSN", None) -SENTRY_SAMPLE_RATE = os.environ.get("SENTRY_SAMPLE_RATE", "0.2") -IS_SENTRY_ENABLED = False - -if SENTRY_DSN is not None: - try: - import sentry_sdk - from sentry_sdk.integrations.django import DjangoIntegration - - sentry_sdk.init( - dsn=SENTRY_DSN, - integrations=[DjangoIntegration()], - # Set traces_sample_rate to 1.0 to capture 100% - # of transactions for performance monitoring. - # We recommend adjusting this value in production, - traces_sample_rate=float(SENTRY_SAMPLE_RATE), - # If you wish to associate users to errors (assuming you are using - # django.contrib.auth) you may enable sending PII data. - send_default_pii=True, - # By default the SDK will try to use the SENTRY_RELEASE - # environment variable, or infer a git commit - # SHA as release, however you may want to set - # something more human-readable. - # release="myapp@1.0.0", - ) - IS_SENTRY_ENABLED = True - except ModuleNotFoundError: - logging.error( - "sentry_sdk has to be installed to use Sentry. Run `pip install --upgrade sentry_sdk` to install it." - ) - - -def SITE_ROOT(): - root = os.environ.get("SITE_ROOT", "") - if root == "": - return root - elif root.endswith("/"): - return root - else: - return "%s/" % root - - -def SITE_URL(): - url = os.environ.get("SITE_URL", "") - if url == "": - return url - elif url.endswith("/"): - return url[:-1] - else: - return url - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = os.environ.get( - "SECRET_KEY", "chv^^7i_v3-04!rzu&qe#+h*a=%h(ib#5w9n$!f2q7%2$qp=zz" -) - - -# SECURITY WARNING: don't run without row security in production! -# Row security is dedicated to filter the data result sets according to users' right -# Example: user registered at a Health Facility should only see claims recorded for that Health Facility -ROW_SECURITY = os.environ.get("ROW_SECURITY", "True").lower() == "true" - -if "ALLOWED_HOSTS" in os.environ: - ALLOWED_HOSTS = json.loads(os.environ["ALLOWED_HOSTS"]) -else: - ALLOWED_HOSTS = ["*"] - -# TEST_WITHOUT_MIGRATIONS_COMMAND = 'django_nose.management.commands.test.Command' -# TEST_RUNNER = 'core.test_utils.UnManagedModelTestRunner' - -# Application definition - -INSTALLED_APPS = [ - "django.contrib.admin", - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.messages", - "django.contrib.staticfiles", - "graphene_django", - "graphql_jwt.refresh_token.apps.RefreshTokenConfig", - "test_without_migrations", - "rest_framework", - "rules", - "health_check", # required - "health_check.db", # stock Django health checkers - "health_check.cache", - "health_check.storage", - "django_apscheduler", - "channels", # Websocket support - "developer_tools", - "drf_spectacular", # Swagger UI for FHIR API - "axes", - "django_opensearch_dsl", -] -INSTALLED_APPS += OPENIMIS_APPS -INSTALLED_APPS += ["apscheduler_runner", "signal_binding"] # Signal binding should be last installed module - -AUTHENTICATION_BACKENDS = [] - -if os.environ.get("REMOTE_USER_AUTHENTICATION", "false").lower() == "true": - AUTHENTICATION_BACKENDS += ["django.contrib.auth.backends.RemoteUserBackend"] - -AUTHENTICATION_BACKENDS += [ - "axes.backends.AxesStandaloneBackend", - "rules.permissions.ObjectPermissionBackend", - "graphql_jwt.backends.JSONWebTokenBackend", - "django.contrib.auth.backends.ModelBackend", -] - -ANONYMOUS_USER_NAME = None - -REST_FRAMEWORK = { - "DEFAULT_AUTHENTICATION_CLASSES": [ - "core.jwt_authentication.JWTAuthentication", - "rest_framework.authentication.BasicAuthentication", - "rest_framework.authentication.SessionAuthentication", - ], - "EXCEPTION_HANDLER": "openIMIS.ExceptionHandlerDispatcher.dispatcher", - 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', -} - -SPECTACULAR_SETTINGS = { - 'TITLE': 'FHIR R4', - 'DESCRIPTION': 'openIMIS FHIR R4 API', - 'VERSION': '1.0.0', - 'AUTHENTICATION_WHITELIST': [ - 'core.jwt_authentication.JWTAuthentication', - 'api_fhir_r4.views.CsrfExemptSessionAuthentication' - ], -} - -if os.environ.get("REMOTE_USER_AUTHENTICATION", "false").lower() == "true": - REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"].insert( - 0, - "rest_framework.authentication.RemoteUserAuthentication", - ) - -MIDDLEWARE = [ - "django.middleware.security.SecurityMiddleware", - "whitenoise.middleware.WhiteNoiseMiddleware", - 'core.middleware.GraphQLRateLimitMiddleware', - "axes.middleware.AxesMiddleware", - "core.middleware.DefaultAxesAttributesMiddleware", - "django.contrib.sessions.middleware.SessionMiddleware", - "django.middleware.locale.LocaleMiddleware", - "django.middleware.common.CommonMiddleware", - "django.middleware.csrf.CsrfViewMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", - "core.middleware.SecurityHeadersMiddleware", -] - -MODE = os.environ.get("MODE") - -# Lockout mechanism configuration -AXES_ENABLED = True if os.environ.get("MODE", "DEV") == "PROD" else False -AXES_FAILURE_LIMIT = int(os.getenv("LOGIN_LOCKOUT_FAILURE_LIMIT", 5)) -AXES_COOLOFF_TIME = timedelta(minutes=int(os.getenv("LOGIN_LOCKOUT_COOLOFF_TIME", 5))) - -RATELIMIT_CACHE = os.getenv('RATELIMIT_CACHE', 'default') -RATELIMIT_KEY = os.getenv('RATELIMIT_KEY', 'ip') -RATELIMIT_RATE = os.getenv('RATELIMIT_RATE', '150/m') -RATELIMIT_METHOD = os.getenv('RATELIMIT_METHOD', 'ALL') -RATELIMIT_GROUP = os.getenv('RATELIMIT_GROUP', 'graphql') -RATELIMIT_SKIP_TIMEOUT = os.getenv('RATELIMIT_SKIP_TIMEOUT', 'False') - -if DEBUG: - # Attach profiler middleware - MIDDLEWARE.append( - "django_cprofile_middleware.middleware.ProfilerMiddleware" - ) - DJANGO_CPROFILE_MIDDLEWARE_REQUIRE_STAFF = False - -if os.environ.get("REMOTE_USER_AUTHENTICATION", "false").lower() == "true": - MIDDLEWARE += ["core.security.RemoteUserMiddleware"] -MIDDLEWARE += [ - "django.contrib.messages.middleware.MessageMiddleware", - "django.middleware.clickjacking.XFrameOptionsMiddleware", -] - -ROOT_URLCONF = "openIMIS.urls" - -TEMPLATES = [ - { - "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [], - "APP_DIRS": True, - "OPTIONS": { - "context_processors": [ - "django.template.context_processors.debug", - "django.template.context_processors.request", - "django.contrib.auth.context_processors.auth", - "django.contrib.messages.context_processors.messages", - ], - }, - }, -] - -WSGI_APPLICATION = "openIMIS.wsgi.application" - -GRAPHENE = { - "SCHEMA": "openIMIS.schema.schema", - "RELAY_CONNECTION_MAX_LIMIT": 100, - "GRAPHIQL_HEADER_EDITOR_ENABLED": True, - "MIDDLEWARE": [ - "openIMIS.tracer.TracerMiddleware", - "openIMIS.schema.GQLUserLanguageMiddleware", - "graphql_jwt.middleware.JSONWebTokenMiddleware", - "graphene_django.debug.DjangoDebugMiddleware", # adds a _debug query to graphQL with sql debug info - ], -} - -GRAPHQL_JWT = { - "JWT_VERIFY_EXPIRATION": True, - "JWT_EXPIRATION_DELTA": timedelta(days=1), - "JWT_REFRESH_EXPIRATION_DELTA": timedelta(days=30), - "JWT_AUTH_HEADER_PREFIX": "Bearer", - "JWT_ENCODE_HANDLER": "core.jwt.jwt_encode_user_key", - "JWT_DECODE_HANDLER": "core.jwt.jwt_decode_user_key", - # This can be used to expose some resources without authentication - "JWT_ALLOW_ANY_CLASSES": [ - "graphql_jwt.mutations.ObtainJSONWebToken", - "graphql_jwt.mutations.Verify", - "graphql_jwt.mutations.Refresh", - "graphql_jwt.mutations.Revoke", - "core.schema.ResetPasswordMutation", - "core.schema.SetPasswordMutation", - ], -} - -# Load RSA keys -private_key_path = os.path.join(BASE_DIR, 'keys', 'jwt_private_key.pem') -public_key_path = os.path.join(BASE_DIR, 'keys', 'jwt_public_key.pem') - -if os.path.exists(private_key_path) and os.path.exists(public_key_path): - with open(private_key_path, 'rb') as f: - private_key = serialization.load_pem_private_key( - f.read(), - password=None, - ) - - with open(public_key_path, 'rb') as f: - public_key = serialization.load_pem_public_key( - f.read(), - ) - - # If RSA keys exist, update the algorithm and add keys to GRAPHQL_JWT settings - GRAPHQL_JWT.update({ - "JWT_ALGORITHM": "RS256", - "JWT_PRIVATE_KEY": private_key, - "JWT_PUBLIC_KEY": public_key, - }) - -if MODE == "PROD": - # Enhance security in production - GRAPHQL_JWT.update({ - "JWT_COOKIE_SECURE": True, - "JWT_COOKIE_SAMESITE": "Lax", - }) - - CSRF_COOKIE_SECURE = True - CSRF_COOKIE_HTTPONLY = True - CSRF_COOKIE_SAMESITE = 'Lax' - - SECURE_BROWSER_XSS_FILTER = True - SECURE_CONTENT_TYPE_NOSNIFF = True - SECURE_HSTS_SECONDS = 63072000 - SECURE_HSTS_INCLUDE_SUBDOMAINS = True - SECURE_HSTS_PRELOAD = True - SECURE_SSL_REDIRECT = True - -csrf_trusted_origins = os.environ.get('CSRF_TRUSTED_ORIGINS', default='') -CSRF_TRUSTED_ORIGINS = csrf_trusted_origins.split(',') if csrf_trusted_origins else [] - -# no db -DATABASES = {} -DB_DEFAULT = os.environ.get("DB_DEFAULT", 'postgresql') - -if os.environ.get("NO_DATABASE", "False") == "True": - - DATABASES['default'] = { - # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ' ../script/sqlite.db', # Or path to database file if using sqlite3. - 'USER': '', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. - } -if "DB_OPTIONS" in os.environ: - DATABASE_OPTIONS = json.loads(os.environ["DB_OPTIONS"]) - MSSQL_DATABASE_OPTIONS = DATABASE_OPTIONS - PSQL_DATABASE_OPTIONS = DATABASE_OPTIONS -else: - if os.name == "nt": - MSSQL_DATABASE_OPTIONS = { - "driver": "ODBC Driver 17 for SQL Server", - "extra_params": "Persist Security Info=False;server=%s" - % os.environ.get("DB_HOST"), - "unicode_results": True, - } - else: - MSSQL_DATABASE_OPTIONS = { - "driver": "ODBC Driver 17 for SQL Server", - "unicode_results": True, - } - PSQL_DATABASE_OPTIONS = {'options': '-c search_path=django,public'} - -DEFAULT_ENGINE = os.environ.get("DB_ENGINE", "mssql" if DB_DEFAULT == 'mssql' else "django.db.backends.postgresql") -DEFAULT_NAME = os.environ.get("DB_NAME", "imis") -DEFAULT_USER = os.environ.get("DB_USER", "IMISuser") -DEFAULT_PASSWORD = os.environ.get("DB_PASSWORD") -DEFAULT_HOST = os.environ.get("DB_HOST", 'db') -DEFAULT_PORT = os.environ.get("DB_PORT", "1433" if DB_DEFAULT == 'mssql' else "5432") - - - -if DB_DEFAULT == 'mssql': - DATABASES["default"] = { - "ENGINE": os.environ.get("MSSQL_DB_ENGINE", DEFAULT_ENGINE), - "NAME": os.environ.get("MSSQL_DB_NAME", DEFAULT_NAME), - "USER": os.environ.get("MSSQL_DB_USER", DEFAULT_USER), - "PASSWORD": os.environ.get("MSSQL_DB_PASSWORD", DEFAULT_PASSWORD), - "HOST": os.environ.get("MSSQL_DB_HOST", DEFAULT_HOST), - "PORT": os.environ.get("MSSQL_DB_PORT", DEFAULT_PORT), - "OPTIONS": MSSQL_DATABASE_OPTIONS, - 'TEST': { - 'NAME': os.environ.get("DB_TEST_NAME", "test_" + os.environ.get("MSSQL_DB_NAME", "imis")), - } - } -else: - DATABASES["default"] = { - "ENGINE": os.environ.get("PSQL_DB_ENGINE", DEFAULT_ENGINE), - "NAME": os.environ.get("PSQL_DB_NAME", DEFAULT_NAME), - "USER": os.environ.get("PSQL_DB_USER", DEFAULT_USER), - "PASSWORD": os.environ.get("PSQL_DB_PASSWORD", DEFAULT_PASSWORD), - "HOST": os.environ.get("PSQL_DB_HOST", DEFAULT_HOST), - "PORT": os.environ.get("PSQL_DB_PORT", DEFAULT_PORT), - "OPTIONS": PSQL_DATABASE_OPTIONS, - 'TEST': { - 'NAME': os.environ.get("DB_TEST_NAME", "test_" + os.environ.get("MSSQL_DB_NAME", "imis")), - } - } - -#should not add that config unless used -if "DASHBOARD_DB_ENGINE" in os.environ: - DATABASES['dashboard_db'] = { - "ENGINE": os.environ.get("DASHBOARD_DB_ENGINE", DEFAULT_ENGINE), - "NAME": os.environ.get("DASHBOARD_DB_NAME"), - "USER": os.environ.get("DASHBOARD_DB_USER"), - "PASSWORD": os.environ.get("DASHBOARD_DB_PASSWORD"), - "HOST": os.environ.get("DASHBOARD_DB_HOST", DEFAULT_HOST), - "PORT": os.environ.get("DASHBOARD_DB_PORT", DEFAULT_PORT) - } - -if "sql_server.pyodbc" in DATABASES["default"]['ENGINE'] or "mssql" in DATABASES["default"]['ENGINE']: - MSSQL = True - -else: - MSSQL = False - - # Database - # https://docs.djangoproject.com/en/2.1/ref/settings/#databases - - -DATABASE_ROUTERS = ["openIMIS.routers.DashboardDatabaseRouter"] - - - - -# Celery message broker configuration for RabbitMQ. One can also use Redis on AWS SQS -CELERY_BROKER_URL = os.environ.get("CELERY_BROKER_URL", "amqp://rabitmq") -if 'CELERY_RESULT_BACKEND' in os.environ: - CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND") - -if 'CACHE_BACKEND' in os.environ and 'CACHE_URL' in os.environ: - CACHE_BACKEND = os.environ.get('CACHE_BACKEND') - CACHE_URL = os.environ.get("CACHE_URL") - CACHE_OPTIONS = os.environ.get("CACHE_OPTIONS", None) - if CACHE_OPTIONS: - CACHE_OPTIONS = json.loads(CACHE_OPTIONS) -else: - CACHE_BACKEND = 'django.core.cache.backends.locmem.LocMemCache' - CACHE_URL = None - CACHE_OPTIONS = None - -CACHE_PARAM = {} -CACHE_PARAM['BACKEND'] = CACHE_BACKEND -if CACHE_URL: - CACHE_PARAM['LOCATION'] = CACHE_URL - -if CACHE_OPTIONS: - CACHE_PARAM['OPTIONS'] = CACHE_OPTIONS - - -CACHES = { - 'default': { - **CACHE_PARAM, - 'KEY_PREFIX': "oi" - }, - 'location': { - **CACHE_PARAM, - 'KEY_PREFIX': "loc" - }, - 'coverage': { - **CACHE_PARAM, - 'KEY_PREFIX': "cov" - - } -} - -# This scheduler config will: -# - Store jobs in the project database -# - Execute jobs in threads inside the application process, for production use, we could use a dedicated process -SCHEDULER_CONFIG = { - "apscheduler.jobstores.default": { - "class": "django_apscheduler.jobstores:DjangoJobStore" - }, - "apscheduler.executors.processpool": {"type": "threadpool"}, -} - -SCHEDULER_AUTOSTART = os.environ.get("SCHEDULER_AUTOSTART", False) - -# Normally, one creates a "scheduler" method that calls the appropriate scheduler.add_job but since we are in a -# modular architecture and calling only once from the core module, this has to be dynamic. -# This list will be called with scheduler.add_job() as specified: -# Note that the document implies that the time is local and follows DST but that seems false and in UTC regardless -SCHEDULER_JOBS = [ - { - "method": "policy.tasks.get_policies_for_renewal", - "args": ["cron"], - "kwargs": {"id": "openimis_renewal_batch", "hour": 8, "minute": 30, "replace_existing": True}, - }, - # { - # "method": "policy_notification.tasks.send_notification_messages", - # "args": ["cron"], - # "kwargs": {"id": "openimis_notification_batch", 'day_of_week': '*', - # "hour": "8,12,16,20", "replace_existing": True}, - # }, - # { - # "method": "claim_ai_quality.tasks.claim_ai_processing", - # "args": ["cron"], - # "kwargs": {"id": "claim_ai_processing", - # "hour": 0 - # "minute", 30 - # "replace_existing": True}, - # }, -] -# This one is called directly with the scheduler object as first parameter. The methods can schedule things on their own -SCHEDULER_CUSTOM = [ - { - "method": "core.tasks.sample_method", - "args": ["sample"], - "kwargs": {"sample_named": "param"}, - }, -] - - -AUTH_USER_MODEL = "core.User" - -# Password validation -# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators - -if not DEBUG: - AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", - }, - { - "NAME": "core.utils.CustomPasswordValidator", - } - ] - - -# Internationalization -# https://docs.djangoproject.com/en/2.1/topics/i18n/ - -LANGUAGE_CODE = "en-GB" - -TIME_ZONE = "UTC" - -USE_I18N = True - -USE_L10N = True - -USE_TZ = False - -# List of places to look for translations, this could include an external translation module -LOCALE_PATHS = get_locale_folders() + [ - os.path.join(BASE_DIR, "locale"), -] - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/2.1/howto/static-files/ - -STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") -STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" -STATIC_URL = "/%sstatic/" % SITE_ROOT() - - -ASGI_APPLICATION = "openIMIS.asgi.application" - -# Django channels require rabbitMQ server, by default it use 127.0.0.1, port 5672 -if "CHANNELS_BACKEND" in os.environ and "CHANNELS_HOST" in os.environ: - CHANNEL_LAYERS = { - "default": { - "BACKEND": os.environ.get("CHANNELS_BACKEND"), - "CONFIG": { - "hosts": [os.environ.get("CHANNELS_HOST")], - # "ssl_context": ... (optional) - }, - }, - } - - -# Django email settings -EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" - -EMAIL_HOST = os.environ.get("EMAIL_HOST", "localhost") -EMAIL_PORT = os.environ.get("EMAIL_PORT", "1025") -EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER", "") -EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD", "") -EMAIL_USE_TLS = os.environ.get("EMAIL_USE_TLS", False) -EMAIL_USE_SSL = os.environ.get("EMAIL_USE_SSL", False) - -# By default, the maximum upload size is 2.5Mb, which is a bit short for base64 picture upload -DATA_UPLOAD_MAX_MEMORY_SIZE = int(os.environ.get('DATA_UPLOAD_MAX_MEMORY_SIZE', 10 * 1024 * 1024)) - - -# Insuree number validation. One can use the validator function for specific processing or just specify the length -# and modulo for the typical use case. These two can be overridden from the environment but the validator being a -# function, it is not possible. -# -# def insuree_number_validator(x): -# if str(x)[0] != "x": -# return ["don't start with x"] -# else: -# return [] -# -# - - - -# There used to be a default password for zip files but for security reasons, it was removed. Trying to export -# without a password defined is going to fail -MASTER_DATA_PASSWORD = os.environ.get("MASTER_DATA_PASSWORD", None) - -FRONTEND_URL = os.environ.get("FRONTEND_URL", "") - -USE_X_FORWARDED_HOST = True -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') - -OPENSEARCH_HOST = os.environ.get("OPENSEARCH_HOST", "0.0.0.0") -OPEN_SEARCH_HTTP_PORT = os.environ.get("OPEN_SEARCH_HTTP_PORT", "9200") - -OPENSEARCH_DSL = { - 'default': { - 'hosts': f"{OPENSEARCH_HOST}:{OPEN_SEARCH_HTTP_PORT}", - 'http_auth': ( - f"{os.environ.get('OPENSEARCH_ADMIN')}", - f"{os.environ.get('OPENSEARCH_PASSWORD')}" - ), - 'timeout': 120, - } -} - -PASSWORD_MIN_LENGTH = int(os.getenv('PASSWORD_MIN_LENGTH', 8)) -PASSWORD_UPPERCASE = int(os.getenv('PASSWORD_UPPERCASE', 1)) -PASSWORD_LOWERCASE = int(os.getenv('PASSWORD_LOWERCASE', 1)) -PASSWORD_DIGITS = int(os.getenv('PASSWORD_DIGITS', 1)) -PASSWORD_SYMBOLS = int(os.getenv('PASSWORD_SYMBOLS', 1)) \ No newline at end of file diff --git a/openIMIS/openIMIS/settings/__init__.py b/openIMIS/openIMIS/settings/__init__.py new file mode 100644 index 0000000..27fbcb8 --- /dev/null +++ b/openIMIS/openIMIS/settings/__init__.py @@ -0,0 +1,38 @@ +""" +Django settings for openIMIS project. +""" +import json +import logging +import os + +from ..openimisapps import openimis_apps, get_locale_folders +from datetime import timedelta +from cryptography.hazmat.primitives import serialization +from .common import MODE + +from split_settings.tools import optional, include + +LOAD_ENV = os.environ.get("LOAD_ENV", '.env') +if LOAD_ENV != '': + from dotenv import load_dotenv, find_dotenv + ENV_PATH = find_dotenv(filename=LOAD_ENV) + load_dotenv(dotenv_path=ENV_PATH) + +base_settings = [ + 'security.py', + 'base.py', + 'database.py', + 'logging.py', + 'sentry.py', + 'scheduler.py', + 'queue_cache.py', + 'opensearch.py', + 'trad.py', + f'{MODE}.py' + # Optional local settings + #optional('local_settings.py'), +] + +# Include the components +include(*base_settings) + diff --git a/openIMIS/openIMIS/settings/base.py b/openIMIS/openIMIS/settings/base.py new file mode 100644 index 0000000..089320c --- /dev/null +++ b/openIMIS/openIMIS/settings/base.py @@ -0,0 +1,195 @@ +""" +Django settings for openIMIS project. +""" +import json +import logging +import os + +from ..openimisapps import openimis_apps, get_locale_folders +from datetime import timedelta +from .common import DEBUG, BASE_DIR, MODE +from .security import REMOTE_USER_AUTHENTICATION + +# Makes openimis_apps available to other modules +OPENIMIS_APPS = openimis_apps() + + +def SITE_ROOT(): + root = os.environ.get("SITE_ROOT", "") + if root == "": + return root + elif root.endswith("/"): + return root + else: + return "%s/" % root + + +def SITE_URL(): + url = os.environ.get("SITE_URL", "") + if url == "": + return url + elif url.endswith("/"): + return url[:-1] + else: + return url + + +SITE_FRONT = os.environ.get("SITE_FRONT", "front") +FRONTEND_URL = SITE_ROOT() + SITE_FRONT + +# Application definition + +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "graphene_django", + "graphql_jwt.refresh_token.apps.RefreshTokenConfig", + "test_without_migrations", + "rest_framework", + "rules", + "health_check", # required + "health_check.db", # stock Django health checkers + "health_check.cache", + "health_check.storage", + "django_apscheduler", + "channels", # Websocket support + "developer_tools", + "drf_spectacular", # Swagger UI for FHIR API + "axes", + "django_opensearch_dsl", +] +INSTALLED_APPS += OPENIMIS_APPS +INSTALLED_APPS += ["apscheduler_runner", "signal_binding"] # Signal binding should be last installed module + +AUTHENTICATION_BACKENDS = [] + +if os.environ.get("REMOTE_USER_AUTHENTICATION", "false").lower() == "true": + AUTHENTICATION_BACKENDS += ["django.contrib.auth.backends.RemoteUserBackend"] + +AUTHENTICATION_BACKENDS += [ + "axes.backends.AxesStandaloneBackend", + "rules.permissions.ObjectPermissionBackend", + "graphql_jwt.backends.JSONWebTokenBackend", + "django.contrib.auth.backends.ModelBackend", +] + +ANONYMOUS_USER_NAME = None + +REST_FRAMEWORK = { + "DEFAULT_AUTHENTICATION_CLASSES": [ + "core.jwt_authentication.JWTAuthentication", + "rest_framework.authentication.BasicAuthentication", + "rest_framework.authentication.SessionAuthentication", + ], + "EXCEPTION_HANDLER": "openIMIS.ExceptionHandlerDispatcher.dispatcher", + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', +} +if REMOTE_USER_AUTHENTICATION: + REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"].insert( + 0, + "rest_framework.authentication.RemoteUserAuthentication", + ) + +SPECTACULAR_SETTINGS = { + 'TITLE': 'FHIR R4', + 'DESCRIPTION': 'openIMIS FHIR R4 API', + 'VERSION': '1.0.0', + 'AUTHENTICATION_WHITELIST': [ + 'core.jwt_authentication.JWTAuthentication', + 'api_fhir_r4.views.CsrfExemptSessionAuthentication' + ], +} + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", + 'core.middleware.GraphQLRateLimitMiddleware', + "axes.middleware.AxesMiddleware", + "core.middleware.DefaultAxesAttributesMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.locale.LocaleMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "core.middleware.SecurityHeadersMiddleware", +] + +if DEBUG: + # Attach profiler middleware + MIDDLEWARE.append( + "django_cprofile_middleware.middleware.ProfilerMiddleware" + ) + DJANGO_CPROFILE_MIDDLEWARE_REQUIRE_STAFF = False + +if REMOTE_USER_AUTHENTICATION: + MIDDLEWARE += ["core.security.RemoteUserMiddleware"] +MIDDLEWARE += [ + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +ROOT_URLCONF = "openIMIS.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +WSGI_APPLICATION = "openIMIS.wsgi.application" + +GRAPHENE = { + "SCHEMA": "openIMIS.schema.schema", + "RELAY_CONNECTION_MAX_LIMIT": 100, + "GRAPHIQL_HEADER_EDITOR_ENABLED": True, + "MIDDLEWARE": [ + "openIMIS.tracer.TracerMiddleware", + "openIMIS.schema.GQLUserLanguageMiddleware", + "graphql_jwt.middleware.JSONWebTokenMiddleware" + ], +} + +if DEBUG: + GRAPHENE['MIDDLEWARE'] += [ + "graphene_django.debug.DjangoDebugMiddleware" # adds a _debug query to graphQL with sql debug info + ] + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.1/howto/static-files/ + +STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") +STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" +STATIC_URL = "/%sstatic/" % SITE_ROOT() + + +ASGI_APPLICATION = "openIMIS.asgi.application" + + +# Django email settings +EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" +EMAIL_HOST = os.environ.get("EMAIL_HOST", "localhost") +EMAIL_PORT = os.environ.get("EMAIL_PORT", "1025") +EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER", "") +EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD", "") +EMAIL_USE_TLS = os.environ.get("EMAIL_USE_TLS", False) +EMAIL_USE_SSL = os.environ.get("EMAIL_USE_SSL", False) + +# By default, the maximum upload size is 2.5Mb, which is a bit short for base64 picture upload +DATA_UPLOAD_MAX_MEMORY_SIZE = int(os.environ.get('DATA_UPLOAD_MAX_MEMORY_SIZE', 10 * 1024 * 1024)) + +FRONTEND_URL = os.environ.get("FRONTEND_URL", "") diff --git a/openIMIS/openIMIS/settings/common.py b/openIMIS/openIMIS/settings/common.py new file mode 100644 index 0000000..402f262 --- /dev/null +++ b/openIMIS/openIMIS/settings/common.py @@ -0,0 +1,10 @@ +import os + + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +MODE = os.environ.get("MODE", 'prod').lower() +if MODE == "dev": + DEBUG = True +else: + DEBUG = os.environ.get("DEBUG", "false").lower() == "true" diff --git a/openIMIS/openIMIS/settings/database.py b/openIMIS/openIMIS/settings/database.py new file mode 100644 index 0000000..2013a26 --- /dev/null +++ b/openIMIS/openIMIS/settings/database.py @@ -0,0 +1,95 @@ +import os +import json +# no db +DATABASES = {} +DB_DEFAULT = os.environ.get("DB_DEFAULT", 'postgresql') + +if os.environ.get("NO_DATABASE", "False") == "True": + + DATABASES['default'] = { + # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ' ../script/sqlite.db', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +if "DB_OPTIONS" in os.environ: + DATABASE_OPTIONS = json.loads(os.environ["DB_OPTIONS"]) + MSSQL_DATABASE_OPTIONS = DATABASE_OPTIONS + PSQL_DATABASE_OPTIONS = DATABASE_OPTIONS +else: + if os.name == "nt": + MSSQL_DATABASE_OPTIONS = { + "driver": "ODBC Driver 17 for SQL Server", + "extra_params": "Persist Security Info=False;server=%s" + % os.environ.get("DB_HOST"), + "unicode_results": True, + } + else: + MSSQL_DATABASE_OPTIONS = { + "driver": "ODBC Driver 17 for SQL Server", + "unicode_results": True, + } + PSQL_DATABASE_OPTIONS = {'options': '-c search_path=django,public'} + +DEFAULT_ENGINE = os.environ.get("DB_ENGINE", "mssql" if DB_DEFAULT == 'mssql' else "django.db.backends.postgresql") +DEFAULT_NAME = os.environ.get("DB_NAME", "imis") +DEFAULT_USER = os.environ.get("DB_USER", "IMISuser") +DEFAULT_PASSWORD = os.environ.get("DB_PASSWORD") +DEFAULT_HOST = os.environ.get("DB_HOST", 'db') +DEFAULT_PORT = os.environ.get("DB_PORT", "1433" if DB_DEFAULT == 'mssql' else "5432") + + + +if DB_DEFAULT == 'mssql': + DATABASES["default"] = { + "ENGINE": os.environ.get("MSSQL_DB_ENGINE", DEFAULT_ENGINE), + "NAME": os.environ.get("MSSQL_DB_NAME", DEFAULT_NAME), + "USER": os.environ.get("MSSQL_DB_USER", DEFAULT_USER), + "PASSWORD": os.environ.get("MSSQL_DB_PASSWORD", DEFAULT_PASSWORD), + "HOST": os.environ.get("MSSQL_DB_HOST", DEFAULT_HOST), + "PORT": os.environ.get("MSSQL_DB_PORT", DEFAULT_PORT), + "OPTIONS": MSSQL_DATABASE_OPTIONS, + 'TEST': { + 'NAME': os.environ.get("DB_TEST_NAME", "test_" + os.environ.get("MSSQL_DB_NAME", "imis")), + } + } +else: + DATABASES["default"] = { + "ENGINE": os.environ.get("PSQL_DB_ENGINE", DEFAULT_ENGINE), + "NAME": os.environ.get("PSQL_DB_NAME", DEFAULT_NAME), + "USER": os.environ.get("PSQL_DB_USER", DEFAULT_USER), + "PASSWORD": os.environ.get("PSQL_DB_PASSWORD", DEFAULT_PASSWORD), + "HOST": os.environ.get("PSQL_DB_HOST", DEFAULT_HOST), + "PORT": os.environ.get("PSQL_DB_PORT", DEFAULT_PORT), + "OPTIONS": PSQL_DATABASE_OPTIONS, + 'TEST': { + 'NAME': os.environ.get("DB_TEST_NAME", "test_" + os.environ.get("MSSQL_DB_NAME", "imis")), + } + } + +# should not add that config unless used +if "DASHBOARD_DB_ENGINE" in os.environ: + DATABASES['dashboard_db'] = { + "ENGINE": os.environ.get("DASHBOARD_DB_ENGINE", DEFAULT_ENGINE), + "NAME": os.environ.get("DASHBOARD_DB_NAME"), + "USER": os.environ.get("DASHBOARD_DB_USER"), + "PASSWORD": os.environ.get("DASHBOARD_DB_PASSWORD"), + "HOST": os.environ.get("DASHBOARD_DB_HOST", DEFAULT_HOST), + "PORT": os.environ.get("DASHBOARD_DB_PORT", DEFAULT_PORT) + } + +if "sql_server.pyodbc" in DATABASES["default"]['ENGINE'] or "mssql" in DATABASES["default"]['ENGINE']: + MSSQL = True + +else: + MSSQL = False + + # Database + # https://docs.djangoproject.com/en/2.1/ref/settings/#databases + + +DATABASE_ROUTERS = ["openIMIS.routers.DashboardDatabaseRouter"] + diff --git a/openIMIS/openIMIS/settings/dev.py b/openIMIS/openIMIS/settings/dev.py new file mode 100644 index 0000000..69eb681 --- /dev/null +++ b/openIMIS/openIMIS/settings/dev.py @@ -0,0 +1,13 @@ +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +# Set ALLOWED_HOSTS +ALLOWED_HOSTS = ['*'] +CSRF_TRUSTED_ORIGINS = [ + 'https://localhost', + 'https://192.168.0.1', + 'https://localhost:8000', + 'https://192.168.0.1:8000', + 'https://localhost:3000', + 'https://192.168.0.1:3000', +] +# Set CORS_ALLOWED_ORIGINS to match CSRF_TRUSTED_ORIGINS +CORS_ALLOWED_ORIGINS = CSRF_TRUSTED_ORIGINS \ No newline at end of file diff --git a/openIMIS/openIMIS/settings/logging.py b/openIMIS/openIMIS/settings/logging.py new file mode 100644 index 0000000..b4b36c6 --- /dev/null +++ b/openIMIS/openIMIS/settings/logging.py @@ -0,0 +1,52 @@ +import os +from .common import DEBUG + +DEFAULT_LOGGING_HANDLER = os.getenv("DJANGO_LOG_HANDLER", "console") +DEFAULT_DB_LOGGING_HANDLER = os.getenv("DJANGO_DB_LOG_HANDLER", "db-queries") +LOGGING_LEVEL = os.getenv("DJANGO_LOG_LEVEL", "DEBUG" if DEBUG else "WARNING") + + + + +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "standard": {"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"}, + "short": {"format": "%(name)s: %(message)s"}, + }, + "handlers": { + "db-queries": { + "level": LOGGING_LEVEL, + "class": "logging.handlers.RotatingFileHandler", + "filename": os.environ.get("DB_QUERIES_LOG_FILE", "db-queries.log"), + "maxBytes": 1024 * 1024 * 5, # 5 MB + "backupCount": 10, + "formatter": "standard", + }, + "debug-log": { + "level": LOGGING_LEVEL, + "class": "logging.handlers.RotatingFileHandler", + "filename": os.environ.get("DEBUG_LOG_FILE", "debug.log"), + "maxBytes": 1024 * 1024 * 5, # 5 MB + "backupCount": 3, + "formatter": "standard", + }, + "console": {"class": "logging.StreamHandler", "formatter": "short"}, + }, + "loggers": { + "": { + "level": LOGGING_LEVEL, + "handlers": [DEFAULT_LOGGING_HANDLER], + }, + "django.db.backends": { + "level": LOGGING_LEVEL, + "propagate": False, + "handlers": [DEFAULT_DB_LOGGING_HANDLER], + }, + "openIMIS": { + "level": LOGGING_LEVEL, + "handlers": [DEFAULT_LOGGING_HANDLER], + }, + }, +} \ No newline at end of file diff --git a/openIMIS/openIMIS/settings/opensearch.py b/openIMIS/openIMIS/settings/opensearch.py new file mode 100644 index 0000000..9a6e833 --- /dev/null +++ b/openIMIS/openIMIS/settings/opensearch.py @@ -0,0 +1,17 @@ +import os + + +OPENSEARCH_HOST = os.environ.get("OPENSEARCH_HOST", "0.0.0.0") +OPEN_SEARCH_HTTP_PORT = os.environ.get("OPEN_SEARCH_HTTP_PORT", "9200") +OPENSEARCH_DSL_AUTOSYNC = os.environ.get('OPENSEARCH_DSL_AUTOSYNC', 'True') == 'True' + +OPENSEARCH_DSL = { + 'default': { + 'hosts': f"{OPENSEARCH_HOST}:{OPEN_SEARCH_HTTP_PORT}", + 'http_auth': ( + f"{os.environ.get('OPENSEARCH_ADMIN')}", + f"{os.environ.get('OPENSEARCH_PASSWORD')}" + ), + 'timeout': 120, + } +} diff --git a/openIMIS/openIMIS/settings/prod.py b/openIMIS/openIMIS/settings/prod.py new file mode 100644 index 0000000..01fc026 --- /dev/null +++ b/openIMIS/openIMIS/settings/prod.py @@ -0,0 +1,56 @@ + + +GRAPHQL_JWT.update({ + "JWT_COOKIE_SECURE": True, + "JWT_COOKIE_SAMESITE": "Lax", +}) + + +# Fetch protocols and hosts from environment variables +protos = os.environ.get('PROTOS', default='https').split(',') +hosts = os.environ.get('HOSTS', default='') + +# Set ALLOWED_HOSTS +ALLOWED_HOSTS = hosts.split(',') if hosts else ['*'] + +# Create CSRF_TRUSTED_ORIGINS by combining protocols and hosts +CSRF_TRUSTED_ORIGINS = [f'{proto}://{host.strip()}' for proto in protos for host in ALLOWED_HOSTS if host != '*'] + +# If ALLOWED_HOSTS is ['*'], set a default for CSRF_TRUSTED_ORIGINS +if not CSRF_TRUSTED_ORIGINS: + CSRF_TRUSTED_ORIGINS = ['https://localhost'] + +# Set CORS_ALLOWED_ORIGINS to match CSRF_TRUSTED_ORIGINS +CORS_ALLOWED_ORIGINS = CSRF_TRUSTED_ORIGINS + +# Determine if we're behind a proxy (using http in protos indicates proxy use) +BEHIND_PROXY = 'http' in protos + +# Security settings +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +USE_X_FORWARDED_HOST = BEHIND_PROXY +SECURE_SSL_REDIRECT = not BEHIND_PROXY # Only redirect if not behind a proxy + +# CSRF settings +CSRF_COOKIE_SECURE = True +SESSION_COOKIE_SECURE = True + +# CORS settings +CORS_ALLOW_CREDENTIALS = True + +# Cookie settings +SESSION_COOKIE_SAMESITE = 'Lax' # or 'None' if cross-site +CSRF_COOKIE_SAMESITE = 'Lax' # or 'None' if cross-site +CSRF_COOKIE_HTTPONLY = False # False if you need to access it from JavaScript + +# HSTS settings (if using HTTPS) +if 'https' in protos: + SECURE_HSTS_SECONDS = 31536000 # 1 year + SECURE_HSTS_INCLUDE_SUBDOMAINS = True + SECURE_HSTS_PRELOAD = True + SECURE_HSTS_REDIRECT = True + +# Additional security settings +X_FRAME_OPTIONS = 'DENY' +SECURE_CONTENT_TYPE_NOSNIFF = True +SECURE_BROWSER_XSS_FILTER = True \ No newline at end of file diff --git a/openIMIS/openIMIS/settings/queue_cache.py b/openIMIS/openIMIS/settings/queue_cache.py new file mode 100644 index 0000000..c56c589 --- /dev/null +++ b/openIMIS/openIMIS/settings/queue_cache.py @@ -0,0 +1,55 @@ +import os +import json + + +# Celery message broker configuration for RabbitMQ. One can also use Redis on AWS SQS +CELERY_BROKER_URL = os.environ.get("CELERY_BROKER_URL", "amqp://rabitmq") +if 'CELERY_RESULT_BACKEND' in os.environ: + CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND") + +if 'CACHE_BACKEND' in os.environ and 'CACHE_URL' in os.environ: + CACHE_BACKEND = os.environ.get('CACHE_BACKEND') + CACHE_URL = os.environ.get("CACHE_URL") + CACHE_OPTIONS = os.environ.get("CACHE_OPTIONS", None) + if CACHE_OPTIONS: + CACHE_OPTIONS = json.loads(CACHE_OPTIONS) +else: + CACHE_BACKEND = 'django.core.cache.backends.locmem.LocMemCache' + CACHE_URL = None + CACHE_OPTIONS = None + +CACHE_PARAM = {} +CACHE_PARAM['BACKEND'] = CACHE_BACKEND +if CACHE_URL: + CACHE_PARAM['LOCATION'] = CACHE_URL + +if CACHE_OPTIONS: + CACHE_PARAM['OPTIONS'] = CACHE_OPTIONS + +CACHES = { + 'default': { + **CACHE_PARAM, + 'KEY_PREFIX': "oi" + }, + 'location': { + **CACHE_PARAM, + 'KEY_PREFIX': "loc" + }, + 'coverage': { + **CACHE_PARAM, + 'KEY_PREFIX': "cov" + + } +} + +# Django channels require rabbitMQ server, by default it use 127.0.0.1, port 5672 +if "CHANNELS_BACKEND" in os.environ and "CHANNELS_HOST" in os.environ: + CHANNEL_LAYERS = { + "default": { + "BACKEND": os.environ.get("CHANNELS_BACKEND"), + "CONFIG": { + "hosts": [os.environ.get("CHANNELS_HOST")], + # "ssl_context": ... (optional) + }, + }, + } diff --git a/openIMIS/openIMIS/settings/scheduler.py b/openIMIS/openIMIS/settings/scheduler.py new file mode 100644 index 0000000..b58dc36 --- /dev/null +++ b/openIMIS/openIMIS/settings/scheduler.py @@ -0,0 +1,46 @@ +import os +# This scheduler config will: +# - Store jobs in the project database +# - Execute jobs in threads inside the application process, for production use, we could use a dedicated process +SCHEDULER_CONFIG = { + "apscheduler.jobstores.default": { + "class": "django_apscheduler.jobstores:DjangoJobStore" + }, + "apscheduler.executors.processpool": {"type": "threadpool"}, +} + +SCHEDULER_AUTOSTART = os.environ.get("SCHEDULER_AUTOSTART", False) + +# Normally, one creates a "scheduler" method that calls the appropriate scheduler.add_job but since we are in a +# modular architecture and calling only once from the core module, this has to be dynamic. +# This list will be called with scheduler.add_job() as specified: +# Note that the document implies that the time is local and follows DST but that seems false and in UTC regardless +SCHEDULER_JOBS = [ + { + "method": "policy.tasks.get_policies_for_renewal", + "args": ["cron"], + "kwargs": {"id": "openimis_renewal_batch", "hour": 8, "minute": 30, "replace_existing": True}, + }, + # { + # "method": "policy_notification.tasks.send_notification_messages", + # "args": ["cron"], + # "kwargs": {"id": "openimis_notification_batch", 'day_of_week': '*', + # "hour": "8,12,16,20", "replace_existing": True}, + # }, + # { + # "method": "claim_ai_quality.tasks.claim_ai_processing", + # "args": ["cron"], + # "kwargs": {"id": "claim_ai_processing", + # "hour": 0 + # "minute", 30 + # "replace_existing": True}, + # }, +] +# This one is called directly with the scheduler object as first parameter. The methods can schedule things on their own +SCHEDULER_CUSTOM = [ + { + "method": "core.tasks.sample_method", + "args": ["sample"], + "kwargs": {"sample_named": "param"}, + }, +] diff --git a/openIMIS/openIMIS/settings/security.py b/openIMIS/openIMIS/settings/security.py new file mode 100644 index 0000000..83d2567 --- /dev/null +++ b/openIMIS/openIMIS/settings/security.py @@ -0,0 +1,108 @@ +import os +from .common import DEBUG, BASE_DIR +from datetime import timedelta +from cryptography.hazmat.primitives import serialization + + +AUTH_USER_MODEL = "core.User" + +# Password validation +# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators + +if not DEBUG: + AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "core.utils.CustomPasswordValidator", + } + ] + +# SECURITY WARNING: don't run without row security in production! +# Row security is dedicated to filter the data result sets according to users' right +# Example: user registered at a Health Facility should only see claims recorded for that Health Facility +ROW_SECURITY = os.environ.get("ROW_SECURITY", "True").lower() == "true" + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.environ.get( + "SECRET_KEY", "chv^^7i_v3-04!rzu&qe#+h*a=%h(ib#5w9n$!f2q7%2$qp=zz" +) +REMOTE_USER_AUTHENTICATION = os.environ.get("REMOTE_USER_AUTHENTICATION", "false").lower() == "true" + + +GRAPHQL_JWT = { + "JWT_VERIFY_EXPIRATION": True, + "JWT_EXPIRATION_DELTA": timedelta(days=1), + "JWT_REFRESH_EXPIRATION_DELTA": timedelta(days=30), + "JWT_AUTH_HEADER_PREFIX": "Bearer", + "JWT_ENCODE_HANDLER": "core.jwt.jwt_encode_user_key", + "JWT_DECODE_HANDLER": "core.jwt.jwt_decode_user_key", + # This can be used to expose some resources without authentication + "JWT_ALLOW_ANY_CLASSES": [ + "graphql_jwt.mutations.ObtainJSONWebToken", + "graphql_jwt.mutations.Verify", + "graphql_jwt.mutations.Refresh", + "graphql_jwt.mutations.Revoke", + "core.schema.ResetPasswordMutation", + "core.schema.SetPasswordMutation", + ], +} + +# Load RSA keys +private_key_path = os.path.join(BASE_DIR, 'keys', 'jwt_private_key.pem') +public_key_path = os.path.join(BASE_DIR, 'keys', 'jwt_public_key.pem') + +if os.path.exists(private_key_path) and os.path.exists(public_key_path): + with open(private_key_path, 'rb') as f: + private_key = serialization.load_pem_private_key( + f.read(), + password=None, + ) + + with open(public_key_path, 'rb') as f: + public_key = serialization.load_pem_public_key( + f.read(), + ) + + # If RSA keys exist, update the algorithm and add keys to GRAPHQL_JWT settings + GRAPHQL_JWT.update({ + "JWT_ALGORITHM": "RS256", + "JWT_PRIVATE_KEY": private_key, + "JWT_PUBLIC_KEY": public_key, + }) + + +# Lockout mechanism configuration +AXES_ENABLED = True if os.environ.get("MODE", "DEV") == "PROD" else False +AXES_FAILURE_LIMIT = int(os.getenv("LOGIN_LOCKOUT_FAILURE_LIMIT", 5)) +AXES_COOLOFF_TIME = timedelta(minutes=int(os.getenv("LOGIN_LOCKOUT_COOLOFF_TIME", 5))) + +RATELIMIT_CACHE = os.getenv('RATELIMIT_CACHE', 'default') +RATELIMIT_KEY = os.getenv('RATELIMIT_KEY', 'ip') +RATELIMIT_RATE = os.getenv('RATELIMIT_RATE', '150/m') +RATELIMIT_METHOD = os.getenv('RATELIMIT_METHOD', 'ALL') +RATELIMIT_GROUP = os.getenv('RATELIMIT_GROUP', 'graphql') +RATELIMIT_SKIP_TIMEOUT = os.getenv('RATELIMIT_SKIP_TIMEOUT', 'False') + + + + +# Adjust other settings as needed for your specific application +# ... + +# If using GraphQL, ensure the CSRF_EXEMPT_LIST includes your GraphQL endpoint +# CSRF_EXEMPT_LIST = ['/graphql/'] # Adjust as needed + +# There used to be a default password for zip files but for security reasons, it was removed. Trying to export +# without a password defined is going to fail +MASTER_DATA_PASSWORD = os.environ.get("MASTER_DATA_PASSWORD", None) + +PASSWORD_MIN_LENGTH = int(os.getenv('PASSWORD_MIN_LENGTH', 8)) +PASSWORD_UPPERCASE = int(os.getenv('PASSWORD_UPPERCASE', 1)) +PASSWORD_LOWERCASE = int(os.getenv('PASSWORD_LOWERCASE', 1)) +PASSWORD_DIGITS = int(os.getenv('PASSWORD_DIGITS', 1)) +PASSWORD_SYMBOLS = int(os.getenv('PASSWORD_SYMBOLS', 1)) \ No newline at end of file diff --git a/openIMIS/openIMIS/settings/sentry.py b/openIMIS/openIMIS/settings/sentry.py new file mode 100644 index 0000000..9ded7c9 --- /dev/null +++ b/openIMIS/openIMIS/settings/sentry.py @@ -0,0 +1,32 @@ +import os + +SENTRY_DSN = os.environ.get("SENTRY_DSN", None) +SENTRY_SAMPLE_RATE = os.environ.get("SENTRY_SAMPLE_RATE", "0.2") +IS_SENTRY_ENABLED = False + +if SENTRY_DSN is not None: + try: + import sentry_sdk + from sentry_sdk.integrations.django import DjangoIntegration + + sentry_sdk.init( + dsn=SENTRY_DSN, + integrations=[DjangoIntegration()], + # Set traces_sample_rate to 1.0 to capture 100% + # of transactions for performance monitoring. + # We recommend adjusting this value in production, + traces_sample_rate=float(SENTRY_SAMPLE_RATE), + # If you wish to associate users to errors (assuming you are using + # django.contrib.auth) you may enable sending PII data. + send_default_pii=True, + # By default the SDK will try to use the SENTRY_RELEASE + # environment variable, or infer a git commit + # SHA as release, however you may want to set + # something more human-readable. + # release="myapp@1.0.0", + ) + IS_SENTRY_ENABLED = True + except ModuleNotFoundError: + logging.error( + "sentry_sdk has to be installed to use Sentry. Run `pip install --upgrade sentry_sdk` to install it." + ) diff --git a/openIMIS/openIMIS/settings/trad.py b/openIMIS/openIMIS/settings/trad.py new file mode 100644 index 0000000..4b12404 --- /dev/null +++ b/openIMIS/openIMIS/settings/trad.py @@ -0,0 +1,18 @@ +from .common import BASE_DIR +# Internationalization +# https://docs.djangoproject.com/en/2.1/topics/i18n/ + +LANGUAGE_CODE = "en-GB" + +TIME_ZONE = "UTC" + +USE_I18N = True + +USE_L10N = True + +USE_TZ = False + +# List of places to look for translations, this could include an external translation module +LOCALE_PATHS = get_locale_folders() + [ + os.path.join(BASE_DIR, "locale"), +] diff --git a/requirements.txt b/requirements.txt index 5bc8b0b..636ceeb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,7 +32,7 @@ waitress wheel whitenoise django-health-check -requests~=2.32.0 +requests~=2.32.0 apscheduler==3.10.1 # As from v0.4, Django-apscheduler has a migration that is incompatible with SQL Server # (autoincrement int => bigint) so we are using our own fork with a squashed migration @@ -57,3 +57,4 @@ django-opensearch-dsl==0.5.1 zxcvbn~=4.4.28 password-validator==1.0 django-axes==6.4.0 +django-split-settings \ No newline at end of file From f4f0ffa289f3aa5d1ed2faa19f283438240d09cf Mon Sep 17 00:00:00 2001 From: delcroip Date: Fri, 1 Nov 2024 12:28:23 +0100 Subject: [PATCH 35/37] update env vars --- README.md | 382 +++++++++++++++++++++++++++--------------------------- 1 file changed, 191 insertions(+), 191 deletions(-) diff --git a/README.md b/README.md index 8390317..8375f8a 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,72 @@ # Environment Variables -| ENV | Values | Description | +| ENV | Values | Description | | --------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| MODE | DEV, PROD | This is the mode of running the application. There are 2 modes available. DEV for the Development mode and PROD for the production mode. Certain settings will be changed according to the mode. Such as in the PROD mode, mutation will run asynchronously and synchronously otherwise. Same applies to DEBUG, it will be OFF in PROD and TRUE otherwise. | -| DB_ENGINE | django.db.backends.postgresql, mssql | Currently openIMIS supports 2 databases, as the values suggested, postgres and mssql. | -| DEMO_DATASET | true | Define if the database should be initiated with demo dataset. Comment for empty database. | -| DB_DEFAULT | String | String This variables sets the default database engine for the system. Possible values: postgresql, mssql. Default: postgresql. | -| DB_HOST | String | Define the name of your database server | -| DB_PORT | Integer | Define the port on which your database accepts the connection | -| DB_NAME | String | Define the name of the openIMIS database | -| DB_USER | String | Configure the username with which you want to connect to the database | -| DB_PASSWORD | String | Configure the database password | -| DB_TEST_NAME | String | If you are developing unit tests then this setting will create the testing database as per the name set | -| NO_DATABASE | true, false | If set to true, it will use sqlite.db3 as a database | -| DB_OPTIONS | String | Define any additional database options | -| PSQL_DB_ENGINE | String | Define a library to use to connect with postgres database. Default value is django.db.backends.postgresql | -| MSSQL_DB_ENGINE | String | Define a library to use to connect with MS SQL database Default value is mssql. | -| SITE_ROOT | String | Site root that will prefix all exposed endpoints. It's required when working with openIMIS frontend. For example, if the value is set `api` then the endpoint will appear like `your_domain_name/api/xxx` | -| DJANGO_LOG_LEVEL | INFO, WARNING, ERROR, DEBUG | Define the level of logs | -| DJANGO_LOG_HANDLER | console, debug-log | Depending on the value set, application will print the logs | -| DJANGO_DB_LOG_HANDLER | console, debug-log | Depending on the value set, application will print the logs | -| PHOTO_ROOT_PATH | String | Define the path for the photos of insurees. This setting is used in the Insuree module. The value set here will be overwritten by the InsureeConfig file. | -| DJANGO_MIGRATE | True, False | Based on the value set, application runs the migration command before starting up. If the SITE_ROOT value is set to api then the migration will always run regardless of the value | -| SCHEDULER_AUTOSTART | True, False | All the modules will be searched for the scheduled tasks, if the value is set to True | -| OPENSEARCH_HOST | String | Define the opensearch host | -| OPENSEARCH_ADMIN | String | Define the login name for open search | -| OPENSEARCH_PASSWORD | String | Define the admin password to login to open search | -| BE_BRANCH | String | Define the github branch for the Backend form which you wan to install the module. Default is develop. | -| FE_BRANCH | String | Define the github branch for the Front-end form which you wan to install the module. Default is develop. | -| DB_BRANCH | String | Define the github branch for the Database form which you wan to install the module. Default is develop. | -| ALLOWED_HOST | Comma separated String | Define the list of allowed hosts such as IP addresses or Domain names to access the application. If the value is not set it will allow all the IP addresses. | -| LOKALISE_APIKEY | String | Set the lokalise api key. Obtain this key form the lokalise project to be able to use the lokalise-upload | -| OPENIMIS_CONF_JSON | String | Define the path for the openimis config file. If not set the default config from the root folder will be taken. | -| DB_QUERIES_LOG_FILE | String | Define the path of the file to save the database queries. Default is db-queries.log | -| DEBUG_LOG_FILE | String | Define the path of the file to save the debug log. Default is debug.log | -| SENTRY_DSN | String | Set the unique Sentry DSN. This can be obtained from your Sentry account dashboard | -| SENTRY_SAMPLE_RATE | 0-1 | This configuration allows you to to control the rate at which traces are collected. Values are between 0 and 1. 0 means no traces will be collected (tracing is disabled). 1 means traces will be collected for every request. Any value between 0 and 1 represents the probability of capturing trace. For instance, a value 0.3 means that approximately 30% of requests will have traces collected. | -| IS_SENTRY_ENABLED | True, False | Defines if the Sentry error tracking and monitoring functionality is enabled or disabled. | -| SITE_URL | String | Define the base url. This is used to create links in FHIR module | -| SECRET_KEY | String | This is used internally by Django. Make sure to set it up in production server. | -| REMOTE_USER_AUTHENTICATION | true, false | Set it to true if you want to enable the RemoteUserBackend as an authentication backend in Django. By default it's false | -| CELERY_BROKER_URL | String | Define a message broker url for celery. Default value is amqp://rabitmq | -| CHANNELS_HOST | String | Set the host for the Django Channel. Default value is amqp://guest:guest@127.0.0.1/ | -| EMAIL_HOST | String | Define an Email Host. Default value is localhost | -| EMAIL_PORT | Integer | Define a valid port for the email server | -| EMAIL_HOST_USER | String | Set the username to send emails | -| EMAIL_HOST_PASSWORD | String | Set the password for the email | -| EMAIL_USE_TLS | True, False | Configure the TLS setting. Default value is False | -| EMAIL_USE_SSL | True, False | Configure the SSL settings for the emails. Default value is False | -| DATA_UPLOAD_MAX_MEMORY_SIZE | Integer | Define the upload size allowed in **bytes** via the POST request. Default is 10 MB | -| MASTER_DATA_PASSWORD | String | This setting is used in exporting entities. Configure the password to zip the exported entities. | -| FRONTEND_URL | String | Define the URL to access the front-end | -| DJANGO_SETTINGS_MODULE | String | Define the python import path to settings module for Django project. By default it is set to openIMIS.settings | -| OPEHNHIM_URL | String | This setting is used in fhir module. Define the url for openHIM | -| OPEHNHIM_USER | String | This setting is used in fhir module. Define the user for openHIM | -| OPEHNHIM_PASSWORD | String | This setting is used in fhir module. Define the password for openHIM | -| OPENIMIS_CONF | String | Define a path to the config file. By default it reads from ../openimis.json | -| CLAIMDOC_TOKEN | String | Used in backend caching. Define a token to communicate with the remote server. Default is set to 'TestToken' | -| CACHE_BACKEND | String | Specifies the [caching backend](https://docs.djangoproject.com/en/5.0/topics/cache/#setting-up-the-cache) to be used. Default is set to PyMemcached. | -| CACHE_URL | String | Defines the location of the cache backend. Default is `unix:/tmp/memcached.sock` for a Unix socket connection. | -| CACHE_OPTIONS | String | A JSON string representing a dictionary of additional options passed to the cache backend. Empty by default | -| RATELIMIT_CACHE | String | The cache alias to use for rate limiting. Defaults to `default`. | -| RATELIMIT_KEY | String | Key to identify the client for rate limiting; `ip` means it will use the client's IP address. Defaults to `ip`. | -| RATELIMIT_RATE | String | Rate limit value (e.g., `150/m` for 150 requests per minute). Defaults to `150/m`. | -| RATELIMIT_METHOD | String | HTTP methods to rate limit; `ALL` means all methods. Defaults to `ALL`. | -| RATELIMIT_GROUP | String | Group name for the rate limit. Defaults to `graphql`. | -| RATELIMIT_SKIP_TIMEOUT | Boolean | Whether to skip rate limiting during cache timeout. Defaults to `False`. | -| CSRF_TRUSTED_ORIGINS | String | Define the trusted origins for CSRF protection, separated by commas. Defaults to `http://localhost:3000,http://localhost:8000`. | +| MODE | DEV, PROD | This is the mode of running the application. There are 2 modes available. DEV for the Development mode and PROD for the production mode. Certain settings will be changed according to the mode. Such as in the PROD mode, mutation will run asynchronously and synchronously otherwise. Same applies to DEBUG, it will be OFF in PROD and TRUE otherwise. | +| DB_ENGINE | django.db.backends.postgresql, mssql | Currently openIMIS supports 2 databases, as the values suggested, postgres and mssql. | +| DEMO_DATASET | true | Define if the database should be initiated with demo dataset. Comment for empty database. | +| DB_DEFAULT | String | String This variables sets the default database engine for the system. Possible values: postgresql, mssql. Default: postgresql. | +| DB_HOST | String | Define the name of your database server | +| DB_PORT | Integer | Define the port on which your database accepts the connection | +| DB_NAME | String | Define the name of the openIMIS database | +| DB_USER | String | Configure the username with which you want to connect to the database | +| DB_PASSWORD | String | Configure the database password | +| DB_TEST_NAME | String | If you are developing unit tests then this setting will create the testing database as per the name set| +| NO_DATABASE | true, false | If set to true, it will use sqlite.db3 as a database | +| DB_OPTIONS | String | Define any additional database options | +| PSQL_DB_ENGINE | String | Define a library to use to connect with postgres database. Default value is django.db.backends.postgresql | +| MSSQL_DB_ENGINE | String | Define a library to use to connect with MS SQL database Default value is mssql. | +| SITE_ROOT | String | Site root that will prefix all exposed endpoints. It's required when working with openIMIS frontend. For example, if the value is set `api` then the endpoint will appear like `your_domain_name/api/xxx` | +| DJANGO_LOG_LEVEL | INFO, WARNING, ERROR, DEBUG | Define the level of logs | +| DJANGO_LOG_HANDLER | console, debug-log | Depending on the value set, application will print the logs | +| DJANGO_DB_LOG_HANDLER | console, debug-log | Depending on the value set, application will print the logs | +| PHOTO_ROOT_PATH | String | Define the path for the photos of insurees. This setting is used in the Insuree module. The value set here will be overwritten by the InsureeConfig file. | +| DJANGO_MIGRATE | True, False | Based on the value set, application runs the migration command before starting up. If the SITE_ROOT value is set to api then the migration will always run regardless of the value | +| SCHEDULER_AUTOSTART | True, False | All the modules will be searched for the scheduled tasks, if the value is set to True | +| OPENSEARCH_HOST | String | Define the opensearch host | +| OPENSEARCH_ADMIN | String | Define the login name for open search | +| OPENSEARCH_PASSWORD | String | Define the admin password to login to open search | +| BE_BRANCH | String | Define the github branch for the Backend form which you wan to install the module. Default is develop. | +| FE_BRANCH | String | Define the github branch for the Front-end form which you wan to install the module. Default is develop. | +| DB_BRANCH | String | Define the github branch for the Database form which you wan to install the module. Default is develop.| | +| LOKALISE_APIKEY | String | Set the lokalise api key. Obtain this key form the lokalise project to be able to use the lokalise-upload | +| OPENIMIS_CONF_JSON | String | Define the path for the openimis config file. If not set the default config from the root folder will be taken. | +| DB_QUERIES_LOG_FILE | String | Define the path of the file to save the database queries. Default is db-queries.log | +| DEBUG_LOG_FILE | String | Define the path of the file to save the debug log. Default is debug.log | +| SENTRY_DSN | String | Set the unique Sentry DSN. This can be obtained from your Sentry account dashboard | +| SENTRY_SAMPLE_RATE | 0-1 | This configuration allows you to to control the rate at which traces are collected. Values are between 0 and 1. 0 means no traces will be collected (tracing is disabled). 1 means traces will be collected for every request. Any value between 0 and 1 represents the probability of capturing trace. For instance, a value 0.3 means that approximately 30% of requests will have traces collected. | +| IS_SENTRY_ENABLED | True, False | Defines if the Sentry error tracking and monitoring functionality is enabled or disabled. | +| SITE_URL | String | Define the base url. This is used to create links in FHIR module | +| SITE_FRONT | String | Define base uri for the frontend| +| FRONTEND_URL | String | Define the frontend URL if not aligned with SITE_URL/SITE_FRONT| +| SECRET_KEY | String | This is used internally by Django. Make sure to set it up in production server. | +| REMOTE_USER_AUTHENTICATION | true, false | Set it to true if you want to enable the RemoteUserBackend as an authentication backend in Django. By default it's false | +| CELERY_BROKER_URL | String | Define a message broker url for celery. Default value is amqp://rabitmq | +| CHANNELS_HOST | String | Set the host for the Django Channel. Default value is amqp://guest:guest@127.0.0.1/ | +| EMAIL_HOST | String | Define an Email Host. Default value is localhost | +| EMAIL_PORT | Integer | Define a valid port for the email server | +| EMAIL_HOST_USER | String | Set the username to send emails | +| EMAIL_HOST_PASSWORD | String | Set the password for the email | +| EMAIL_USE_TLS | True, False | Configure the TLS setting. Default value is False | +| EMAIL_USE_SSL | True, False | Configure the SSL settings for the emails. Default value is False | +| DATA_UPLOAD_MAX_MEMORY_SIZE | Integer | Define the upload size allowed in **bytes** via the POST request. Default is 10 MB | +| MASTER_DATA_PASSWORD | String | This setting is used in exporting entities. Configure the password to zip the exported entities. | +| DJANGO_SETTINGS_MODULE | String | Define the python import path to settings module for Django project. By default it is set to openIMIS.settings | +| OPEHNHIM_URL | String | This setting is used in fhir module. Define the url for openHIM | +| OPEHNHIM_USER | String | This setting is used in fhir module. Define the user for openHIM | +| OPEHNHIM_PASSWORD | String | This setting is used in fhir module. Define the password for openHIM | +| OPENIMIS_CONF | String | Define a path to the config file. By default it reads from ../openimis.json| +| CLAIMDOC_TOKEN | String | Used in backend caching. Define a token to communicate with the remote server. Default is set to 'TestToken' | +| CACHE_BACKEND | String | Specifies the [caching backend](https://docs.djangoproject.com/en/5.0/topics/cache/#setting-up-the-cache) to be used. Default is set to PyMemcached. | +| CACHE_URL | String | Defines the location of the cache backend. Default is `unix:/tmp/memcached.sock` for a Unix socket connection. | +| CACHE_OPTIONS | String | A JSON string representing a dictionary of additional options passed to the cache backend. Empty by default | +| RATELIMIT_CACHE | String | The cache alias to use for rate limiting. Defaults to `default`. | +| RATELIMIT_KEY | String | Key to identify the client for rate limiting; `ip` means it will use the client's IP address. Defaults to `ip`. | +| RATELIMIT_RATE | String | Rate limit value (e.g., `150/m` for 150 requests per minute). Defaults to `150/m`. | +| RATELIMIT_METHOD | String | HTTP methods to rate limit; `ALL` means all methods. Defaults to `ALL`. | +| RATELIMIT_GROUP | String | Group name for the rate limit. Defaults to `graphql`. | +| RATELIMIT_SKIP_TIMEOUT | Boolean | Whether to skip rate limiting during cache timeout. Defaults to `False`. | +| HOSTS | String | Define the trusted domains that are used for PROD CORS and CSRF protection, separated by commas. Defaults to `localhost, 192.168.0.1`. | ## Developers setup @@ -78,61 +78,61 @@ When programming for openIMIS backend, you are highly encouraged to use the feat - install python 3, recommended in a [venv](https://docs.python.org/3/library/venv.html) or [virtualenv](https://virtualenv.pypa.io) - install [pip](https://pip.pypa.io) - within `openimis-be_py` directory - - install openIMIS (external) dependencies: `pip install -r requirements.txt`. For development workstations, one can use `pip install -r dev-requirements.txt` instead, for more modules. - - In the script directory, - - generate the openIMIS modules dependencies file (from openimis.json config): `python modules-requirements.py openimis.json > modules-requirements.txt` - - if you previously installed openIMIS on another version, it seems safe to uninstall all previous modules-requirement to be sure it match current version `pip uninstall -r modules-requirements.txt` - - install openIMIS current modules: `pip install -r modules-requirements.txt` - - Copy the example environment setup and adjust the settings (like database connection): `cp .env.example .env`. - Refer to .env.example or the Environment Variable tables above for more info. + - install openIMIS (external) dependencies: `pip install -r requirements.txt`. For development workstations, one can use `pip install -r dev-requirements.txt` instead, for more modules. + - In the script directory, + - generate the openIMIS modules dependencies file (from openimis.json config): `python modules-requirements.py openimis.json > modules-requirements.txt` + - if you previously installed openIMIS on another version, it seems safe to uninstall all previous modules-requirement to be sure it match current version `pip uninstall -r modules-requirements.txt` + - install openIMIS current modules: `pip install -r modules-requirements.txt` + - Copy the example environment setup and adjust the settings (like database connection): `cp .env.example .env`. + Refer to .env.example or the Environment Variable tables above for more info. - start openIMIS from within `openimis-be_py/openIMIS`: `python manage.py runserver` At this stage, you may (depends on the database you connect to) need to: - apply django migrations, from `openimis-be_py/openIMIS`: `python manage.py migrate` - create a superuser for django admin console, from - `openimis-be_py/openIMIS`: `python manage.py createsuperuser` (will - not prompt for a password) and then `python manage.py changepassword + `openimis-be_py/openIMIS`: `python manage.py createsuperuser` (will + not prompt for a password) and then `python manage.py changepassword ` ### To edit (modify) an existing openIMIS module (e.g. `openimis-be-claim`) - checkout the module's git repo NEXT TO (not within!) `openimis-be_py` directory and create a git branch for your changes - from `openimis-be_py` - - uninstall the packaged module you want to work on (example: openimis-be-claim): `pip uninstall openimis-be-claim` - - install the 'local' version of the module: `pip install -e ../openimis-be-claim_py/` + - uninstall the packaged module you want to work on (example: openimis-be-claim): `pip uninstall openimis-be-claim` + - install the 'local' version of the module: `pip install -e ../openimis-be-claim_py/` - from here on, openIMIS is using the local content of the module (with live update) ### To create a new openIMIS module (e.g. `openimis-be-mymodule`) - create a (git-enabled) directory next to the other modules, with a subdirectory named as your module 'logical' name: `/openimis-be-mymodule_py/mymodule` - from `/openimis-be_py/openIMIS`: - - create the module skeleton: `python manage.py startapp mymodule ../../openimis-be-mymodule_py/mymodule` - - prepare your module to be mounted via pip: create and complete the `/openimis-be-mymodule_py/setup.py` (and README.md,... files) - - every openIMIS module must provide its urlpatterns (even if empty): - - create the file `/openimis-be-mymodule_py/mymodule/urls.py` - - with content: `urlpatterns = []` - - register your module in the pip requirements of openIMIS, referencing your 'local' codebase: `pip install -e ../../openimis-be-mymodule_py/` - - register your module to openIMIS django site in `/openimis-be_py/openimis.json` + - create the module skeleton: `python manage.py startapp mymodule ../../openimis-be-mymodule_py/mymodule` + - prepare your module to be mounted via pip: create and complete the `/openimis-be-mymodule_py/setup.py` (and README.md,... files) + - every openIMIS module must provide its urlpatterns (even if empty): + - create the file `/openimis-be-mymodule_py/mymodule/urls.py` + - with content: `urlpatterns = []` + - register your module in the pip requirements of openIMIS, referencing your 'local' codebase: `pip install -e ../../openimis-be-mymodule_py/` + - register your module to openIMIS django site in `/openimis-be_py/openimis.json` - from here on, your local openIMIS has a new module, directly loaded from your directory. ### To create a distinct implementation of an existing openIMIS module (e.g. `openimis-be-location-dhis2`) - from `openimis-be_py`, uninstall the packaged module you want to replace: `pip uninstall openimis-be-location` - follow the same procedure as for a brand new openIMIS module, - ... but give it the same logical name as the one you want to replace: `/openimis-be-location-dhis2_py/location` + ... but give it the same logical name as the one you want to replace: `/openimis-be-location-dhis2_py/location` ### To manage translations of your module - from your module root dir, execute '../openimis-be_py/script/gettext.sh' - ... this extract all your translations keys from your code into your module root dir/locale/en/LC_MESSAGES/django.po + ... this extract all your translations keys from your code into your module root dir/locale/en/LC_MESSAGES/django.po - you may want to provide translation in generated django.po file... or manage them via lokalize (need to upload the keys,...) ### To run unit tests on a module (example openimis-be-claim) - from `openimis-be_py` - - (re)initialize test database (at this stage structure is not managed by django): - - launch unit tests, with the 'keep database' option: `python + - (re)initialize test database (at this stage structure is not managed by django): + - launch unit tests, with the 'keep database' option: `python manage.py test --keep claim` ### To get profiler report (DEBUG mode only) @@ -144,7 +144,7 @@ In request query include additional parameters: #### Example: -`http://localhost:8000/api/graphql?prof=True&download=True` +`http://localhost:8000/api/graphql?prof=True&download=True` creates profiler report for execution of query/mutation defined in request's POST body. ### To publish (in PyPI) the modified (or new) module @@ -152,8 +152,8 @@ creates profiler report for execution of query/mutation defined in request's POS - adapt the `openimis-be-mymodule_py/setup.py` to (at least) bump version number (e.g. 1.2.3) - commit your changes to the git repo and merge into master - tag the git repo according to your new version number: - - `git tag -a v1.2.3 -m "v1.2.3"` - - `git push --tags` + - `git tag -a v1.2.3 -m "v1.2.3"` + - `git push --tags` - create the PyPI package (can be automated on a ci-build): `python setup.py bdist_wheel` - upload the created package (in `dist/`) to PyPI.org: `twine upload -r pypi dist/openimis_be_mymodule-1.2.3*` @@ -166,12 +166,12 @@ Note: as a distributor, you may want to run an openIMIS version without docker. - clone this repo (creates the `openimis-be_py` directory) and create a git branch (named according to the release you want to bundle) - adapt the `openimis-be_py/openimis.json` to specify the modules (and their versions) to be bundled - make release candidates docker image from `openimis-be_py/`: `docker build . -t openimis-be-2.3.4 [--build-arg="DB_DEFAULT=postgresql"]` - - change the version (openimis-be-2.3.4) to the actual version you want to build - - if only postgresql database is used, include the build-arg argument + - change the version (openimis-be-2.3.4) to the actual version you want to build + - if only postgresql database is used, include the build-arg argument - configure the database connection (see section here below) - run the docker image, referring to environment variables file: `docker run --env-file .env openimis-be-2.3.4` - Note: when starting, the docker image will automatically apply the necessary database migrations to - the database + Note: when starting, the docker image will automatically apply the necessary database migrations to + the database When release candidate is accepted: @@ -183,11 +183,11 @@ When release candidate is accepted: - clone this repo (creates the `openimis-be_py` directory) and create a git branch (named according to the release you want to bundle) - adapt the `openimis-be_py/openimis.json` to specify the modules (and their versions) to be bundled, the "pip" params can be: - - standard pip: `openimis-be-core==1.2.0rc1` - - from local: `-e ../openimis-be-core_py` - - from git: `git+https://github.com/openimis/openimis-be-core_py.git@develop` - - the egg can be specified so pip know what to look `git+https://github.com/openimis/openimis-be-core_py.git@develop#egg=openimis-be-core` - - from tarball: `https://github.com/openimis/openimis-be_py/archive/v1.1.0.tar.gz` + - standard pip: `openimis-be-core==1.2.0rc1` + - from local: `-e ../openimis-be-core_py` + - from git: `git+https://github.com/openimis/openimis-be-core_py.git@develop` + - the egg can be specified so pip know what to look `git+https://github.com/openimis/openimis-be-core_py.git@develop#egg=openimis-be-core` + - from tarball: `https://github.com/openimis/openimis-be_py/archive/v1.1.0.tar.gz` - (required only once)`python -m venv ./venv`: create the python venv - `./venv/Script/activate[.sh/.ps1]`: Activate the venv - `python script/modules-requirements.py openimis.json > modules-requirements.txt`: list the source of the module to install @@ -201,146 +201,146 @@ When release candidate is accepted: The configuration for connection to the database is identical for developers and distributors: - By default, openIMIS is connected to MS-SQL Server: - - via ODBC (and pyodbc) driver - - using TCP/IP protocol (with server DNS name as hostname... or localhost) and fixed port (leave `DB_PORT` here below empty for dynamic port) - - SQL Server (not Windows/AD) authentication (user name password managed in SQL Server admin) - Download and install the ODBC that correspond to your OS and MS-SQL Server version (https://docs.microsoft.com/en-us/sql/connect/odbc/) + - via ODBC (and pyodbc) driver + - using TCP/IP protocol (with server DNS name as hostname... or localhost) and fixed port (leave `DB_PORT` here below empty for dynamic port) + - SQL Server (not Windows/AD) authentication (user name password managed in SQL Server admin) + Download and install the ODBC that correspond to your OS and MS-SQL Server version (https://docs.microsoft.com/en-us/sql/connect/odbc/) - Copy the example environment setup and adjust the variables: `cp .env.example .env`. Refer to .env.example for more info. - ``` - DB_HOST=mssql-host-server - DB_PORT=mssql-port - DB_NAME=database-name - DB_USER=database-user - DB_PASSWORD=database-password - ``` - Notes: + ``` + DB_HOST=mssql-host-server + DB_PORT=mssql-port + DB_NAME=database-name + DB_USER=database-user + DB_PASSWORD=database-password + ``` + Notes: - instead of `.env` file, you can use environment variables (e.g. provided as parameters in the docker-compose.yml) - default used django database 'engine' in openIMIS is - `sql_server.pyodbc`. If you need to use another one, use the `DB_ENGINE` entry in the `.env` file + `sql_server.pyodbc`. If you need to use another one, use the `DB_ENGINE` entry in the `.env` file - default 'options' in openIMIS are `{'driver': 'ODBC Driver 17 for SQL Server','unicode_results': True}` - If you need to provide other options, use the `DB_OPTIONS` entry in the `.env` file (be complete: the new json string will entirely replace the default one) + If you need to provide other options, use the `DB_OPTIONS` entry in the `.env` file (be complete: the new json string will entirely replace the default one) ## Developer tools ### To create backend module skeleton in single command - from `/openimis-be_py/openIMIS`: - - run this command: `python manage.py create_openimis_module [--template