From 1da664f6651324705196359739256004f9e33616 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Fri, 23 Oct 2026 01:15:54 -0600 Subject: [PATCH 1/5] feat(models): add a default-queryset hook for plugins Adds dojo.query_hooks: a registry of default-queryset filters keyed by model, applied by the HookedManager declared as `objects` on Product_Type, Product, Engagement, Test, Finding and the rows that hang off them. With nothing registered the querysets are unchanged. Each of those models also gets an explicit `unfiltered` manager, and two nullable columns (archived_at, archive_batch) that open source never reads or writes, with partial indexes built concurrently. Co-Authored-By: Claude Opus 5.5 --- dojo/db_migrations/0303_archive_columns.py | 483 ++++++++++++++++++ .../0304_archive_batch_indexes.py | 60 +++ dojo/endpoint/models.py | 18 + dojo/engagement/models.py | 20 +- dojo/finding/models.py | 29 +- dojo/jira/models.py | 21 + dojo/location/manager.py | 11 + dojo/location/models.py | 20 +- dojo/models.py | 25 + dojo/object/models.py | 10 + dojo/product/models.py | 20 +- dojo/product_type/models.py | 12 +- dojo/query_hooks.py | 53 ++ dojo/test/models.py | 28 + dojo/tool_product/models.py | 10 + dojo/vulnerability/models.py | 16 +- unittests/test_query_hooks.py | 47 ++ 17 files changed, 876 insertions(+), 7 deletions(-) create mode 100644 dojo/db_migrations/0303_archive_columns.py create mode 100644 dojo/db_migrations/0304_archive_batch_indexes.py create mode 100644 dojo/query_hooks.py create mode 100644 unittests/test_query_hooks.py diff --git a/dojo/db_migrations/0303_archive_columns.py b/dojo/db_migrations/0303_archive_columns.py new file mode 100644 index 00000000000..1d9301e2104 --- /dev/null +++ b/dojo/db_migrations/0303_archive_columns.py @@ -0,0 +1,483 @@ +# Generated by Django 5.2.17 on 2026-10-22 19:48 + +import pgtrigger.compiler +import pgtrigger.migrations +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("dojo", "0302_locationfindingreference_test_required"), + ] + + operations = [ + pgtrigger.migrations.RemoveTrigger( + model_name="endpoint", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="endpoint", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="endpoint", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="engagement", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="engagement", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="engagement", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding_group", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding_group", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding_group", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product_type", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product_type", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product_type", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="test", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="test", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="test", + name="delete_delete", + ), + migrations.AddField( + model_name="app_analysis", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="app_analysis", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="dojometa", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="dojometa", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint_status", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint_status", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpointevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpointevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement_presets", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement_presets", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagementevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagementevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_group", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_group", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_groupevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_groupevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingvulnerabilityreference", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingvulnerabilityreference", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_issue", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_issue", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_project", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_project", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="languages", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="languages", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationfindingreference", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationfindingreference", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationproductreference", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationproductreference", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="objects_product", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="objects_product", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_api_scan_configuration", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_api_scan_configuration", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_type", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_type", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_typeevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_typeevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="productevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="productevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import_finding_action", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import_finding_action", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="testevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="testevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="tool_product_settings", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="tool_product_settings", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="vulnerability_id", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="vulnerability_id", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + pgtrigger.migrations.AddTrigger( + model_name="endpoint", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash="4aa86c99a53e2afc8a2e7bbc9dce7e87cfe93c99", operation="INSERT", pgid="pgtrigger_insert_insert_c7973", table="dojo_endpoint", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="endpoint", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition="WHEN (OLD.* IS DISTINCT FROM NEW.*)", func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash="187a4d67775847794459c2d4249fe13e333b2118", operation="UPDATE", pgid="pgtrigger_update_update_2b19a", table="dojo_endpoint", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="endpoint", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (OLD."archive_batch", OLD."archived_at", OLD."fragment", OLD."host", OLD."id", OLD."path", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."port", OLD."product_id", OLD."protocol", OLD."query", OLD."userinfo"); RETURN NULL;', hash="c30fc33fac55999df702b7c9c249f64513bf7497", operation="DELETE", pgid="pgtrigger_delete_delete_dd1f9", table="dojo_endpoint", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="engagement", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash="5b48232cfe7dc67a91eebfd023a4ccb6eb920c39", operation="INSERT", pgid="pgtrigger_insert_insert_125f1", table="dojo_engagement", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="engagement", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."api_test" IS DISTINCT FROM (NEW."api_test") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."check_list" IS DISTINCT FROM (NEW."check_list") OR OLD."cicd_build_server_id" IS DISTINCT FROM (NEW."cicd_build_server_id") OR OLD."cicd_orchestration_engine_id" IS DISTINCT FROM (NEW."cicd_orchestration_engine_id") OR OLD."cicd_scm_server_id" IS DISTINCT FROM (NEW."cicd_scm_server_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."deduplication_on_engagement" IS DISTINCT FROM (NEW."deduplication_on_engagement") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."done_testing" IS DISTINCT FROM (NEW."done_testing") OR OLD."engagement_type" IS DISTINCT FROM (NEW."engagement_type") OR OLD."first_contacted" IS DISTINCT FROM (NEW."first_contacted") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."pen_test" IS DISTINCT FROM (NEW."pen_test") OR OLD."preset_id" IS DISTINCT FROM (NEW."preset_id") OR OLD."product_id" IS DISTINCT FROM (NEW."product_id") OR OLD."progress" IS DISTINCT FROM (NEW."progress") OR OLD."reason" IS DISTINCT FROM (NEW."reason") OR OLD."report_type_id" IS DISTINCT FROM (NEW."report_type_id") OR OLD."requester_id" IS DISTINCT FROM (NEW."requester_id") OR OLD."source_code_management_uri" IS DISTINCT FROM (NEW."source_code_management_uri") OR OLD."status" IS DISTINCT FROM (NEW."status") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_strategy" IS DISTINCT FROM (NEW."test_strategy") OR OLD."threat_model" IS DISTINCT FROM (NEW."threat_model") OR OLD."tmodel_path" IS DISTINCT FROM (NEW."tmodel_path") OR OLD."tracker" IS DISTINCT FROM (NEW."tracker") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash="8990b78ab9370e3cd1ec2b85dd89d52834d5aaf6", operation="UPDATE", pgid="pgtrigger_update_update_65136", table="dojo_engagement", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="engagement", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (OLD."active", OLD."api_test", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."check_list", OLD."cicd_build_server_id", OLD."cicd_orchestration_engine_id", OLD."cicd_scm_server_id", OLD."commit_hash", OLD."created", OLD."deduplication_on_engagement", OLD."description", OLD."done_testing", OLD."engagement_type", OLD."first_contacted", OLD."id", OLD."lead_id", OLD."name", OLD."pen_test", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."preset_id", OLD."product_id", OLD."progress", OLD."reason", OLD."report_type_id", OLD."requester_id", OLD."source_code_management_uri", OLD."status", OLD."target_end", OLD."target_start", OLD."test_strategy", OLD."threat_model", OLD."tmodel_path", OLD."tracker", OLD."updated", OLD."version"); RETURN NULL;', hash="0de881cdff9409808f24eb0258bdd61ae9ddc60e", operation="DELETE", pgid="pgtrigger_delete_delete_9f4df", table="dojo_engagement", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash="bfca827e3bf9d38085346f34984b62bfc9efa036", operation="INSERT", pgid="pgtrigger_insert_insert_2fbbb", table="dojo_finding", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."component_name" IS DISTINCT FROM (NEW."component_name") OR OLD."component_version" IS DISTINCT FROM (NEW."component_version") OR OLD."cve" IS DISTINCT FROM (NEW."cve") OR OLD."cvssv3" IS DISTINCT FROM (NEW."cvssv3") OR OLD."cvssv3_score" IS DISTINCT FROM (NEW."cvssv3_score") OR OLD."cvssv4" IS DISTINCT FROM (NEW."cvssv4") OR OLD."cvssv4_score" IS DISTINCT FROM (NEW."cvssv4_score") OR OLD."cwe" IS DISTINCT FROM (NEW."cwe") OR OLD."date" IS DISTINCT FROM (NEW."date") OR OLD."defect_review_requested_by_id" IS DISTINCT FROM (NEW."defect_review_requested_by_id") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."duplicate" IS DISTINCT FROM (NEW."duplicate") OR OLD."duplicate_finding_id" IS DISTINCT FROM (NEW."duplicate_finding_id") OR OLD."dynamic_finding" IS DISTINCT FROM (NEW."dynamic_finding") OR OLD."effort_for_fixing" IS DISTINCT FROM (NEW."effort_for_fixing") OR OLD."epss_percentile" IS DISTINCT FROM (NEW."epss_percentile") OR OLD."epss_score" IS DISTINCT FROM (NEW."epss_score") OR OLD."false_p" IS DISTINCT FROM (NEW."false_p") OR OLD."file_path" IS DISTINCT FROM (NEW."file_path") OR OLD."fix_available" IS DISTINCT FROM (NEW."fix_available") OR OLD."fix_version" IS DISTINCT FROM (NEW."fix_version") OR OLD."hash_code" IS DISTINCT FROM (NEW."hash_code") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."impact" IS DISTINCT FROM (NEW."impact") OR OLD."is_mitigated" IS DISTINCT FROM (NEW."is_mitigated") OR OLD."kev_date" IS DISTINCT FROM (NEW."kev_date") OR OLD."known_exploited" IS DISTINCT FROM (NEW."known_exploited") OR OLD."last_reviewed" IS DISTINCT FROM (NEW."last_reviewed") OR OLD."last_reviewed_by_id" IS DISTINCT FROM (NEW."last_reviewed_by_id") OR OLD."line" IS DISTINCT FROM (NEW."line") OR OLD."mitigated" IS DISTINCT FROM (NEW."mitigated") OR OLD."mitigated_by_id" IS DISTINCT FROM (NEW."mitigated_by_id") OR OLD."mitigation" IS DISTINCT FROM (NEW."mitigation") OR OLD."nb_occurences" IS DISTINCT FROM (NEW."nb_occurences") OR OLD."numerical_severity" IS DISTINCT FROM (NEW."numerical_severity") OR OLD."out_of_scope" IS DISTINCT FROM (NEW."out_of_scope") OR OLD."param" IS DISTINCT FROM (NEW."param") OR OLD."payload" IS DISTINCT FROM (NEW."payload") OR OLD."planned_remediation_date" IS DISTINCT FROM (NEW."planned_remediation_date") OR OLD."planned_remediation_version" IS DISTINCT FROM (NEW."planned_remediation_version") OR OLD."publish_date" IS DISTINCT FROM (NEW."publish_date") OR OLD."ransomware_used" IS DISTINCT FROM (NEW."ransomware_used") OR OLD."refs" IS DISTINCT FROM (NEW."refs") OR OLD."reporter_id" IS DISTINCT FROM (NEW."reporter_id") OR OLD."review_requested_by_id" IS DISTINCT FROM (NEW."review_requested_by_id") OR OLD."risk_accepted" IS DISTINCT FROM (NEW."risk_accepted") OR OLD."sast_sink_object" IS DISTINCT FROM (NEW."sast_sink_object") OR OLD."sast_source_file_path" IS DISTINCT FROM (NEW."sast_source_file_path") OR OLD."sast_source_line" IS DISTINCT FROM (NEW."sast_source_line") OR OLD."sast_source_object" IS DISTINCT FROM (NEW."sast_source_object") OR OLD."scanner_confidence" IS DISTINCT FROM (NEW."scanner_confidence") OR OLD."service" IS DISTINCT FROM (NEW."service") OR OLD."severity" IS DISTINCT FROM (NEW."severity") OR OLD."severity_justification" IS DISTINCT FROM (NEW."severity_justification") OR OLD."sla_expiration_date" IS DISTINCT FROM (NEW."sla_expiration_date") OR OLD."sla_start_date" IS DISTINCT FROM (NEW."sla_start_date") OR OLD."sonarqube_issue_id" IS DISTINCT FROM (NEW."sonarqube_issue_id") OR OLD."static_finding" IS DISTINCT FROM (NEW."static_finding") OR OLD."steps_to_reproduce" IS DISTINCT FROM (NEW."steps_to_reproduce") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id") OR OLD."thread_id" IS DISTINCT FROM (NEW."thread_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."under_defect_review" IS DISTINCT FROM (NEW."under_defect_review") OR OLD."under_review" IS DISTINCT FROM (NEW."under_review") OR OLD."unique_id_from_tool" IS DISTINCT FROM (NEW."unique_id_from_tool") OR OLD."url" IS DISTINCT FROM (NEW."url") OR OLD."verified" IS DISTINCT FROM (NEW."verified") OR OLD."vuln_id_from_tool" IS DISTINCT FROM (NEW."vuln_id_from_tool"))', func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash="7b1c5da1fc67ea4d10b0d6e9ec42fbf428ad6d47", operation="UPDATE", pgid="pgtrigger_update_update_92175", table="dojo_finding", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (OLD."active", OLD."archive_batch", OLD."archived_at", OLD."component_name", OLD."component_version", OLD."created", OLD."cve", OLD."cvssv3", OLD."cvssv3_score", OLD."cvssv4", OLD."cvssv4_score", OLD."cwe", OLD."date", OLD."defect_review_requested_by_id", OLD."description", OLD."duplicate", OLD."duplicate_finding_id", OLD."dynamic_finding", OLD."effort_for_fixing", OLD."epss_percentile", OLD."epss_score", OLD."false_p", OLD."file_path", OLD."fix_available", OLD."fix_version", OLD."hash_code", OLD."id", OLD."impact", OLD."is_mitigated", OLD."kev_date", OLD."known_exploited", OLD."last_reviewed", OLD."last_reviewed_by_id", OLD."last_status_update", OLD."line", OLD."mitigated", OLD."mitigated_by_id", OLD."mitigation", OLD."nb_occurences", OLD."numerical_severity", OLD."out_of_scope", OLD."param", OLD."payload", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."planned_remediation_date", OLD."planned_remediation_version", OLD."publish_date", OLD."ransomware_used", OLD."refs", OLD."reporter_id", OLD."review_requested_by_id", OLD."risk_accepted", OLD."sast_sink_object", OLD."sast_source_file_path", OLD."sast_source_line", OLD."sast_source_object", OLD."scanner_confidence", OLD."service", OLD."severity", OLD."severity_justification", OLD."sla_expiration_date", OLD."sla_start_date", OLD."sonarqube_issue_id", OLD."static_finding", OLD."steps_to_reproduce", OLD."test_id", OLD."thread_id", OLD."title", OLD."under_defect_review", OLD."under_review", OLD."unique_id_from_tool", OLD."updated", OLD."url", OLD."verified", OLD."vuln_id_from_tool"); RETURN NULL;', hash="0b0ae774839868caab7908236804d2b14393a699", operation="DELETE", pgid="pgtrigger_delete_delete_72933", table="dojo_finding", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding_group", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."test_id"); RETURN NULL;', hash="bcad4bd5b2d4c90eede0665d18169e85f5f14257", operation="INSERT", pgid="pgtrigger_insert_insert_94bd2", table="dojo_finding_group", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding_group", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."creator_id" IS DISTINCT FROM (NEW."creator_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id"))', func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."test_id"); RETURN NULL;', hash="bc709885f7ae1a3e00bb01e453bfd461ea3ac298", operation="UPDATE", pgid="pgtrigger_update_update_37b5f", table="dojo_finding_group", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding_group", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."creator_id", OLD."id", OLD."modified", OLD."name", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."test_id"); RETURN NULL;', hash="e573c51b932f142bef508cc995f8f4e6657c1d62", operation="DELETE", pgid="pgtrigger_delete_delete_24b41", table="dojo_finding_group", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL;', hash="b5851c1970f7b7c91e09d80dc365cbe2579c1220", operation="INSERT", pgid="pgtrigger_insert_insert_d5d32", table="dojo_product", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."async_updating" IS DISTINCT FROM (NEW."async_updating") OR OLD."business_criticality" IS DISTINCT FROM (NEW."business_criticality") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."disable_sla_breach_notifications" IS DISTINCT FROM (NEW."disable_sla_breach_notifications") OR OLD."enable_full_risk_acceptance" IS DISTINCT FROM (NEW."enable_full_risk_acceptance") OR OLD."enable_product_tag_inheritance" IS DISTINCT FROM (NEW."enable_product_tag_inheritance") OR OLD."enable_simple_risk_acceptance" IS DISTINCT FROM (NEW."enable_simple_risk_acceptance") OR OLD."external_audience" IS DISTINCT FROM (NEW."external_audience") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."internet_accessible" IS DISTINCT FROM (NEW."internet_accessible") OR OLD."lifecycle_id" IS DISTINCT FROM (NEW."lifecycle_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."origin_id" IS DISTINCT FROM (NEW."origin_id") OR OLD."platform_id" IS DISTINCT FROM (NEW."platform_id") OR OLD."prod_numeric_grade" IS DISTINCT FROM (NEW."prod_numeric_grade") OR OLD."prod_type_id" IS DISTINCT FROM (NEW."prod_type_id") OR OLD."product_manager_id" IS DISTINCT FROM (NEW."product_manager_id") OR OLD."revenue" IS DISTINCT FROM (NEW."revenue") OR OLD."sla_configuration_id" IS DISTINCT FROM (NEW."sla_configuration_id") OR OLD."team_manager_id" IS DISTINCT FROM (NEW."team_manager_id") OR OLD."technical_contact_id" IS DISTINCT FROM (NEW."technical_contact_id") OR OLD."tid" IS DISTINCT FROM (NEW."tid") OR OLD."user_records" IS DISTINCT FROM (NEW."user_records"))', func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL;', hash="b5793f361239e1329aea5ee48f4b68ba6d9c5f0f", operation="UPDATE", pgid="pgtrigger_update_update_e7040", table="dojo_product", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (OLD."archive_batch", OLD."archived_at", OLD."async_updating", OLD."business_criticality", OLD."created", OLD."description", OLD."disable_sla_breach_notifications", OLD."enable_full_risk_acceptance", OLD."enable_product_tag_inheritance", OLD."enable_simple_risk_acceptance", OLD."external_audience", OLD."id", OLD."internet_accessible", OLD."lifecycle_id", OLD."name", OLD."origin_id", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."platform_id", OLD."prod_numeric_grade", OLD."prod_type_id", OLD."product_manager_id", OLD."revenue", OLD."sla_configuration_id", OLD."team_manager_id", OLD."technical_contact_id", OLD."tid", OLD."updated", OLD."user_records"); RETURN NULL;', hash="b680a761758c22da5777b8b70f718169dfaf58b5", operation="DELETE", pgid="pgtrigger_delete_delete_064dd", table="dojo_product", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product_type", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."updated"); RETURN NULL;', hash="c22c7686452daedc2b9216ac67df591501e319f2", operation="INSERT", pgid="pgtrigger_insert_insert_2d109", table="dojo_product_type", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product_type", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."critical_product" IS DISTINCT FROM (NEW."critical_product") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."key_product" IS DISTINCT FROM (NEW."key_product") OR OLD."name" IS DISTINCT FROM (NEW."name"))', func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."updated"); RETURN NULL;', hash="f0b2de3b71e7b546d0efe2cb7950638c095d85fd", operation="UPDATE", pgid="pgtrigger_update_update_a0136", table="dojo_product_type", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product_type", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."critical_product", OLD."description", OLD."id", OLD."key_product", OLD."name", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."updated"); RETURN NULL;', hash="7d8aada72ff77dd0e91e25d2324c57b8d8500509", operation="DELETE", pgid="pgtrigger_delete_delete_66b18", table="dojo_product_type", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="test", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash="477f6a297658d54b13ef83b4f4b19b0e76f2bb27", operation="INSERT", pgid="pgtrigger_insert_insert_ecfc1", table="dojo_test", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="test", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."api_scan_configuration_id" IS DISTINCT FROM (NEW."api_scan_configuration_id") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."engagement_id" IS DISTINCT FROM (NEW."engagement_id") OR OLD."environment_id" IS DISTINCT FROM (NEW."environment_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."percent_complete" IS DISTINCT FROM (NEW."percent_complete") OR OLD."scan_type" IS DISTINCT FROM (NEW."scan_type") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_type_id" IS DISTINCT FROM (NEW."test_type_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash="50e41edef10c98f5e20b9c43a324c49f5b897f88", operation="UPDATE", pgid="pgtrigger_update_update_c40f8", table="dojo_test", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="test", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (OLD."api_scan_configuration_id", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."commit_hash", OLD."created", OLD."description", OLD."engagement_id", OLD."environment_id", OLD."id", OLD."lead_id", OLD."percent_complete", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."scan_type", OLD."target_end", OLD."target_start", OLD."test_type_id", OLD."title", OLD."updated", OLD."version"); RETURN NULL;', hash="0b9eda2793d6208cb855751dc6c39f8d6819cd2d", operation="DELETE", pgid="pgtrigger_delete_delete_66d18", table="dojo_test", when="AFTER")), + ), + ] diff --git a/dojo/db_migrations/0304_archive_batch_indexes.py b/dojo/db_migrations/0304_archive_batch_indexes.py new file mode 100644 index 00000000000..6bc9c071d70 --- /dev/null +++ b/dojo/db_migrations/0304_archive_batch_indexes.py @@ -0,0 +1,60 @@ +from django.contrib.postgres.operations import AddIndexConcurrently +from django.db import migrations, models + + +class Migration(migrations.Migration): + + # CREATE INDEX CONCURRENTLY cannot run inside a transaction, and a plain + # CREATE INDEX would lock dojo_finding and dojo_endpoint_status for the whole build. + atomic = False + + dependencies = [ + ("dojo", "0303_archive_columns"), + ] + + operations = [ + AddIndexConcurrently( + model_name="findingvulnerabilityreference", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_findvulnref_archive_batch"), + ), + AddIndexConcurrently( + model_name="endpoint_status", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_endpstatus_archive_batch"), + ), + AddIndexConcurrently( + model_name="engagement", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_engagement_archive_batch"), + ), + AddIndexConcurrently( + model_name="finding", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_finding_archive_batch"), + ), + AddIndexConcurrently( + model_name="jira_issue", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_jiraissue_archive_batch"), + ), + AddIndexConcurrently( + model_name="locationfindingreference", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_locfindref_archive_batch"), + ), + AddIndexConcurrently( + model_name="product", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_product_archive_batch"), + ), + AddIndexConcurrently( + model_name="product_type", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_prod_type_archive_batch"), + ), + AddIndexConcurrently( + model_name="test", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_test_archive_batch"), + ), + AddIndexConcurrently( + model_name="test_import_finding_action", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_tifa_archive_batch"), + ), + AddIndexConcurrently( + model_name="vulnerability_id", + index=models.Index(condition=models.Q(("archive_batch__isnull", False)), fields=["archive_batch"], name="dojo_vulnid_archive_batch"), + ), + ] diff --git a/dojo/endpoint/models.py b/dojo/endpoint/models.py index 628b28b9f2f..0963340ddfb 100644 --- a/dojo/endpoint/models.py +++ b/dojo/endpoint/models.py @@ -20,6 +20,7 @@ # before the re-export that loads this module — resolves despite partial circular load. # Must keep their dojo.models.* path for Django migration serialization. from dojo.models import copy_model_util, get_current_date, get_current_datetime +from dojo.query_hooks import HookedManager, UnfilteredManager logger = logging.getLogger(__name__) @@ -44,8 +45,17 @@ class Endpoint_Status(models.Model): endpoint = models.ForeignKey("dojo.Endpoint", null=False, blank=False, on_delete=models.CASCADE, related_name="status_endpoint") finding = models.ForeignKey("dojo.Finding", null=False, blank=False, on_delete=models.CASCADE, related_name="status_finding") + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_endpstatus_archive_batch"), models.Index(fields=["finding", "mitigated"]), models.Index(fields=["endpoint", "mitigated"]), # Optimize frequent lookups of "active" statuses (mitigated/flags all False) @@ -141,6 +151,14 @@ class Endpoint(models.Model): tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this endpoint. Choose from the list or add new tags. Press Enter key to add.")) inherited_tags = TagField(blank=True, force_lowercase=True, help_text=_("Internal use tags sepcifically for maintaining parity with product. This field will be present as a subset in the tags field")) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: ordering = ["product", "host", "protocol", "port", "userinfo", "path", "query", "fragment"] indexes = [ diff --git a/dojo/engagement/models.py b/dojo/engagement/models.py index 07492938afd..cd84840af3c 100644 --- a/dojo/engagement/models.py +++ b/dojo/engagement/models.py @@ -10,7 +10,8 @@ from django.utils.translation import gettext as _ from django_tagulous.models import TagField -from dojo.base_models.base import BaseModel +from dojo.base_models.base import BaseManager, BaseModel +from dojo.query_hooks import HookedBaseManager, HookedManager, UnfilteredManager logger = logging.getLogger(__name__) @@ -24,6 +25,14 @@ class Engagement_Presets(models.Model): product = models.ForeignKey("dojo.Product", on_delete=models.CASCADE) created = models.DateTimeField(auto_now_add=True, null=False) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: ordering = ["title"] @@ -94,9 +103,18 @@ class Engagement(BaseModel): tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this engagement. Choose from the list or add new tags. Press Enter key to add.")) inherited_tags = TagField(blank=True, force_lowercase=True, help_text=_("Internal use tags sepcifically for maintaining parity with product. This field will be present as a subset in the tags field")) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedBaseManager() + unfiltered = BaseManager() + class Meta: ordering = ["-target_start"] indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_engagement_archive_batch"), models.Index(fields=["product", "active"]), # Global search (pro/search/): weighted tsvector FTS + trigram fuzzy match. GinIndex( diff --git a/dojo/finding/models.py b/dojo/finding/models.py index caee92ae19d..976d5403fc5 100644 --- a/dojo/finding/models.py +++ b/dojo/finding/models.py @@ -24,7 +24,7 @@ from django_tagulous.models import TagField from titlecase import titlecase -from dojo.base_models.base import BaseModel +from dojo.base_models.base import BaseManager, BaseModel from dojo.finding.cwe import cwe_label, finding_cwe_labels from dojo.finding.vulnerability_id import resolve_vulnerability_id_type @@ -32,6 +32,7 @@ # re-export that loads this module — so this resolves despite the partial circular load, and # keeps their dojo.models.* path for Django migration serialization (used as field defaults). from dojo.models import copy_model_util, get_current_date, tomorrow +from dojo.query_hooks import HookedBaseManager, HookedManager, UnfilteredManager from dojo.validators import cvss3_validator, cvss4_validator if TYPE_CHECKING: @@ -454,9 +455,18 @@ class Finding(BaseModel): SEVERITIES = {"Info": 4, "Low": 3, "Medium": 2, "High": 1, "Critical": 0} + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedBaseManager() + unfiltered = BaseManager() + class Meta: ordering = ("numerical_severity", "-date", "title", "epss_score", "epss_percentile") indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_finding_archive_batch"), # Global search (pro/search/): weighted tsvector FTS + trigram fuzzy match. GinIndex( SearchVector("title", weight="A", config="english") @@ -1549,11 +1559,20 @@ class Vulnerability_Id(models.Model): # prefix. Denormalized/indexed so type-scoped queries (e.g. GROUP BY type) stay cheap. vulnerability_id_type = models.CharField(max_length=20, null=True, blank=True, editable=False, db_index=True) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: constraints = [ models.UniqueConstraint(fields=["finding", "vulnerability_id"], name="unique_finding_vulnerability_id"), ] indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_vulnid_archive_batch"), # Leading on vulnerability_id (the unique constraint's index leads on finding), for the # vulnerability-id Explorer's GROUP BY vulnerability_id / lookups by exact id. models.Index(fields=["vulnerability_id"], name="dojo_vuln_id_lookup_idx"), @@ -1622,6 +1641,14 @@ class Finding_Group(TimeStampedModel): findings = models.ManyToManyField("dojo.Finding") creator = models.ForeignKey("dojo.Dojo_User", on_delete=models.RESTRICT) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + def __str__(self): return self.name diff --git a/dojo/jira/models.py b/dojo/jira/models.py index 17b742f98b5..a2d7f998edb 100644 --- a/dojo/jira/models.py +++ b/dojo/jira/models.py @@ -5,6 +5,8 @@ from django.db import models from django.utils.translation import gettext as _ +from dojo.query_hooks import HookedManager, UnfilteredManager + class JIRA_Instance(models.Model): configuration_name = models.CharField(max_length=2000, help_text=_("Enter a name to give to this configuration"), default="") @@ -139,6 +141,14 @@ class JIRA_Project(models.Model): default=True, blank=True) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: app_label = "dojo" @@ -197,7 +207,18 @@ class JIRA_Issue(models.Model): verbose_name=_("Jira last update"), help_text=_("The date the linked Jira issue was last modified.")) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: + indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_jiraissue_archive_batch"), + ] app_label = "dojo" def __str__(self): diff --git a/dojo/location/manager.py b/dojo/location/manager.py index 56b8bd6b445..1cf940257f0 100644 --- a/dojo/location/manager.py +++ b/dojo/location/manager.py @@ -4,6 +4,7 @@ from dojo.base_models.base import BaseManager, BaseQuerySet from dojo.location.status import rollup_finding_location_status +from dojo.query_hooks import HookedManagerMixin class LocationQueryset(BaseQuerySet): @@ -72,3 +73,13 @@ class LocationFindingReferenceManager(BaseManager): """LocationFindingReference manager to manipulate all objects with.""" QUERY_SET_CLASS = LocationFindingReferenceQueryset + + +class HookedLocationProductReferenceManager(HookedManagerMixin, LocationProductReferenceManager): + + """LocationProductReference manager that applies the registered default-queryset filters.""" + + +class HookedLocationFindingReferenceManager(HookedManagerMixin, LocationFindingReferenceManager): + + """LocationFindingReference manager that applies the registered default-queryset filters.""" diff --git a/dojo/location/models.py b/dojo/location/models.py index 76303b093cc..59823ab242e 100644 --- a/dojo/location/models.py +++ b/dojo/location/models.py @@ -23,6 +23,7 @@ QuerySet, TextChoices, UniqueConstraint, + UUIDField, ) from django.utils.translation import gettext_lazy as _ from django_tagulous.models import TagField @@ -30,6 +31,8 @@ from dojo.base_models.base import BaseModel, BaseModelWithoutTimeMeta from dojo.base_models.validators import validate_not_empty from dojo.location.manager import ( + HookedLocationFindingReferenceManager, + HookedLocationProductReferenceManager, LocationFindingReferenceManager, LocationFindingReferenceQueryset, LocationManager, @@ -652,7 +655,13 @@ class LocationFindingReference(BaseModel, ReferenceDataMixin): help_text=_("The status of the the given Location"), ) - objects = LocationFindingReferenceManager().from_queryset(LocationFindingReferenceQueryset)() + # Read and written only by plugins; open source never sets them. + archived_at = DateTimeField(null=True, blank=True, editable=False) + archive_batch = UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedLocationFindingReferenceManager().from_queryset(LocationFindingReferenceQueryset)() + unfiltered = LocationFindingReferenceManager().from_queryset(LocationFindingReferenceQueryset)() class Meta: verbose_name = "Locations - FindingReference" @@ -664,6 +673,7 @@ class Meta: ), ] indexes = [ + Index(fields=["archive_batch"], condition=Q(archive_batch__isnull=False), name="dojo_locfindref_archive_batch"), Index(fields=["location"]), Index(fields=["finding"]), ] @@ -715,7 +725,13 @@ class LocationProductReference(BaseModel, ReferenceDataMixin): help_text=_("The status of the the given Location"), ) - objects = LocationProductReferenceManager().from_queryset(LocationProductReferenceQueryset)() + # Read and written only by plugins; open source never sets them. + archived_at = DateTimeField(null=True, blank=True, editable=False) + archive_batch = UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedLocationProductReferenceManager().from_queryset(LocationProductReferenceQueryset)() + unfiltered = LocationProductReferenceManager().from_queryset(LocationProductReferenceQueryset)() class Meta: verbose_name = "Locations - ProductReference" diff --git a/dojo/models.py b/dojo/models.py index dfaa968893e..1614b431086 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -158,6 +158,7 @@ def get_current_datetime(): Product_Line, # noqa: F401 -- re-export ) from dojo.product_type.models import Product_Type # noqa: E402, F401 -- re-export +from dojo.query_hooks import HookedManager, UnfilteredManager # noqa: E402 from dojo.reports.models import Report_Type # noqa: E402, F401 -- re-export from dojo.test.models import ( # noqa: E402 -- re-export; class-body FKs below reference these IMPORT_ACTIONS, # noqa: F401 -- re-export @@ -203,6 +204,14 @@ class DojoMeta(models.Model): editable=False, related_name="location_meta_scope") + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: unique_together = (("product", "name"), ("endpoint", "name"), @@ -530,6 +539,14 @@ class Languages(models.Model): code = models.IntegerField(blank=True, null=True, verbose_name=_("Number of code lines")) created = models.DateTimeField(auto_now_add=True, null=False) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: unique_together = [("language", "product")] @@ -550,6 +567,14 @@ class App_Analysis(models.Model): tags = TagField(blank=True, force_lowercase=True) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: indexes = [ # Global search (pro/search/): weighted tsvector FTS + trigram fuzzy match. diff --git a/dojo/object/models.py b/dojo/object/models.py index 30b086ba544..5f1fb2b3d60 100644 --- a/dojo/object/models.py +++ b/dojo/object/models.py @@ -2,6 +2,8 @@ from django.utils.translation import gettext as _ from django_tagulous.models import TagField +from dojo.query_hooks import HookedManager, UnfilteredManager + class Objects_Review(models.Model): name = models.CharField(max_length=100, null=True, blank=True) @@ -25,6 +27,14 @@ class Objects_Product(models.Model): tags = TagField(blank=True, force_lowercase=True, help_text=_("Add tags that help describe this object. Choose from the list or add new tags. Press Enter key to add.")) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + def __str__(self): name = None if self.path is not None: diff --git a/dojo/product/models.py b/dojo/product/models.py index 8fd475308eb..52d00ce79c1 100644 --- a/dojo/product/models.py +++ b/dojo/product/models.py @@ -11,7 +11,8 @@ from django.utils.translation import gettext as _ from django_tagulous.models import TagField -from dojo.base_models.base import BaseModel +from dojo.base_models.base import BaseManager, BaseModel +from dojo.query_hooks import HookedBaseManager, HookedManager, UnfilteredManager class Product_Line(models.Model): @@ -131,9 +132,18 @@ class Product(BaseModel): async_updating = models.BooleanField(default=False, help_text=_("Findings under this Product or SLA configuration are asynchronously being updated")) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedBaseManager() + unfiltered = BaseManager() + class Meta: ordering = ("name",) indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_product_archive_batch"), # Serves the case-insensitive product-name lookup # (WHERE UPPER(name) = UPPER(%s)) used when filtering findings by # product name; the plain unique btree on name can't (Sentry DJANGO-D2M). @@ -307,6 +317,14 @@ class Product_API_Scan_Configuration(models.Model): service_key_2 = models.CharField(max_length=200, null=True, blank=True) service_key_3 = models.CharField(max_length=200, null=True, blank=True) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + def __str__(self): name = self.tool_configuration.name if self.service_key_1 or self.service_key_2 or self.service_key_3: diff --git a/dojo/product_type/models.py b/dojo/product_type/models.py index e9394d7e45a..7cfa3450e61 100644 --- a/dojo/product_type/models.py +++ b/dojo/product_type/models.py @@ -4,7 +4,8 @@ from django.urls import reverse from django.utils.functional import cached_property -from dojo.base_models.base import BaseModel +from dojo.base_models.base import BaseManager, BaseModel +from dojo.query_hooks import HookedBaseManager class Product_Type(BaseModel): @@ -25,9 +26,18 @@ class Product_Type(BaseModel): key_product = models.BooleanField(default=False) authorized_users = models.ManyToManyField("dojo.Dojo_User", related_name="authorized_product_types", blank=True) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedBaseManager() + unfiltered = BaseManager() + class Meta: ordering = ("name",) indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_prod_type_archive_batch"), # Global search (pro/search/): weighted tsvector FTS + trigram fuzzy match. GinIndex( SearchVector("name", weight="A", config="english") diff --git a/dojo/query_hooks.py b/dojo/query_hooks.py new file mode 100644 index 00000000000..ca0d0e955f9 --- /dev/null +++ b/dojo/query_hooks.py @@ -0,0 +1,53 @@ +""" +Default-queryset hooks for plugins. + +A model whose ``objects`` manager is a ``HookedManager`` (or ``HookedBaseManager``) +applies every filter registered for its label, in registration order, to the +queryset it returns. With nothing registered the queryset is unchanged, so the +open source behaviour is exactly that of a plain manager. + +``objects`` is declared first on those models, so it is also ``_default_manager``: +the filters reach reverse relations, ``get()`` and uniqueness checks as well. Each +model also carries an ``unfiltered`` manager, the explicit way to bypass them. +``_base_manager`` stays a plain manager, so forward foreign key access and the +deletion collector are never filtered. +""" + +from django.db.models import Manager + +from dojo.base_models.base import BaseManager + +_DEFAULT_QUERYSET_FILTERS = {} + + +def register_default_queryset_filter(model_label, key, func): + # Keyed so a repeated ready() (tests, autoreload) replaces rather than stacks. + _DEFAULT_QUERYSET_FILTERS.setdefault(model_label.lower(), {})[key] = func + + +def get_default_queryset_filters(model_label): + return tuple(_DEFAULT_QUERYSET_FILTERS.get(model_label.lower(), {}).values()) + + +def apply_default_queryset_filters(model, queryset): + for func in get_default_queryset_filters(model._meta.label): + queryset = func(queryset) + return queryset + + +class HookedManagerMixin: + def get_queryset(self): + return apply_default_queryset_filters(self.model, super().get_queryset()) + + +class HookedManager(HookedManagerMixin, Manager): + pass + + +class HookedBaseManager(HookedManagerMixin, BaseManager): + pass + + +class UnfilteredManager(Manager): + + """A plain manager, declared as ``unfiltered`` beside a hooked ``objects``: the explicit bypass.""" diff --git a/dojo/test/models.py b/dojo/test/models.py index 841fc5cb3c8..7b05d66ce54 100644 --- a/dojo/test/models.py +++ b/dojo/test/models.py @@ -11,6 +11,8 @@ from django_extensions.db.models import TimeStampedModel from django_tagulous.models import TagField +from dojo.query_hooks import HookedManager, UnfilteredManager + logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") @@ -80,8 +82,17 @@ class Test(models.Model): null=True, blank=True, help_text=_("Tag or branch that was tested, a reimport may update this field."), verbose_name=_("Branch/Tag")) api_scan_configuration = models.ForeignKey("dojo.Product_API_Scan_Configuration", null=True, editable=True, blank=True, on_delete=models.CASCADE, verbose_name=_("API Scan Configuration")) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_test_archive_batch"), models.Index(fields=["engagement", "test_type"]), # Global search (pro/search/): weighted tsvector FTS + trigram fuzzy match. GinIndex( @@ -249,6 +260,14 @@ class Test_Import(TimeStampedModel): branch_tag = models.CharField(editable=True, max_length=150, null=True, blank=True, help_text=_("Tag or branch that was tested, a reimport may update this field."), verbose_name=_("Branch/Tag")) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + def get_queryset(self): logger.debug("prefetch test_import counts") super_query = super().get_queryset() @@ -285,8 +304,17 @@ class Test_Import_Finding_Action(TimeStampedModel): finding = models.ForeignKey("dojo.Finding", editable=False, null=False, blank=False, on_delete=models.CASCADE) action = models.CharField(max_length=100, null=True, blank=True, choices=IMPORT_ACTIONS) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: indexes = [ + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_tifa_archive_batch"), models.Index(fields=["finding", "action", "test_import"]), ] unique_together = (("test_import", "finding")) diff --git a/dojo/tool_product/models.py b/dojo/tool_product/models.py index 2f77ea89a6e..a68130581bc 100644 --- a/dojo/tool_product/models.py +++ b/dojo/tool_product/models.py @@ -2,6 +2,8 @@ from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ +from dojo.query_hooks import HookedManager, UnfilteredManager + class Tool_Product_Settings(models.Model): name = models.CharField(max_length=200, null=False) @@ -13,6 +15,14 @@ class Tool_Product_Settings(models.Model): tool_project_id = models.CharField(max_length=200, null=True, blank=True) notes = models.ManyToManyField("dojo.Notes", blank=True, editable=False) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: ordering = ["name"] diff --git a/dojo/vulnerability/models.py b/dojo/vulnerability/models.py index 6ae4cb9b935..d919b63af3a 100644 --- a/dojo/vulnerability/models.py +++ b/dojo/vulnerability/models.py @@ -4,6 +4,8 @@ from django.db import models from django.db.models.functions import Upper +from dojo.query_hooks import HookedManager, UnfilteredManager + class Vulnerability(models.Model): @@ -80,6 +82,14 @@ class FindingVulnerabilityReference(models.Model): ) created = models.DateTimeField(auto_now_add=True) + # Read and written only by plugins; open source never sets them. + archived_at = models.DateTimeField(null=True, blank=True, editable=False) + archive_batch = models.UUIDField(null=True, blank=True, editable=False) + + # objects is declared first, so it is the default manager; see dojo.query_hooks. + objects = HookedManager() + unfiltered = UnfilteredManager() + class Meta: ordering = ["order"] constraints = [ @@ -89,7 +99,11 @@ class Meta: # insert write path, which assigns 0..n-1 in one transaction (see manager.py). models.UniqueConstraint(fields=["finding", "order"], name="unique_finding_order"), ] - indexes = [models.Index(fields=["finding", "order"]), models.Index(fields=["vulnerability"])] + indexes = [ + models.Index(fields=["finding", "order"]), + models.Index(fields=["vulnerability"]), + models.Index(fields=["archive_batch"], condition=models.Q(archive_batch__isnull=False), name="dojo_findvulnref_archive_batch"), + ] def __str__(self): return self.vulnerability.vulnerability_id diff --git a/unittests/test_query_hooks.py b/unittests/test_query_hooks.py new file mode 100644 index 00000000000..a394f43b20b --- /dev/null +++ b/unittests/test_query_hooks.py @@ -0,0 +1,47 @@ +from dojo.models import Engagement, Finding, Product, Product_Type, Test +from dojo.query_hooks import _DEFAULT_QUERYSET_FILTERS, register_default_queryset_filter # noqa: PLC2701 +from unittests.dojo_test_case import DojoTestCase, versioned_fixtures + + +@versioned_fixtures +class TestDefaultQuerysetHooks(DojoTestCase): + fixtures = ["dojo_testdata.json"] + + def setUp(self): + self._saved = {label: dict(funcs) for label, funcs in _DEFAULT_QUERYSET_FILTERS.items()} + _DEFAULT_QUERYSET_FILTERS.clear() + + def tearDown(self): + _DEFAULT_QUERYSET_FILTERS.clear() + _DEFAULT_QUERYSET_FILTERS.update(self._saved) + + def test_nothing_registered_leaves_querysets_unchanged(self): + for model in (Product_Type, Product, Engagement, Test, Finding): + with self.subTest(model=model.__name__): + self.assertEqual(model.objects.count(), model.unfiltered.count()) + + def test_hooked_manager_is_the_default_manager(self): + for model in (Product_Type, Product, Engagement, Test, Finding): + with self.subTest(model=model.__name__): + self.assertIs(model._default_manager, model.objects) + self.assertIsNot(model._base_manager, model.objects) + + def test_registered_filter_applies_to_objects_get_and_reverse_relations(self): + finding = Finding.objects.filter(test__isnull=False).first() + register_default_queryset_filter("dojo.Finding", "hide-one", lambda qs: qs.exclude(pk=finding.pk)) + + with self.subTest("objects"): + self.assertFalse(Finding.objects.filter(pk=finding.pk).exists()) + with self.subTest("get"), self.assertRaises(Finding.DoesNotExist): + Finding.objects.get(pk=finding.pk) + with self.subTest("reverse relation"): + self.assertNotIn(finding.pk, finding.test.finding_set.values_list("pk", flat=True)) + with self.subTest("unfiltered bypasses"): + self.assertTrue(Finding.unfiltered.filter(pk=finding.pk).exists()) + with self.subTest("base manager bypasses"): + self.assertTrue(Finding._base_manager.filter(pk=finding.pk).exists()) + + def test_registering_the_same_key_replaces_the_filter(self): + register_default_queryset_filter("dojo.Product", "k", lambda qs: qs.none()) + register_default_queryset_filter("dojo.Product", "k", lambda qs: qs) + self.assertEqual(Product.objects.count(), Product.unfiltered.count()) From e2c2014bc1a51dabcaf158d3ceb1cf0f0c8f00ab Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 26 Oct 2026 09:14:41 -0600 Subject: [PATCH 2/5] chore(models): renumber the queryset-hook migrations after dev Co-Authored-By: Claude Opus 5.5 --- .../{0303_archive_columns.py => 0304_archive_columns.py} | 2 +- ...4_archive_batch_indexes.py => 0305_archive_batch_indexes.py} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename dojo/db_migrations/{0303_archive_columns.py => 0304_archive_columns.py} (99%) rename dojo/db_migrations/{0304_archive_batch_indexes.py => 0305_archive_batch_indexes.py} (98%) diff --git a/dojo/db_migrations/0303_archive_columns.py b/dojo/db_migrations/0304_archive_columns.py similarity index 99% rename from dojo/db_migrations/0303_archive_columns.py rename to dojo/db_migrations/0304_archive_columns.py index 1d9301e2104..3b52540bdef 100644 --- a/dojo/db_migrations/0303_archive_columns.py +++ b/dojo/db_migrations/0304_archive_columns.py @@ -8,7 +8,7 @@ class Migration(migrations.Migration): dependencies = [ - ("dojo", "0302_locationfindingreference_test_required"), + ("dojo", "0303_system_settings_install_id"), ] operations = [ diff --git a/dojo/db_migrations/0304_archive_batch_indexes.py b/dojo/db_migrations/0305_archive_batch_indexes.py similarity index 98% rename from dojo/db_migrations/0304_archive_batch_indexes.py rename to dojo/db_migrations/0305_archive_batch_indexes.py index 6bc9c071d70..16919c925a6 100644 --- a/dojo/db_migrations/0304_archive_batch_indexes.py +++ b/dojo/db_migrations/0305_archive_batch_indexes.py @@ -9,7 +9,7 @@ class Migration(migrations.Migration): atomic = False dependencies = [ - ("dojo", "0303_archive_columns"), + ("dojo", "0304_archive_columns"), ] operations = [ From 23f81cea31332905ee35a393899c0f3c0bc70203 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 26 Oct 2026 17:47:23 -0600 Subject: [PATCH 3/5] test: expect the archive columns on endpoint status rows test_endpoint_queries compares Endpoint_Status.values() against literal rows, which now include the two nullable columns. Co-Authored-By: Claude Opus 5.5 --- unittests/test_metrics_queries.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/unittests/test_metrics_queries.py b/unittests/test_metrics_queries.py index 94ec80f2035..81f4a15242f 100644 --- a/unittests/test_metrics_queries.py +++ b/unittests/test_metrics_queries.py @@ -337,12 +337,12 @@ def test_endpoint_queries(self, mock_now): self.assertCountEqual( endpoint_queries["all"].values(), [ - {"id": 1, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 2, "finding_id": 2}, - {"id": 3, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": True, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 5, "finding_id": 228}, - {"id": 4, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": True, "risk_accepted": False, "endpoint_id": 5, "finding_id": 229}, - {"id": 5, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": True, "endpoint_id": 5, "finding_id": 230}, - {"id": 7, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 7, "finding_id": 227}, - {"id": 8, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 8, "finding_id": 231}, + {"id": 1, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 2, "finding_id": 2, "archived_at": None, "archive_batch": None}, + {"id": 3, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": True, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 5, "finding_id": 228, "archived_at": None, "archive_batch": None}, + {"id": 4, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": True, "risk_accepted": False, "endpoint_id": 5, "finding_id": 229, "archived_at": None, "archive_batch": None}, + {"id": 5, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": True, "endpoint_id": 5, "finding_id": 230, "archived_at": None, "archive_batch": None}, + {"id": 7, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 7, "finding_id": 227, "archived_at": None, "archive_batch": None}, + {"id": 8, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": False, "endpoint_id": 8, "finding_id": 231, "archived_at": None, "archive_batch": None}, ], ) self.assertSequenceEqual( @@ -351,7 +351,7 @@ def test_endpoint_queries(self, mock_now): ) self.assertSequenceEqual( endpoint_queries["accepted"].values(), - [{"id": 5, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": True, "endpoint_id": 5, "finding_id": 230}], + [{"id": 5, "date": date(2020, 7, 1), "last_modified": datetime(2020, 7, 1, 17, 45, 39, 791907, tzinfo=zoneinfo.ZoneInfo("UTC")), "mitigated": False, "mitigated_time": None, "mitigated_by_id": None, "false_positive": False, "out_of_scope": False, "risk_accepted": True, "endpoint_id": 5, "finding_id": 230, "archived_at": None, "archive_batch": None}], ) self.assertSequenceEqual( list(endpoint_queries["accepted_count"].values()), From 4fadf2ae9c3842e485ae1ba3837588025a41d2ec Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Wed, 28 Oct 2026 16:22:37 -0600 Subject: [PATCH 4/5] perf(migrations): hold the archive-column locks only for the SQL itself Measured on 10 million findings, 0304 blocked every read of dojo_finding for about 40 seconds. Its SQL takes milliseconds, but Django rebuilds its model state after each of the migration's operations, and each table's ACCESS EXCLUSIVE lock is taken by its ALTER and held through all the rebuilding that follows until the migration commits. The operations are now applied to the migration state only, and the database work is the SQL they generate (from sqlmigrate), frozen and run as one batch at the end. The resulting schema is identical; the slowest concurrent read during the migration dropped to 0.4 s. Co-Authored-By: Claude Opus 5.5 --- dojo/db_migrations/0304_archive_columns.py | 3790 +++++++++++++++++--- 1 file changed, 3323 insertions(+), 467 deletions(-) diff --git a/dojo/db_migrations/0304_archive_columns.py b/dojo/db_migrations/0304_archive_columns.py index 3b52540bdef..c7f8d8eaef5 100644 --- a/dojo/db_migrations/0304_archive_columns.py +++ b/dojo/db_migrations/0304_archive_columns.py @@ -4,480 +4,3336 @@ import pgtrigger.migrations from django.db import migrations, models +# Generated with `manage.py sqlmigrate` from the operations below, then frozen. +FORWARD_SQL = r""" +-- +-- Remove trigger insert_insert from model endpoint +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_c7973 ON "dojo_endpoint"; +-- +-- Remove trigger update_update from model endpoint +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_2b19a ON "dojo_endpoint"; +-- +-- Remove trigger delete_delete from model endpoint +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_dd1f9 ON "dojo_endpoint"; +-- +-- Remove trigger insert_insert from model engagement +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_125f1 ON "dojo_engagement"; +-- +-- Remove trigger update_update from model engagement +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_65136 ON "dojo_engagement"; +-- +-- Remove trigger delete_delete from model engagement +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_9f4df ON "dojo_engagement"; +-- +-- Remove trigger insert_insert from model finding +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2fbbb ON "dojo_finding"; +-- +-- Remove trigger update_update from model finding +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_92175 ON "dojo_finding"; +-- +-- Remove trigger delete_delete from model finding +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_72933 ON "dojo_finding"; +-- +-- Remove trigger insert_insert from model finding_group +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_94bd2 ON "dojo_finding_group"; +-- +-- Remove trigger update_update from model finding_group +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_37b5f ON "dojo_finding_group"; +-- +-- Remove trigger delete_delete from model finding_group +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_24b41 ON "dojo_finding_group"; +-- +-- Remove trigger insert_insert from model product +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_d5d32 ON "dojo_product"; +-- +-- Remove trigger update_update from model product +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_e7040 ON "dojo_product"; +-- +-- Remove trigger delete_delete from model product +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_064dd ON "dojo_product"; +-- +-- Remove trigger insert_insert from model product_type +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2d109 ON "dojo_product_type"; +-- +-- Remove trigger update_update from model product_type +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_a0136 ON "dojo_product_type"; +-- +-- Remove trigger delete_delete from model product_type +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66b18 ON "dojo_product_type"; +-- +-- Remove trigger insert_insert from model test +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_ecfc1 ON "dojo_test"; +-- +-- Remove trigger update_update from model test +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_c40f8 ON "dojo_test"; +-- +-- Remove trigger delete_delete from model test +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66d18 ON "dojo_test"; +-- +-- Add field archive_batch to app_analysis +-- +ALTER TABLE "dojo_app_analysis" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to app_analysis +-- +ALTER TABLE "dojo_app_analysis" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to dojometa +-- +ALTER TABLE "dojo_dojometa" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to dojometa +-- +ALTER TABLE "dojo_dojometa" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to endpoint +-- +ALTER TABLE "dojo_endpoint" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to endpoint +-- +ALTER TABLE "dojo_endpoint" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to endpoint_status +-- +ALTER TABLE "dojo_endpoint_status" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to endpoint_status +-- +ALTER TABLE "dojo_endpoint_status" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to endpointevent +-- +ALTER TABLE "dojo_endpointevent" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to endpointevent +-- +ALTER TABLE "dojo_endpointevent" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to engagement +-- +ALTER TABLE "dojo_engagement" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to engagement +-- +ALTER TABLE "dojo_engagement" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to engagement_presets +-- +ALTER TABLE "dojo_engagement_presets" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to engagement_presets +-- +ALTER TABLE "dojo_engagement_presets" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to engagementevent +-- +ALTER TABLE "dojo_engagementevent" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to engagementevent +-- +ALTER TABLE "dojo_engagementevent" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to finding +-- +ALTER TABLE "dojo_finding" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to finding +-- +ALTER TABLE "dojo_finding" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to finding_group +-- +ALTER TABLE "dojo_finding_group" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to finding_group +-- +ALTER TABLE "dojo_finding_group" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to finding_groupevent +-- +ALTER TABLE "dojo_finding_groupevent" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to finding_groupevent +-- +ALTER TABLE "dojo_finding_groupevent" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to findingevent +-- +ALTER TABLE "dojo_findingevent" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to findingevent +-- +ALTER TABLE "dojo_findingevent" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to findingvulnerabilityreference +-- +ALTER TABLE "dojo_findingvulnerabilityreference" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to findingvulnerabilityreference +-- +ALTER TABLE "dojo_findingvulnerabilityreference" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to jira_issue +-- +ALTER TABLE "dojo_jira_issue" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to jira_issue +-- +ALTER TABLE "dojo_jira_issue" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to jira_project +-- +ALTER TABLE "dojo_jira_project" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to jira_project +-- +ALTER TABLE "dojo_jira_project" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to languages +-- +ALTER TABLE "dojo_languages" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to languages +-- +ALTER TABLE "dojo_languages" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to locationfindingreference +-- +ALTER TABLE "dojo_locationfindingreference" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to locationfindingreference +-- +ALTER TABLE "dojo_locationfindingreference" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to locationproductreference +-- +ALTER TABLE "dojo_locationproductreference" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to locationproductreference +-- +ALTER TABLE "dojo_locationproductreference" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to objects_product +-- +ALTER TABLE "dojo_objects_product" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to objects_product +-- +ALTER TABLE "dojo_objects_product" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to product +-- +ALTER TABLE "dojo_product" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to product +-- +ALTER TABLE "dojo_product" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to product_api_scan_configuration +-- +ALTER TABLE "dojo_product_api_scan_configuration" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to product_api_scan_configuration +-- +ALTER TABLE "dojo_product_api_scan_configuration" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to product_type +-- +ALTER TABLE "dojo_product_type" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to product_type +-- +ALTER TABLE "dojo_product_type" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to product_typeevent +-- +ALTER TABLE "dojo_product_typeevent" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to product_typeevent +-- +ALTER TABLE "dojo_product_typeevent" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to productevent +-- +ALTER TABLE "dojo_productevent" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to productevent +-- +ALTER TABLE "dojo_productevent" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to test +-- +ALTER TABLE "dojo_test" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to test +-- +ALTER TABLE "dojo_test" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to test_import +-- +ALTER TABLE "dojo_test_import" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to test_import +-- +ALTER TABLE "dojo_test_import" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to test_import_finding_action +-- +ALTER TABLE "dojo_test_import_finding_action" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to test_import_finding_action +-- +ALTER TABLE "dojo_test_import_finding_action" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to testevent +-- +ALTER TABLE "dojo_testevent" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to testevent +-- +ALTER TABLE "dojo_testevent" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to tool_product_settings +-- +ALTER TABLE "dojo_tool_product_settings" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to tool_product_settings +-- +ALTER TABLE "dojo_tool_product_settings" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Add field archive_batch to vulnerability_id +-- +ALTER TABLE "dojo_vulnerability_id" ADD COLUMN "archive_batch" uuid NULL; +-- +-- Add field archived_at to vulnerability_id +-- +ALTER TABLE "dojo_vulnerability_id" ADD COLUMN "archived_at" timestamp with time zone NULL; +-- +-- Create trigger insert_insert on model endpoint +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_c7973() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_c7973 ON "dojo_endpoint"; + CREATE TRIGGER pgtrigger_insert_insert_c7973 + AFTER INSERT ON "dojo_endpoint" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_c7973(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_c7973 ON "dojo_endpoint" IS '4aa86c99a53e2afc8a2e7bbc9dce7e87cfe93c99'; + +-- +-- Create trigger update_update on model endpoint +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_2b19a() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_2b19a ON "dojo_endpoint"; + CREATE TRIGGER pgtrigger_update_update_2b19a + AFTER UPDATE ON "dojo_endpoint" + + + FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) + EXECUTE PROCEDURE pgtrigger_update_update_2b19a(); + + COMMENT ON TRIGGER pgtrigger_update_update_2b19a ON "dojo_endpoint" IS '187a4d67775847794459c2d4249fe13e333b2118'; + +-- +-- Create trigger delete_delete on model endpoint +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_dd1f9() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (OLD."archive_batch", OLD."archived_at", OLD."fragment", OLD."host", OLD."id", OLD."path", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."port", OLD."product_id", OLD."protocol", OLD."query", OLD."userinfo"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_dd1f9 ON "dojo_endpoint"; + CREATE TRIGGER pgtrigger_delete_delete_dd1f9 + AFTER DELETE ON "dojo_endpoint" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_dd1f9(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_dd1f9 ON "dojo_endpoint" IS 'c30fc33fac55999df702b7c9c249f64513bf7497'; + +-- +-- Create trigger insert_insert on model engagement +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_125f1() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_125f1 ON "dojo_engagement"; + CREATE TRIGGER pgtrigger_insert_insert_125f1 + AFTER INSERT ON "dojo_engagement" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_125f1(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_125f1 ON "dojo_engagement" IS '5b48232cfe7dc67a91eebfd023a4ccb6eb920c39'; + +-- +-- Create trigger update_update on model engagement +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_65136() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_65136 ON "dojo_engagement"; + CREATE TRIGGER pgtrigger_update_update_65136 + AFTER UPDATE ON "dojo_engagement" + + + FOR EACH ROW WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."api_test" IS DISTINCT FROM (NEW."api_test") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."check_list" IS DISTINCT FROM (NEW."check_list") OR OLD."cicd_build_server_id" IS DISTINCT FROM (NEW."cicd_build_server_id") OR OLD."cicd_orchestration_engine_id" IS DISTINCT FROM (NEW."cicd_orchestration_engine_id") OR OLD."cicd_scm_server_id" IS DISTINCT FROM (NEW."cicd_scm_server_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."deduplication_on_engagement" IS DISTINCT FROM (NEW."deduplication_on_engagement") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."done_testing" IS DISTINCT FROM (NEW."done_testing") OR OLD."engagement_type" IS DISTINCT FROM (NEW."engagement_type") OR OLD."first_contacted" IS DISTINCT FROM (NEW."first_contacted") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."pen_test" IS DISTINCT FROM (NEW."pen_test") OR OLD."preset_id" IS DISTINCT FROM (NEW."preset_id") OR OLD."product_id" IS DISTINCT FROM (NEW."product_id") OR OLD."progress" IS DISTINCT FROM (NEW."progress") OR OLD."reason" IS DISTINCT FROM (NEW."reason") OR OLD."report_type_id" IS DISTINCT FROM (NEW."report_type_id") OR OLD."requester_id" IS DISTINCT FROM (NEW."requester_id") OR OLD."source_code_management_uri" IS DISTINCT FROM (NEW."source_code_management_uri") OR OLD."status" IS DISTINCT FROM (NEW."status") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_strategy" IS DISTINCT FROM (NEW."test_strategy") OR OLD."threat_model" IS DISTINCT FROM (NEW."threat_model") OR OLD."tmodel_path" IS DISTINCT FROM (NEW."tmodel_path") OR OLD."tracker" IS DISTINCT FROM (NEW."tracker") OR OLD."version" IS DISTINCT FROM (NEW."version")) + EXECUTE PROCEDURE pgtrigger_update_update_65136(); + + COMMENT ON TRIGGER pgtrigger_update_update_65136 ON "dojo_engagement" IS '8990b78ab9370e3cd1ec2b85dd89d52834d5aaf6'; + +-- +-- Create trigger delete_delete on model engagement +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_9f4df() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (OLD."active", OLD."api_test", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."check_list", OLD."cicd_build_server_id", OLD."cicd_orchestration_engine_id", OLD."cicd_scm_server_id", OLD."commit_hash", OLD."created", OLD."deduplication_on_engagement", OLD."description", OLD."done_testing", OLD."engagement_type", OLD."first_contacted", OLD."id", OLD."lead_id", OLD."name", OLD."pen_test", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."preset_id", OLD."product_id", OLD."progress", OLD."reason", OLD."report_type_id", OLD."requester_id", OLD."source_code_management_uri", OLD."status", OLD."target_end", OLD."target_start", OLD."test_strategy", OLD."threat_model", OLD."tmodel_path", OLD."tracker", OLD."updated", OLD."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_9f4df ON "dojo_engagement"; + CREATE TRIGGER pgtrigger_delete_delete_9f4df + AFTER DELETE ON "dojo_engagement" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_9f4df(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_9f4df ON "dojo_engagement" IS '0de881cdff9409808f24eb0258bdd61ae9ddc60e'; + +-- +-- Create trigger insert_insert on model finding +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_2fbbb() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2fbbb ON "dojo_finding"; + CREATE TRIGGER pgtrigger_insert_insert_2fbbb + AFTER INSERT ON "dojo_finding" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_2fbbb(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_2fbbb ON "dojo_finding" IS 'bfca827e3bf9d38085346f34984b62bfc9efa036'; + +-- +-- Create trigger update_update on model finding +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_92175() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_92175 ON "dojo_finding"; + CREATE TRIGGER pgtrigger_update_update_92175 + AFTER UPDATE ON "dojo_finding" + + + FOR EACH ROW WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."component_name" IS DISTINCT FROM (NEW."component_name") OR OLD."component_version" IS DISTINCT FROM (NEW."component_version") OR OLD."cve" IS DISTINCT FROM (NEW."cve") OR OLD."cvssv3" IS DISTINCT FROM (NEW."cvssv3") OR OLD."cvssv3_score" IS DISTINCT FROM (NEW."cvssv3_score") OR OLD."cvssv4" IS DISTINCT FROM (NEW."cvssv4") OR OLD."cvssv4_score" IS DISTINCT FROM (NEW."cvssv4_score") OR OLD."cwe" IS DISTINCT FROM (NEW."cwe") OR OLD."date" IS DISTINCT FROM (NEW."date") OR OLD."defect_review_requested_by_id" IS DISTINCT FROM (NEW."defect_review_requested_by_id") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."duplicate" IS DISTINCT FROM (NEW."duplicate") OR OLD."duplicate_finding_id" IS DISTINCT FROM (NEW."duplicate_finding_id") OR OLD."dynamic_finding" IS DISTINCT FROM (NEW."dynamic_finding") OR OLD."effort_for_fixing" IS DISTINCT FROM (NEW."effort_for_fixing") OR OLD."epss_percentile" IS DISTINCT FROM (NEW."epss_percentile") OR OLD."epss_score" IS DISTINCT FROM (NEW."epss_score") OR OLD."false_p" IS DISTINCT FROM (NEW."false_p") OR OLD."file_path" IS DISTINCT FROM (NEW."file_path") OR OLD."fix_available" IS DISTINCT FROM (NEW."fix_available") OR OLD."fix_version" IS DISTINCT FROM (NEW."fix_version") OR OLD."hash_code" IS DISTINCT FROM (NEW."hash_code") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."impact" IS DISTINCT FROM (NEW."impact") OR OLD."is_mitigated" IS DISTINCT FROM (NEW."is_mitigated") OR OLD."kev_date" IS DISTINCT FROM (NEW."kev_date") OR OLD."known_exploited" IS DISTINCT FROM (NEW."known_exploited") OR OLD."last_reviewed" IS DISTINCT FROM (NEW."last_reviewed") OR OLD."last_reviewed_by_id" IS DISTINCT FROM (NEW."last_reviewed_by_id") OR OLD."line" IS DISTINCT FROM (NEW."line") OR OLD."mitigated" IS DISTINCT FROM (NEW."mitigated") OR OLD."mitigated_by_id" IS DISTINCT FROM (NEW."mitigated_by_id") OR OLD."mitigation" IS DISTINCT FROM (NEW."mitigation") OR OLD."nb_occurences" IS DISTINCT FROM (NEW."nb_occurences") OR OLD."numerical_severity" IS DISTINCT FROM (NEW."numerical_severity") OR OLD."out_of_scope" IS DISTINCT FROM (NEW."out_of_scope") OR OLD."param" IS DISTINCT FROM (NEW."param") OR OLD."payload" IS DISTINCT FROM (NEW."payload") OR OLD."planned_remediation_date" IS DISTINCT FROM (NEW."planned_remediation_date") OR OLD."planned_remediation_version" IS DISTINCT FROM (NEW."planned_remediation_version") OR OLD."publish_date" IS DISTINCT FROM (NEW."publish_date") OR OLD."ransomware_used" IS DISTINCT FROM (NEW."ransomware_used") OR OLD."refs" IS DISTINCT FROM (NEW."refs") OR OLD."reporter_id" IS DISTINCT FROM (NEW."reporter_id") OR OLD."review_requested_by_id" IS DISTINCT FROM (NEW."review_requested_by_id") OR OLD."risk_accepted" IS DISTINCT FROM (NEW."risk_accepted") OR OLD."sast_sink_object" IS DISTINCT FROM (NEW."sast_sink_object") OR OLD."sast_source_file_path" IS DISTINCT FROM (NEW."sast_source_file_path") OR OLD."sast_source_line" IS DISTINCT FROM (NEW."sast_source_line") OR OLD."sast_source_object" IS DISTINCT FROM (NEW."sast_source_object") OR OLD."scanner_confidence" IS DISTINCT FROM (NEW."scanner_confidence") OR OLD."service" IS DISTINCT FROM (NEW."service") OR OLD."severity" IS DISTINCT FROM (NEW."severity") OR OLD."severity_justification" IS DISTINCT FROM (NEW."severity_justification") OR OLD."sla_expiration_date" IS DISTINCT FROM (NEW."sla_expiration_date") OR OLD."sla_start_date" IS DISTINCT FROM (NEW."sla_start_date") OR OLD."sonarqube_issue_id" IS DISTINCT FROM (NEW."sonarqube_issue_id") OR OLD."static_finding" IS DISTINCT FROM (NEW."static_finding") OR OLD."steps_to_reproduce" IS DISTINCT FROM (NEW."steps_to_reproduce") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id") OR OLD."thread_id" IS DISTINCT FROM (NEW."thread_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."under_defect_review" IS DISTINCT FROM (NEW."under_defect_review") OR OLD."under_review" IS DISTINCT FROM (NEW."under_review") OR OLD."unique_id_from_tool" IS DISTINCT FROM (NEW."unique_id_from_tool") OR OLD."url" IS DISTINCT FROM (NEW."url") OR OLD."verified" IS DISTINCT FROM (NEW."verified") OR OLD."vuln_id_from_tool" IS DISTINCT FROM (NEW."vuln_id_from_tool")) + EXECUTE PROCEDURE pgtrigger_update_update_92175(); + + COMMENT ON TRIGGER pgtrigger_update_update_92175 ON "dojo_finding" IS '7b1c5da1fc67ea4d10b0d6e9ec42fbf428ad6d47'; + +-- +-- Create trigger delete_delete on model finding +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_72933() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (OLD."active", OLD."archive_batch", OLD."archived_at", OLD."component_name", OLD."component_version", OLD."created", OLD."cve", OLD."cvssv3", OLD."cvssv3_score", OLD."cvssv4", OLD."cvssv4_score", OLD."cwe", OLD."date", OLD."defect_review_requested_by_id", OLD."description", OLD."duplicate", OLD."duplicate_finding_id", OLD."dynamic_finding", OLD."effort_for_fixing", OLD."epss_percentile", OLD."epss_score", OLD."false_p", OLD."file_path", OLD."fix_available", OLD."fix_version", OLD."hash_code", OLD."id", OLD."impact", OLD."is_mitigated", OLD."kev_date", OLD."known_exploited", OLD."last_reviewed", OLD."last_reviewed_by_id", OLD."last_status_update", OLD."line", OLD."mitigated", OLD."mitigated_by_id", OLD."mitigation", OLD."nb_occurences", OLD."numerical_severity", OLD."out_of_scope", OLD."param", OLD."payload", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."planned_remediation_date", OLD."planned_remediation_version", OLD."publish_date", OLD."ransomware_used", OLD."refs", OLD."reporter_id", OLD."review_requested_by_id", OLD."risk_accepted", OLD."sast_sink_object", OLD."sast_source_file_path", OLD."sast_source_line", OLD."sast_source_object", OLD."scanner_confidence", OLD."service", OLD."severity", OLD."severity_justification", OLD."sla_expiration_date", OLD."sla_start_date", OLD."sonarqube_issue_id", OLD."static_finding", OLD."steps_to_reproduce", OLD."test_id", OLD."thread_id", OLD."title", OLD."under_defect_review", OLD."under_review", OLD."unique_id_from_tool", OLD."updated", OLD."url", OLD."verified", OLD."vuln_id_from_tool"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_72933 ON "dojo_finding"; + CREATE TRIGGER pgtrigger_delete_delete_72933 + AFTER DELETE ON "dojo_finding" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_72933(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_72933 ON "dojo_finding" IS '0b0ae774839868caab7908236804d2b14393a699'; + +-- +-- Create trigger insert_insert on model finding_group +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_94bd2() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."test_id"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_94bd2 ON "dojo_finding_group"; + CREATE TRIGGER pgtrigger_insert_insert_94bd2 + AFTER INSERT ON "dojo_finding_group" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_94bd2(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_94bd2 ON "dojo_finding_group" IS 'bcad4bd5b2d4c90eede0665d18169e85f5f14257'; + +-- +-- Create trigger update_update on model finding_group +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_37b5f() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."test_id"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_37b5f ON "dojo_finding_group"; + CREATE TRIGGER pgtrigger_update_update_37b5f + AFTER UPDATE ON "dojo_finding_group" + + + FOR EACH ROW WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."creator_id" IS DISTINCT FROM (NEW."creator_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id")) + EXECUTE PROCEDURE pgtrigger_update_update_37b5f(); + + COMMENT ON TRIGGER pgtrigger_update_update_37b5f ON "dojo_finding_group" IS 'bc709885f7ae1a3e00bb01e453bfd461ea3ac298'; + +-- +-- Create trigger delete_delete on model finding_group +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_24b41() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."creator_id", OLD."id", OLD."modified", OLD."name", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."test_id"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_24b41 ON "dojo_finding_group"; + CREATE TRIGGER pgtrigger_delete_delete_24b41 + AFTER DELETE ON "dojo_finding_group" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_24b41(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_24b41 ON "dojo_finding_group" IS 'e573c51b932f142bef508cc995f8f4e6657c1d62'; + +-- +-- Create trigger insert_insert on model product +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_d5d32() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_d5d32 ON "dojo_product"; + CREATE TRIGGER pgtrigger_insert_insert_d5d32 + AFTER INSERT ON "dojo_product" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_d5d32(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_d5d32 ON "dojo_product" IS 'b5851c1970f7b7c91e09d80dc365cbe2579c1220'; + +-- +-- Create trigger update_update on model product +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_e7040() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_e7040 ON "dojo_product"; + CREATE TRIGGER pgtrigger_update_update_e7040 + AFTER UPDATE ON "dojo_product" + + + FOR EACH ROW WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."async_updating" IS DISTINCT FROM (NEW."async_updating") OR OLD."business_criticality" IS DISTINCT FROM (NEW."business_criticality") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."disable_sla_breach_notifications" IS DISTINCT FROM (NEW."disable_sla_breach_notifications") OR OLD."enable_full_risk_acceptance" IS DISTINCT FROM (NEW."enable_full_risk_acceptance") OR OLD."enable_product_tag_inheritance" IS DISTINCT FROM (NEW."enable_product_tag_inheritance") OR OLD."enable_simple_risk_acceptance" IS DISTINCT FROM (NEW."enable_simple_risk_acceptance") OR OLD."external_audience" IS DISTINCT FROM (NEW."external_audience") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."internet_accessible" IS DISTINCT FROM (NEW."internet_accessible") OR OLD."lifecycle_id" IS DISTINCT FROM (NEW."lifecycle_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."origin_id" IS DISTINCT FROM (NEW."origin_id") OR OLD."platform_id" IS DISTINCT FROM (NEW."platform_id") OR OLD."prod_numeric_grade" IS DISTINCT FROM (NEW."prod_numeric_grade") OR OLD."prod_type_id" IS DISTINCT FROM (NEW."prod_type_id") OR OLD."product_manager_id" IS DISTINCT FROM (NEW."product_manager_id") OR OLD."revenue" IS DISTINCT FROM (NEW."revenue") OR OLD."sla_configuration_id" IS DISTINCT FROM (NEW."sla_configuration_id") OR OLD."team_manager_id" IS DISTINCT FROM (NEW."team_manager_id") OR OLD."technical_contact_id" IS DISTINCT FROM (NEW."technical_contact_id") OR OLD."tid" IS DISTINCT FROM (NEW."tid") OR OLD."user_records" IS DISTINCT FROM (NEW."user_records")) + EXECUTE PROCEDURE pgtrigger_update_update_e7040(); + + COMMENT ON TRIGGER pgtrigger_update_update_e7040 ON "dojo_product" IS 'b5793f361239e1329aea5ee48f4b68ba6d9c5f0f'; + +-- +-- Create trigger delete_delete on model product +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_064dd() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (OLD."archive_batch", OLD."archived_at", OLD."async_updating", OLD."business_criticality", OLD."created", OLD."description", OLD."disable_sla_breach_notifications", OLD."enable_full_risk_acceptance", OLD."enable_product_tag_inheritance", OLD."enable_simple_risk_acceptance", OLD."external_audience", OLD."id", OLD."internet_accessible", OLD."lifecycle_id", OLD."name", OLD."origin_id", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."platform_id", OLD."prod_numeric_grade", OLD."prod_type_id", OLD."product_manager_id", OLD."revenue", OLD."sla_configuration_id", OLD."team_manager_id", OLD."technical_contact_id", OLD."tid", OLD."updated", OLD."user_records"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_064dd ON "dojo_product"; + CREATE TRIGGER pgtrigger_delete_delete_064dd + AFTER DELETE ON "dojo_product" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_064dd(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_064dd ON "dojo_product" IS 'b680a761758c22da5777b8b70f718169dfaf58b5'; + +-- +-- Create trigger insert_insert on model product_type +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_2d109() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."updated"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2d109 ON "dojo_product_type"; + CREATE TRIGGER pgtrigger_insert_insert_2d109 + AFTER INSERT ON "dojo_product_type" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_2d109(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_2d109 ON "dojo_product_type" IS 'c22c7686452daedc2b9216ac67df591501e319f2'; + +-- +-- Create trigger update_update on model product_type +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_a0136() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."updated"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_a0136 ON "dojo_product_type"; + CREATE TRIGGER pgtrigger_update_update_a0136 + AFTER UPDATE ON "dojo_product_type" + + + FOR EACH ROW WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."critical_product" IS DISTINCT FROM (NEW."critical_product") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."key_product" IS DISTINCT FROM (NEW."key_product") OR OLD."name" IS DISTINCT FROM (NEW."name")) + EXECUTE PROCEDURE pgtrigger_update_update_a0136(); + + COMMENT ON TRIGGER pgtrigger_update_update_a0136 ON "dojo_product_type" IS 'f0b2de3b71e7b546d0efe2cb7950638c095d85fd'; + +-- +-- Create trigger delete_delete on model product_type +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_66b18() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."critical_product", OLD."description", OLD."id", OLD."key_product", OLD."name", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."updated"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66b18 ON "dojo_product_type"; + CREATE TRIGGER pgtrigger_delete_delete_66b18 + AFTER DELETE ON "dojo_product_type" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_66b18(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_66b18 ON "dojo_product_type" IS '7d8aada72ff77dd0e91e25d2324c57b8d8500509'; + +-- +-- Create trigger insert_insert on model test +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_ecfc1() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_ecfc1 ON "dojo_test"; + CREATE TRIGGER pgtrigger_insert_insert_ecfc1 + AFTER INSERT ON "dojo_test" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_ecfc1(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_ecfc1 ON "dojo_test" IS '477f6a297658d54b13ef83b4f4b19b0e76f2bb27'; + +-- +-- Create trigger update_update on model test +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_c40f8() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_c40f8 ON "dojo_test"; + CREATE TRIGGER pgtrigger_update_update_c40f8 + AFTER UPDATE ON "dojo_test" + + + FOR EACH ROW WHEN (OLD."api_scan_configuration_id" IS DISTINCT FROM (NEW."api_scan_configuration_id") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."engagement_id" IS DISTINCT FROM (NEW."engagement_id") OR OLD."environment_id" IS DISTINCT FROM (NEW."environment_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."percent_complete" IS DISTINCT FROM (NEW."percent_complete") OR OLD."scan_type" IS DISTINCT FROM (NEW."scan_type") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_type_id" IS DISTINCT FROM (NEW."test_type_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."version" IS DISTINCT FROM (NEW."version")) + EXECUTE PROCEDURE pgtrigger_update_update_c40f8(); + + COMMENT ON TRIGGER pgtrigger_update_update_c40f8 ON "dojo_test" IS '50e41edef10c98f5e20b9c43a324c49f5b897f88'; + +-- +-- Create trigger delete_delete on model test +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_66d18() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (OLD."api_scan_configuration_id", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."commit_hash", OLD."created", OLD."description", OLD."engagement_id", OLD."environment_id", OLD."id", OLD."lead_id", OLD."percent_complete", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."scan_type", OLD."target_end", OLD."target_start", OLD."test_type_id", OLD."title", OLD."updated", OLD."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66d18 ON "dojo_test"; + CREATE TRIGGER pgtrigger_delete_delete_66d18 + AFTER DELETE ON "dojo_test" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_66d18(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_66d18 ON "dojo_test" IS '0b9eda2793d6208cb855751dc6c39f8d6819cd2d'; +""" + +BACKWARD_SQL = r""" +-- +-- Create trigger delete_delete on model test +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66d18 ON "dojo_test"; +-- +-- Create trigger update_update on model test +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_c40f8 ON "dojo_test"; +-- +-- Create trigger insert_insert on model test +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_ecfc1 ON "dojo_test"; +-- +-- Create trigger delete_delete on model product_type +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66b18 ON "dojo_product_type"; +-- +-- Create trigger update_update on model product_type +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_a0136 ON "dojo_product_type"; +-- +-- Create trigger insert_insert on model product_type +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2d109 ON "dojo_product_type"; +-- +-- Create trigger delete_delete on model product +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_064dd ON "dojo_product"; +-- +-- Create trigger update_update on model product +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_e7040 ON "dojo_product"; +-- +-- Create trigger insert_insert on model product +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_d5d32 ON "dojo_product"; +-- +-- Create trigger delete_delete on model finding_group +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_24b41 ON "dojo_finding_group"; +-- +-- Create trigger update_update on model finding_group +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_37b5f ON "dojo_finding_group"; +-- +-- Create trigger insert_insert on model finding_group +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_94bd2 ON "dojo_finding_group"; +-- +-- Create trigger delete_delete on model finding +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_72933 ON "dojo_finding"; +-- +-- Create trigger update_update on model finding +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_92175 ON "dojo_finding"; +-- +-- Create trigger insert_insert on model finding +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2fbbb ON "dojo_finding"; +-- +-- Create trigger delete_delete on model engagement +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_9f4df ON "dojo_engagement"; +-- +-- Create trigger update_update on model engagement +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_65136 ON "dojo_engagement"; +-- +-- Create trigger insert_insert on model engagement +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_125f1 ON "dojo_engagement"; +-- +-- Create trigger delete_delete on model endpoint +-- +DROP TRIGGER IF EXISTS pgtrigger_delete_delete_dd1f9 ON "dojo_endpoint"; +-- +-- Create trigger update_update on model endpoint +-- +DROP TRIGGER IF EXISTS pgtrigger_update_update_2b19a ON "dojo_endpoint"; +-- +-- Create trigger insert_insert on model endpoint +-- +DROP TRIGGER IF EXISTS pgtrigger_insert_insert_c7973 ON "dojo_endpoint"; +-- +-- Add field archived_at to vulnerability_id +-- +ALTER TABLE "dojo_vulnerability_id" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to vulnerability_id +-- +ALTER TABLE "dojo_vulnerability_id" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to tool_product_settings +-- +ALTER TABLE "dojo_tool_product_settings" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to tool_product_settings +-- +ALTER TABLE "dojo_tool_product_settings" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to testevent +-- +ALTER TABLE "dojo_testevent" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to testevent +-- +ALTER TABLE "dojo_testevent" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to test_import_finding_action +-- +ALTER TABLE "dojo_test_import_finding_action" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to test_import_finding_action +-- +ALTER TABLE "dojo_test_import_finding_action" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to test_import +-- +ALTER TABLE "dojo_test_import" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to test_import +-- +ALTER TABLE "dojo_test_import" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to test +-- +ALTER TABLE "dojo_test" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to test +-- +ALTER TABLE "dojo_test" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to productevent +-- +ALTER TABLE "dojo_productevent" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to productevent +-- +ALTER TABLE "dojo_productevent" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to product_typeevent +-- +ALTER TABLE "dojo_product_typeevent" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to product_typeevent +-- +ALTER TABLE "dojo_product_typeevent" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to product_type +-- +ALTER TABLE "dojo_product_type" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to product_type +-- +ALTER TABLE "dojo_product_type" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to product_api_scan_configuration +-- +ALTER TABLE "dojo_product_api_scan_configuration" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to product_api_scan_configuration +-- +ALTER TABLE "dojo_product_api_scan_configuration" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to product +-- +ALTER TABLE "dojo_product" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to product +-- +ALTER TABLE "dojo_product" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to objects_product +-- +ALTER TABLE "dojo_objects_product" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to objects_product +-- +ALTER TABLE "dojo_objects_product" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to locationproductreference +-- +ALTER TABLE "dojo_locationproductreference" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to locationproductreference +-- +ALTER TABLE "dojo_locationproductreference" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to locationfindingreference +-- +ALTER TABLE "dojo_locationfindingreference" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to locationfindingreference +-- +ALTER TABLE "dojo_locationfindingreference" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to languages +-- +ALTER TABLE "dojo_languages" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to languages +-- +ALTER TABLE "dojo_languages" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to jira_project +-- +ALTER TABLE "dojo_jira_project" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to jira_project +-- +ALTER TABLE "dojo_jira_project" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to jira_issue +-- +ALTER TABLE "dojo_jira_issue" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to jira_issue +-- +ALTER TABLE "dojo_jira_issue" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to findingvulnerabilityreference +-- +ALTER TABLE "dojo_findingvulnerabilityreference" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to findingvulnerabilityreference +-- +ALTER TABLE "dojo_findingvulnerabilityreference" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to findingevent +-- +ALTER TABLE "dojo_findingevent" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to findingevent +-- +ALTER TABLE "dojo_findingevent" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to finding_groupevent +-- +ALTER TABLE "dojo_finding_groupevent" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to finding_groupevent +-- +ALTER TABLE "dojo_finding_groupevent" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to finding_group +-- +ALTER TABLE "dojo_finding_group" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to finding_group +-- +ALTER TABLE "dojo_finding_group" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to finding +-- +ALTER TABLE "dojo_finding" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to finding +-- +ALTER TABLE "dojo_finding" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to engagementevent +-- +ALTER TABLE "dojo_engagementevent" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to engagementevent +-- +ALTER TABLE "dojo_engagementevent" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to engagement_presets +-- +ALTER TABLE "dojo_engagement_presets" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to engagement_presets +-- +ALTER TABLE "dojo_engagement_presets" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to engagement +-- +ALTER TABLE "dojo_engagement" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to engagement +-- +ALTER TABLE "dojo_engagement" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to endpointevent +-- +ALTER TABLE "dojo_endpointevent" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to endpointevent +-- +ALTER TABLE "dojo_endpointevent" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to endpoint_status +-- +ALTER TABLE "dojo_endpoint_status" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to endpoint_status +-- +ALTER TABLE "dojo_endpoint_status" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to endpoint +-- +ALTER TABLE "dojo_endpoint" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to endpoint +-- +ALTER TABLE "dojo_endpoint" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to dojometa +-- +ALTER TABLE "dojo_dojometa" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to dojometa +-- +ALTER TABLE "dojo_dojometa" DROP COLUMN "archive_batch" CASCADE; +-- +-- Add field archived_at to app_analysis +-- +ALTER TABLE "dojo_app_analysis" DROP COLUMN "archived_at" CASCADE; +-- +-- Add field archive_batch to app_analysis +-- +ALTER TABLE "dojo_app_analysis" DROP COLUMN "archive_batch" CASCADE; +-- +-- Remove trigger delete_delete from model test +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_66d18() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (OLD."api_scan_configuration_id", OLD."branch_tag", OLD."build_id", OLD."commit_hash", OLD."created", OLD."description", OLD."engagement_id", OLD."environment_id", OLD."id", OLD."lead_id", OLD."percent_complete", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."scan_type", OLD."target_end", OLD."target_start", OLD."test_type_id", OLD."title", OLD."updated", OLD."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66d18 ON "dojo_test"; + CREATE TRIGGER pgtrigger_delete_delete_66d18 + AFTER DELETE ON "dojo_test" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_66d18(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_66d18 ON "dojo_test" IS '51bce27193221308adc41e62f1faff5122bbbceb'; + +-- +-- Remove trigger update_update from model test +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_c40f8() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_c40f8 ON "dojo_test"; + CREATE TRIGGER pgtrigger_update_update_c40f8 + AFTER UPDATE ON "dojo_test" + + + FOR EACH ROW WHEN (OLD."api_scan_configuration_id" IS DISTINCT FROM (NEW."api_scan_configuration_id") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."engagement_id" IS DISTINCT FROM (NEW."engagement_id") OR OLD."environment_id" IS DISTINCT FROM (NEW."environment_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."percent_complete" IS DISTINCT FROM (NEW."percent_complete") OR OLD."scan_type" IS DISTINCT FROM (NEW."scan_type") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_type_id" IS DISTINCT FROM (NEW."test_type_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."version" IS DISTINCT FROM (NEW."version")) + EXECUTE PROCEDURE pgtrigger_update_update_c40f8(); + + COMMENT ON TRIGGER pgtrigger_update_update_c40f8 ON "dojo_test" IS '777c92a16d48f7e590e50cb8fb6c0d77c9afa1b6'; + +-- +-- Remove trigger insert_insert from model test +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_ecfc1() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_ecfc1 ON "dojo_test"; + CREATE TRIGGER pgtrigger_insert_insert_ecfc1 + AFTER INSERT ON "dojo_test" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_ecfc1(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_ecfc1 ON "dojo_test" IS '0b6ec21ca35b61b1abcc0b2f8629cb4d1cc92930'; + +-- +-- Remove trigger delete_delete from model product_type +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_66b18() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_product_typeevent" ("created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (OLD."created", OLD."critical_product", OLD."description", OLD."id", OLD."key_product", OLD."name", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."updated"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_66b18 ON "dojo_product_type"; + CREATE TRIGGER pgtrigger_delete_delete_66b18 + AFTER DELETE ON "dojo_product_type" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_66b18(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_66b18 ON "dojo_product_type" IS '1b3bb470de18c3270ba2a1d4453d276b34f650dc'; + +-- +-- Remove trigger update_update from model product_type +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_a0136() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_product_typeevent" ("created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."updated"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_a0136 ON "dojo_product_type"; + CREATE TRIGGER pgtrigger_update_update_a0136 + AFTER UPDATE ON "dojo_product_type" + + + FOR EACH ROW WHEN (OLD."critical_product" IS DISTINCT FROM (NEW."critical_product") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."key_product" IS DISTINCT FROM (NEW."key_product") OR OLD."name" IS DISTINCT FROM (NEW."name")) + EXECUTE PROCEDURE pgtrigger_update_update_a0136(); + + COMMENT ON TRIGGER pgtrigger_update_update_a0136 ON "dojo_product_type" IS '97c18814aec2e06d73b89e3eb65e0cfbf832dda5'; + +-- +-- Remove trigger insert_insert from model product_type +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_2d109() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_product_typeevent" ("created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."updated"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2d109 ON "dojo_product_type"; + CREATE TRIGGER pgtrigger_insert_insert_2d109 + AFTER INSERT ON "dojo_product_type" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_2d109(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_2d109 ON "dojo_product_type" IS '3f3d8e8a68a63bc86ff3557f8fc5f54d950e9d6d'; + +-- +-- Remove trigger delete_delete from model product +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_064dd() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_productevent" ("async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (OLD."async_updating", OLD."business_criticality", OLD."created", OLD."description", OLD."disable_sla_breach_notifications", OLD."enable_full_risk_acceptance", OLD."enable_product_tag_inheritance", OLD."enable_simple_risk_acceptance", OLD."external_audience", OLD."id", OLD."internet_accessible", OLD."lifecycle_id", OLD."name", OLD."origin_id", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."platform_id", OLD."prod_numeric_grade", OLD."prod_type_id", OLD."product_manager_id", OLD."revenue", OLD."sla_configuration_id", OLD."team_manager_id", OLD."technical_contact_id", OLD."tid", OLD."updated", OLD."user_records"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_064dd ON "dojo_product"; + CREATE TRIGGER pgtrigger_delete_delete_064dd + AFTER DELETE ON "dojo_product" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_064dd(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_064dd ON "dojo_product" IS 'fb5075dda22c29fcfbf16c799b636b5dbf993777'; + +-- +-- Remove trigger update_update from model product +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_e7040() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_productevent" ("async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_e7040 ON "dojo_product"; + CREATE TRIGGER pgtrigger_update_update_e7040 + AFTER UPDATE ON "dojo_product" + + + FOR EACH ROW WHEN (OLD."async_updating" IS DISTINCT FROM (NEW."async_updating") OR OLD."business_criticality" IS DISTINCT FROM (NEW."business_criticality") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."disable_sla_breach_notifications" IS DISTINCT FROM (NEW."disable_sla_breach_notifications") OR OLD."enable_full_risk_acceptance" IS DISTINCT FROM (NEW."enable_full_risk_acceptance") OR OLD."enable_product_tag_inheritance" IS DISTINCT FROM (NEW."enable_product_tag_inheritance") OR OLD."enable_simple_risk_acceptance" IS DISTINCT FROM (NEW."enable_simple_risk_acceptance") OR OLD."external_audience" IS DISTINCT FROM (NEW."external_audience") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."internet_accessible" IS DISTINCT FROM (NEW."internet_accessible") OR OLD."lifecycle_id" IS DISTINCT FROM (NEW."lifecycle_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."origin_id" IS DISTINCT FROM (NEW."origin_id") OR OLD."platform_id" IS DISTINCT FROM (NEW."platform_id") OR OLD."prod_numeric_grade" IS DISTINCT FROM (NEW."prod_numeric_grade") OR OLD."prod_type_id" IS DISTINCT FROM (NEW."prod_type_id") OR OLD."product_manager_id" IS DISTINCT FROM (NEW."product_manager_id") OR OLD."revenue" IS DISTINCT FROM (NEW."revenue") OR OLD."sla_configuration_id" IS DISTINCT FROM (NEW."sla_configuration_id") OR OLD."team_manager_id" IS DISTINCT FROM (NEW."team_manager_id") OR OLD."technical_contact_id" IS DISTINCT FROM (NEW."technical_contact_id") OR OLD."tid" IS DISTINCT FROM (NEW."tid") OR OLD."user_records" IS DISTINCT FROM (NEW."user_records")) + EXECUTE PROCEDURE pgtrigger_update_update_e7040(); + + COMMENT ON TRIGGER pgtrigger_update_update_e7040 ON "dojo_product" IS '49923bd314b57154a13024be447d70ff62dda123'; + +-- +-- Remove trigger insert_insert from model product +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_d5d32() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_productevent" ("async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_d5d32 ON "dojo_product"; + CREATE TRIGGER pgtrigger_insert_insert_d5d32 + AFTER INSERT ON "dojo_product" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_d5d32(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_d5d32 ON "dojo_product" IS '56d7d4e2ec7a3c855444408a7cd6be18e2e9ab02'; + +-- +-- Remove trigger delete_delete from model finding_group +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_24b41() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_finding_groupevent" ("created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (OLD."created", OLD."creator_id", OLD."id", OLD."modified", OLD."name", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."test_id"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_24b41 ON "dojo_finding_group"; + CREATE TRIGGER pgtrigger_delete_delete_24b41 + AFTER DELETE ON "dojo_finding_group" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_24b41(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_24b41 ON "dojo_finding_group" IS '4d7241855d22804d01d455fb4228e750c5b11497'; + +-- +-- Remove trigger update_update from model finding_group +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_37b5f() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_finding_groupevent" ("created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."test_id"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_37b5f ON "dojo_finding_group"; + CREATE TRIGGER pgtrigger_update_update_37b5f + AFTER UPDATE ON "dojo_finding_group" + + + FOR EACH ROW WHEN (OLD."creator_id" IS DISTINCT FROM (NEW."creator_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id")) + EXECUTE PROCEDURE pgtrigger_update_update_37b5f(); + + COMMENT ON TRIGGER pgtrigger_update_update_37b5f ON "dojo_finding_group" IS 'd5d94d19b54079f6c284d9448666eb408b20f245'; + +-- +-- Remove trigger insert_insert from model finding_group +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_94bd2() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_finding_groupevent" ("created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."test_id"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_94bd2 ON "dojo_finding_group"; + CREATE TRIGGER pgtrigger_insert_insert_94bd2 + AFTER INSERT ON "dojo_finding_group" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_94bd2(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_94bd2 ON "dojo_finding_group" IS 'ccce37d431a0be588c20aa39b570893c63be9b4b'; + +-- +-- Remove trigger delete_delete from model finding +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_72933() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_findingevent" ("active", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (OLD."active", OLD."component_name", OLD."component_version", OLD."created", OLD."cve", OLD."cvssv3", OLD."cvssv3_score", OLD."cvssv4", OLD."cvssv4_score", OLD."cwe", OLD."date", OLD."defect_review_requested_by_id", OLD."description", OLD."duplicate", OLD."duplicate_finding_id", OLD."dynamic_finding", OLD."effort_for_fixing", OLD."epss_percentile", OLD."epss_score", OLD."false_p", OLD."file_path", OLD."fix_available", OLD."fix_version", OLD."hash_code", OLD."id", OLD."impact", OLD."is_mitigated", OLD."kev_date", OLD."known_exploited", OLD."last_reviewed", OLD."last_reviewed_by_id", OLD."last_status_update", OLD."line", OLD."mitigated", OLD."mitigated_by_id", OLD."mitigation", OLD."nb_occurences", OLD."numerical_severity", OLD."out_of_scope", OLD."param", OLD."payload", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."planned_remediation_date", OLD."planned_remediation_version", OLD."publish_date", OLD."ransomware_used", OLD."refs", OLD."reporter_id", OLD."review_requested_by_id", OLD."risk_accepted", OLD."sast_sink_object", OLD."sast_source_file_path", OLD."sast_source_line", OLD."sast_source_object", OLD."scanner_confidence", OLD."service", OLD."severity", OLD."severity_justification", OLD."sla_expiration_date", OLD."sla_start_date", OLD."sonarqube_issue_id", OLD."static_finding", OLD."steps_to_reproduce", OLD."test_id", OLD."thread_id", OLD."title", OLD."under_defect_review", OLD."under_review", OLD."unique_id_from_tool", OLD."updated", OLD."url", OLD."verified", OLD."vuln_id_from_tool"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_72933 ON "dojo_finding"; + CREATE TRIGGER pgtrigger_delete_delete_72933 + AFTER DELETE ON "dojo_finding" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_72933(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_72933 ON "dojo_finding" IS 'dd1240d046d5292ab4e6ce9cd193d921c9c2d309'; + +-- +-- Remove trigger update_update from model finding +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_92175() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_findingevent" ("active", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_92175 ON "dojo_finding"; + CREATE TRIGGER pgtrigger_update_update_92175 + AFTER UPDATE ON "dojo_finding" + + + FOR EACH ROW WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."component_name" IS DISTINCT FROM (NEW."component_name") OR OLD."component_version" IS DISTINCT FROM (NEW."component_version") OR OLD."cve" IS DISTINCT FROM (NEW."cve") OR OLD."cvssv3" IS DISTINCT FROM (NEW."cvssv3") OR OLD."cvssv3_score" IS DISTINCT FROM (NEW."cvssv3_score") OR OLD."cvssv4" IS DISTINCT FROM (NEW."cvssv4") OR OLD."cvssv4_score" IS DISTINCT FROM (NEW."cvssv4_score") OR OLD."cwe" IS DISTINCT FROM (NEW."cwe") OR OLD."date" IS DISTINCT FROM (NEW."date") OR OLD."defect_review_requested_by_id" IS DISTINCT FROM (NEW."defect_review_requested_by_id") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."duplicate" IS DISTINCT FROM (NEW."duplicate") OR OLD."duplicate_finding_id" IS DISTINCT FROM (NEW."duplicate_finding_id") OR OLD."dynamic_finding" IS DISTINCT FROM (NEW."dynamic_finding") OR OLD."effort_for_fixing" IS DISTINCT FROM (NEW."effort_for_fixing") OR OLD."epss_percentile" IS DISTINCT FROM (NEW."epss_percentile") OR OLD."epss_score" IS DISTINCT FROM (NEW."epss_score") OR OLD."false_p" IS DISTINCT FROM (NEW."false_p") OR OLD."file_path" IS DISTINCT FROM (NEW."file_path") OR OLD."fix_available" IS DISTINCT FROM (NEW."fix_available") OR OLD."fix_version" IS DISTINCT FROM (NEW."fix_version") OR OLD."hash_code" IS DISTINCT FROM (NEW."hash_code") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."impact" IS DISTINCT FROM (NEW."impact") OR OLD."is_mitigated" IS DISTINCT FROM (NEW."is_mitigated") OR OLD."kev_date" IS DISTINCT FROM (NEW."kev_date") OR OLD."known_exploited" IS DISTINCT FROM (NEW."known_exploited") OR OLD."last_reviewed" IS DISTINCT FROM (NEW."last_reviewed") OR OLD."last_reviewed_by_id" IS DISTINCT FROM (NEW."last_reviewed_by_id") OR OLD."line" IS DISTINCT FROM (NEW."line") OR OLD."mitigated" IS DISTINCT FROM (NEW."mitigated") OR OLD."mitigated_by_id" IS DISTINCT FROM (NEW."mitigated_by_id") OR OLD."mitigation" IS DISTINCT FROM (NEW."mitigation") OR OLD."nb_occurences" IS DISTINCT FROM (NEW."nb_occurences") OR OLD."numerical_severity" IS DISTINCT FROM (NEW."numerical_severity") OR OLD."out_of_scope" IS DISTINCT FROM (NEW."out_of_scope") OR OLD."param" IS DISTINCT FROM (NEW."param") OR OLD."payload" IS DISTINCT FROM (NEW."payload") OR OLD."planned_remediation_date" IS DISTINCT FROM (NEW."planned_remediation_date") OR OLD."planned_remediation_version" IS DISTINCT FROM (NEW."planned_remediation_version") OR OLD."publish_date" IS DISTINCT FROM (NEW."publish_date") OR OLD."ransomware_used" IS DISTINCT FROM (NEW."ransomware_used") OR OLD."refs" IS DISTINCT FROM (NEW."refs") OR OLD."reporter_id" IS DISTINCT FROM (NEW."reporter_id") OR OLD."review_requested_by_id" IS DISTINCT FROM (NEW."review_requested_by_id") OR OLD."risk_accepted" IS DISTINCT FROM (NEW."risk_accepted") OR OLD."sast_sink_object" IS DISTINCT FROM (NEW."sast_sink_object") OR OLD."sast_source_file_path" IS DISTINCT FROM (NEW."sast_source_file_path") OR OLD."sast_source_line" IS DISTINCT FROM (NEW."sast_source_line") OR OLD."sast_source_object" IS DISTINCT FROM (NEW."sast_source_object") OR OLD."scanner_confidence" IS DISTINCT FROM (NEW."scanner_confidence") OR OLD."service" IS DISTINCT FROM (NEW."service") OR OLD."severity" IS DISTINCT FROM (NEW."severity") OR OLD."severity_justification" IS DISTINCT FROM (NEW."severity_justification") OR OLD."sla_expiration_date" IS DISTINCT FROM (NEW."sla_expiration_date") OR OLD."sla_start_date" IS DISTINCT FROM (NEW."sla_start_date") OR OLD."sonarqube_issue_id" IS DISTINCT FROM (NEW."sonarqube_issue_id") OR OLD."static_finding" IS DISTINCT FROM (NEW."static_finding") OR OLD."steps_to_reproduce" IS DISTINCT FROM (NEW."steps_to_reproduce") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id") OR OLD."thread_id" IS DISTINCT FROM (NEW."thread_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."under_defect_review" IS DISTINCT FROM (NEW."under_defect_review") OR OLD."under_review" IS DISTINCT FROM (NEW."under_review") OR OLD."unique_id_from_tool" IS DISTINCT FROM (NEW."unique_id_from_tool") OR OLD."url" IS DISTINCT FROM (NEW."url") OR OLD."verified" IS DISTINCT FROM (NEW."verified") OR OLD."vuln_id_from_tool" IS DISTINCT FROM (NEW."vuln_id_from_tool")) + EXECUTE PROCEDURE pgtrigger_update_update_92175(); + + COMMENT ON TRIGGER pgtrigger_update_update_92175 ON "dojo_finding" IS '3a8608f3269631a51e32dffe79021258c6c4af33'; + +-- +-- Remove trigger insert_insert from model finding +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_2fbbb() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_findingevent" ("active", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_2fbbb ON "dojo_finding"; + CREATE TRIGGER pgtrigger_insert_insert_2fbbb + AFTER INSERT ON "dojo_finding" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_2fbbb(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_2fbbb ON "dojo_finding" IS 'b8eea714d4e92bd779ff82939552ad55346d949f'; + +-- +-- Remove trigger delete_delete from model engagement +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_9f4df() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_engagementevent" ("active", "api_test", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (OLD."active", OLD."api_test", OLD."branch_tag", OLD."build_id", OLD."check_list", OLD."cicd_build_server_id", OLD."cicd_orchestration_engine_id", OLD."cicd_scm_server_id", OLD."commit_hash", OLD."created", OLD."deduplication_on_engagement", OLD."description", OLD."done_testing", OLD."engagement_type", OLD."first_contacted", OLD."id", OLD."lead_id", OLD."name", OLD."pen_test", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."preset_id", OLD."product_id", OLD."progress", OLD."reason", OLD."report_type_id", OLD."requester_id", OLD."source_code_management_uri", OLD."status", OLD."target_end", OLD."target_start", OLD."test_strategy", OLD."threat_model", OLD."tmodel_path", OLD."tracker", OLD."updated", OLD."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_9f4df ON "dojo_engagement"; + CREATE TRIGGER pgtrigger_delete_delete_9f4df + AFTER DELETE ON "dojo_engagement" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_9f4df(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_9f4df ON "dojo_engagement" IS 'de64abfdac94fadfbe7a8cd33212b1dc26ad9600'; + +-- +-- Remove trigger update_update from model engagement +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_65136() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_engagementevent" ("active", "api_test", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_65136 ON "dojo_engagement"; + CREATE TRIGGER pgtrigger_update_update_65136 + AFTER UPDATE ON "dojo_engagement" + + + FOR EACH ROW WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."api_test" IS DISTINCT FROM (NEW."api_test") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."check_list" IS DISTINCT FROM (NEW."check_list") OR OLD."cicd_build_server_id" IS DISTINCT FROM (NEW."cicd_build_server_id") OR OLD."cicd_orchestration_engine_id" IS DISTINCT FROM (NEW."cicd_orchestration_engine_id") OR OLD."cicd_scm_server_id" IS DISTINCT FROM (NEW."cicd_scm_server_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."deduplication_on_engagement" IS DISTINCT FROM (NEW."deduplication_on_engagement") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."done_testing" IS DISTINCT FROM (NEW."done_testing") OR OLD."engagement_type" IS DISTINCT FROM (NEW."engagement_type") OR OLD."first_contacted" IS DISTINCT FROM (NEW."first_contacted") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."pen_test" IS DISTINCT FROM (NEW."pen_test") OR OLD."preset_id" IS DISTINCT FROM (NEW."preset_id") OR OLD."product_id" IS DISTINCT FROM (NEW."product_id") OR OLD."progress" IS DISTINCT FROM (NEW."progress") OR OLD."reason" IS DISTINCT FROM (NEW."reason") OR OLD."report_type_id" IS DISTINCT FROM (NEW."report_type_id") OR OLD."requester_id" IS DISTINCT FROM (NEW."requester_id") OR OLD."source_code_management_uri" IS DISTINCT FROM (NEW."source_code_management_uri") OR OLD."status" IS DISTINCT FROM (NEW."status") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_strategy" IS DISTINCT FROM (NEW."test_strategy") OR OLD."threat_model" IS DISTINCT FROM (NEW."threat_model") OR OLD."tmodel_path" IS DISTINCT FROM (NEW."tmodel_path") OR OLD."tracker" IS DISTINCT FROM (NEW."tracker") OR OLD."version" IS DISTINCT FROM (NEW."version")) + EXECUTE PROCEDURE pgtrigger_update_update_65136(); + + COMMENT ON TRIGGER pgtrigger_update_update_65136 ON "dojo_engagement" IS '6a9569fa21d5d7ad16eb018bc4e6236e8401bced'; + +-- +-- Remove trigger insert_insert from model engagement +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_125f1() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_engagementevent" ("active", "api_test", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_125f1 ON "dojo_engagement"; + CREATE TRIGGER pgtrigger_insert_insert_125f1 + AFTER INSERT ON "dojo_engagement" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_125f1(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_125f1 ON "dojo_engagement" IS 'a217ec77b975020749afc350ee463c5867cfea27'; + +-- +-- Remove trigger delete_delete from model endpoint +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_delete_delete_dd1f9() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_endpointevent" ("fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (OLD."fragment", OLD."host", OLD."id", OLD."path", _pgh_attach_context(), NOW(), 'delete', OLD."id", OLD."port", OLD."product_id", OLD."protocol", OLD."query", OLD."userinfo"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_delete_delete_dd1f9 ON "dojo_endpoint"; + CREATE TRIGGER pgtrigger_delete_delete_dd1f9 + AFTER DELETE ON "dojo_endpoint" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_delete_delete_dd1f9(); + + COMMENT ON TRIGGER pgtrigger_delete_delete_dd1f9 ON "dojo_endpoint" IS '5e88416165d3e62cc6717b7d7f5d82933929de32'; + +-- +-- Remove trigger update_update from model endpoint +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_update_update_2b19a() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_endpointevent" ("fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), 'update', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_update_update_2b19a ON "dojo_endpoint"; + CREATE TRIGGER pgtrigger_update_update_2b19a + AFTER UPDATE ON "dojo_endpoint" + + + FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) + EXECUTE PROCEDURE pgtrigger_update_update_2b19a(); + + COMMENT ON TRIGGER pgtrigger_update_update_2b19a ON "dojo_endpoint" IS 'fce28bcbd64850a383950a720a72f134da7989d9'; + +-- +-- Remove trigger insert_insert from model endpoint +-- + + CREATE OR REPLACE FUNCTION "public"._pgtrigger_should_ignore( + trigger_name NAME + ) + RETURNS BOOLEAN AS $$ + DECLARE + _pgtrigger_ignore TEXT[]; + _result BOOLEAN; + BEGIN + BEGIN + SELECT INTO _pgtrigger_ignore + CURRENT_SETTING('pgtrigger.ignore'); + EXCEPTION WHEN OTHERS THEN + END; + IF _pgtrigger_ignore IS NOT NULL THEN + SELECT trigger_name = ANY(_pgtrigger_ignore) + INTO _result; + RETURN _result; + ELSE + RETURN FALSE; + END IF; + END; + $$ LANGUAGE plpgsql; + + CREATE OR REPLACE FUNCTION pgtrigger_insert_insert_c7973() + RETURNS TRIGGER AS $$ + + BEGIN + IF ("public"._pgtrigger_should_ignore(TG_NAME) IS TRUE) THEN + IF (TG_OP = 'DELETE') THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; + END IF; + INSERT INTO "dojo_endpointevent" ("fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), 'insert', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL; + END; + $$ LANGUAGE plpgsql; + + DROP TRIGGER IF EXISTS pgtrigger_insert_insert_c7973 ON "dojo_endpoint"; + CREATE TRIGGER pgtrigger_insert_insert_c7973 + AFTER INSERT ON "dojo_endpoint" + + + FOR EACH ROW + EXECUTE PROCEDURE pgtrigger_insert_insert_c7973(); + + COMMENT ON TRIGGER pgtrigger_insert_insert_c7973 ON "dojo_endpoint" IS '68e589c514e437831f4da3e802ca18e4cced175d'; +""" + class Migration(migrations.Migration): + """ + Archive columns on the hierarchy and its child rows, with their audit triggers. + + The operations are applied to the migration state only; the database work is the + frozen SQL they generate, run as one statement batch at the end. Django rebuilds its + model state after every operation, which takes most of a minute for these, and in a + plain migration each table's ACCESS EXCLUSIVE lock is taken by its ALTER and held + through all the rebuilding that follows. On 10 million findings that blocked every + read of dojo_finding for about 40 seconds. Done this way the locks are held only for + the SQL itself. + """ + dependencies = [ ("dojo", "0303_system_settings_install_id"), ] operations = [ - pgtrigger.migrations.RemoveTrigger( - model_name="endpoint", - name="insert_insert", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="endpoint", - name="update_update", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="endpoint", - name="delete_delete", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="engagement", - name="insert_insert", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="engagement", - name="update_update", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="engagement", - name="delete_delete", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="finding", - name="insert_insert", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="finding", - name="update_update", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="finding", - name="delete_delete", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="finding_group", - name="insert_insert", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="finding_group", - name="update_update", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="finding_group", - name="delete_delete", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="product", - name="insert_insert", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="product", - name="update_update", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="product", - name="delete_delete", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="product_type", - name="insert_insert", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="product_type", - name="update_update", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="product_type", - name="delete_delete", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="test", - name="insert_insert", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="test", - name="update_update", - ), - pgtrigger.migrations.RemoveTrigger( - model_name="test", - name="delete_delete", - ), - migrations.AddField( - model_name="app_analysis", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="app_analysis", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="dojometa", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="dojometa", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="endpoint", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="endpoint", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="endpoint_status", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="endpoint_status", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="endpointevent", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="endpointevent", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="engagement", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="engagement", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="engagement_presets", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="engagement_presets", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="engagementevent", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="engagementevent", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="finding", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="finding", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="finding_group", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="finding_group", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="finding_groupevent", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="finding_groupevent", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="findingevent", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="findingevent", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="findingvulnerabilityreference", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="findingvulnerabilityreference", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="jira_issue", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="jira_issue", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="jira_project", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="jira_project", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="languages", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="languages", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="locationfindingreference", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="locationfindingreference", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="locationproductreference", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="locationproductreference", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="objects_product", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="objects_product", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product_api_scan_configuration", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product_api_scan_configuration", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product_type", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product_type", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product_typeevent", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="product_typeevent", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="productevent", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="productevent", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="test", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="test", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="test_import", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="test_import", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="test_import_finding_action", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="test_import_finding_action", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="testevent", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="testevent", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="tool_product_settings", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="tool_product_settings", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="vulnerability_id", - name="archive_batch", - field=models.UUIDField(blank=True, editable=False, null=True), - ), - migrations.AddField( - model_name="vulnerability_id", - name="archived_at", - field=models.DateTimeField(blank=True, editable=False, null=True), - ), - pgtrigger.migrations.AddTrigger( - model_name="endpoint", - trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash="4aa86c99a53e2afc8a2e7bbc9dce7e87cfe93c99", operation="INSERT", pgid="pgtrigger_insert_insert_c7973", table="dojo_endpoint", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="endpoint", - trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition="WHEN (OLD.* IS DISTINCT FROM NEW.*)", func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash="187a4d67775847794459c2d4249fe13e333b2118", operation="UPDATE", pgid="pgtrigger_update_update_2b19a", table="dojo_endpoint", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="endpoint", - trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (OLD."archive_batch", OLD."archived_at", OLD."fragment", OLD."host", OLD."id", OLD."path", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."port", OLD."product_id", OLD."protocol", OLD."query", OLD."userinfo"); RETURN NULL;', hash="c30fc33fac55999df702b7c9c249f64513bf7497", operation="DELETE", pgid="pgtrigger_delete_delete_dd1f9", table="dojo_endpoint", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="engagement", - trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash="5b48232cfe7dc67a91eebfd023a4ccb6eb920c39", operation="INSERT", pgid="pgtrigger_insert_insert_125f1", table="dojo_engagement", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="engagement", - trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."api_test" IS DISTINCT FROM (NEW."api_test") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."check_list" IS DISTINCT FROM (NEW."check_list") OR OLD."cicd_build_server_id" IS DISTINCT FROM (NEW."cicd_build_server_id") OR OLD."cicd_orchestration_engine_id" IS DISTINCT FROM (NEW."cicd_orchestration_engine_id") OR OLD."cicd_scm_server_id" IS DISTINCT FROM (NEW."cicd_scm_server_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."deduplication_on_engagement" IS DISTINCT FROM (NEW."deduplication_on_engagement") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."done_testing" IS DISTINCT FROM (NEW."done_testing") OR OLD."engagement_type" IS DISTINCT FROM (NEW."engagement_type") OR OLD."first_contacted" IS DISTINCT FROM (NEW."first_contacted") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."pen_test" IS DISTINCT FROM (NEW."pen_test") OR OLD."preset_id" IS DISTINCT FROM (NEW."preset_id") OR OLD."product_id" IS DISTINCT FROM (NEW."product_id") OR OLD."progress" IS DISTINCT FROM (NEW."progress") OR OLD."reason" IS DISTINCT FROM (NEW."reason") OR OLD."report_type_id" IS DISTINCT FROM (NEW."report_type_id") OR OLD."requester_id" IS DISTINCT FROM (NEW."requester_id") OR OLD."source_code_management_uri" IS DISTINCT FROM (NEW."source_code_management_uri") OR OLD."status" IS DISTINCT FROM (NEW."status") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_strategy" IS DISTINCT FROM (NEW."test_strategy") OR OLD."threat_model" IS DISTINCT FROM (NEW."threat_model") OR OLD."tmodel_path" IS DISTINCT FROM (NEW."tmodel_path") OR OLD."tracker" IS DISTINCT FROM (NEW."tracker") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash="8990b78ab9370e3cd1ec2b85dd89d52834d5aaf6", operation="UPDATE", pgid="pgtrigger_update_update_65136", table="dojo_engagement", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="engagement", - trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (OLD."active", OLD."api_test", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."check_list", OLD."cicd_build_server_id", OLD."cicd_orchestration_engine_id", OLD."cicd_scm_server_id", OLD."commit_hash", OLD."created", OLD."deduplication_on_engagement", OLD."description", OLD."done_testing", OLD."engagement_type", OLD."first_contacted", OLD."id", OLD."lead_id", OLD."name", OLD."pen_test", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."preset_id", OLD."product_id", OLD."progress", OLD."reason", OLD."report_type_id", OLD."requester_id", OLD."source_code_management_uri", OLD."status", OLD."target_end", OLD."target_start", OLD."test_strategy", OLD."threat_model", OLD."tmodel_path", OLD."tracker", OLD."updated", OLD."version"); RETURN NULL;', hash="0de881cdff9409808f24eb0258bdd61ae9ddc60e", operation="DELETE", pgid="pgtrigger_delete_delete_9f4df", table="dojo_engagement", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="finding", - trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash="bfca827e3bf9d38085346f34984b62bfc9efa036", operation="INSERT", pgid="pgtrigger_insert_insert_2fbbb", table="dojo_finding", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="finding", - trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."component_name" IS DISTINCT FROM (NEW."component_name") OR OLD."component_version" IS DISTINCT FROM (NEW."component_version") OR OLD."cve" IS DISTINCT FROM (NEW."cve") OR OLD."cvssv3" IS DISTINCT FROM (NEW."cvssv3") OR OLD."cvssv3_score" IS DISTINCT FROM (NEW."cvssv3_score") OR OLD."cvssv4" IS DISTINCT FROM (NEW."cvssv4") OR OLD."cvssv4_score" IS DISTINCT FROM (NEW."cvssv4_score") OR OLD."cwe" IS DISTINCT FROM (NEW."cwe") OR OLD."date" IS DISTINCT FROM (NEW."date") OR OLD."defect_review_requested_by_id" IS DISTINCT FROM (NEW."defect_review_requested_by_id") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."duplicate" IS DISTINCT FROM (NEW."duplicate") OR OLD."duplicate_finding_id" IS DISTINCT FROM (NEW."duplicate_finding_id") OR OLD."dynamic_finding" IS DISTINCT FROM (NEW."dynamic_finding") OR OLD."effort_for_fixing" IS DISTINCT FROM (NEW."effort_for_fixing") OR OLD."epss_percentile" IS DISTINCT FROM (NEW."epss_percentile") OR OLD."epss_score" IS DISTINCT FROM (NEW."epss_score") OR OLD."false_p" IS DISTINCT FROM (NEW."false_p") OR OLD."file_path" IS DISTINCT FROM (NEW."file_path") OR OLD."fix_available" IS DISTINCT FROM (NEW."fix_available") OR OLD."fix_version" IS DISTINCT FROM (NEW."fix_version") OR OLD."hash_code" IS DISTINCT FROM (NEW."hash_code") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."impact" IS DISTINCT FROM (NEW."impact") OR OLD."is_mitigated" IS DISTINCT FROM (NEW."is_mitigated") OR OLD."kev_date" IS DISTINCT FROM (NEW."kev_date") OR OLD."known_exploited" IS DISTINCT FROM (NEW."known_exploited") OR OLD."last_reviewed" IS DISTINCT FROM (NEW."last_reviewed") OR OLD."last_reviewed_by_id" IS DISTINCT FROM (NEW."last_reviewed_by_id") OR OLD."line" IS DISTINCT FROM (NEW."line") OR OLD."mitigated" IS DISTINCT FROM (NEW."mitigated") OR OLD."mitigated_by_id" IS DISTINCT FROM (NEW."mitigated_by_id") OR OLD."mitigation" IS DISTINCT FROM (NEW."mitigation") OR OLD."nb_occurences" IS DISTINCT FROM (NEW."nb_occurences") OR OLD."numerical_severity" IS DISTINCT FROM (NEW."numerical_severity") OR OLD."out_of_scope" IS DISTINCT FROM (NEW."out_of_scope") OR OLD."param" IS DISTINCT FROM (NEW."param") OR OLD."payload" IS DISTINCT FROM (NEW."payload") OR OLD."planned_remediation_date" IS DISTINCT FROM (NEW."planned_remediation_date") OR OLD."planned_remediation_version" IS DISTINCT FROM (NEW."planned_remediation_version") OR OLD."publish_date" IS DISTINCT FROM (NEW."publish_date") OR OLD."ransomware_used" IS DISTINCT FROM (NEW."ransomware_used") OR OLD."refs" IS DISTINCT FROM (NEW."refs") OR OLD."reporter_id" IS DISTINCT FROM (NEW."reporter_id") OR OLD."review_requested_by_id" IS DISTINCT FROM (NEW."review_requested_by_id") OR OLD."risk_accepted" IS DISTINCT FROM (NEW."risk_accepted") OR OLD."sast_sink_object" IS DISTINCT FROM (NEW."sast_sink_object") OR OLD."sast_source_file_path" IS DISTINCT FROM (NEW."sast_source_file_path") OR OLD."sast_source_line" IS DISTINCT FROM (NEW."sast_source_line") OR OLD."sast_source_object" IS DISTINCT FROM (NEW."sast_source_object") OR OLD."scanner_confidence" IS DISTINCT FROM (NEW."scanner_confidence") OR OLD."service" IS DISTINCT FROM (NEW."service") OR OLD."severity" IS DISTINCT FROM (NEW."severity") OR OLD."severity_justification" IS DISTINCT FROM (NEW."severity_justification") OR OLD."sla_expiration_date" IS DISTINCT FROM (NEW."sla_expiration_date") OR OLD."sla_start_date" IS DISTINCT FROM (NEW."sla_start_date") OR OLD."sonarqube_issue_id" IS DISTINCT FROM (NEW."sonarqube_issue_id") OR OLD."static_finding" IS DISTINCT FROM (NEW."static_finding") OR OLD."steps_to_reproduce" IS DISTINCT FROM (NEW."steps_to_reproduce") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id") OR OLD."thread_id" IS DISTINCT FROM (NEW."thread_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."under_defect_review" IS DISTINCT FROM (NEW."under_defect_review") OR OLD."under_review" IS DISTINCT FROM (NEW."under_review") OR OLD."unique_id_from_tool" IS DISTINCT FROM (NEW."unique_id_from_tool") OR OLD."url" IS DISTINCT FROM (NEW."url") OR OLD."verified" IS DISTINCT FROM (NEW."verified") OR OLD."vuln_id_from_tool" IS DISTINCT FROM (NEW."vuln_id_from_tool"))', func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash="7b1c5da1fc67ea4d10b0d6e9ec42fbf428ad6d47", operation="UPDATE", pgid="pgtrigger_update_update_92175", table="dojo_finding", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="finding", - trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (OLD."active", OLD."archive_batch", OLD."archived_at", OLD."component_name", OLD."component_version", OLD."created", OLD."cve", OLD."cvssv3", OLD."cvssv3_score", OLD."cvssv4", OLD."cvssv4_score", OLD."cwe", OLD."date", OLD."defect_review_requested_by_id", OLD."description", OLD."duplicate", OLD."duplicate_finding_id", OLD."dynamic_finding", OLD."effort_for_fixing", OLD."epss_percentile", OLD."epss_score", OLD."false_p", OLD."file_path", OLD."fix_available", OLD."fix_version", OLD."hash_code", OLD."id", OLD."impact", OLD."is_mitigated", OLD."kev_date", OLD."known_exploited", OLD."last_reviewed", OLD."last_reviewed_by_id", OLD."last_status_update", OLD."line", OLD."mitigated", OLD."mitigated_by_id", OLD."mitigation", OLD."nb_occurences", OLD."numerical_severity", OLD."out_of_scope", OLD."param", OLD."payload", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."planned_remediation_date", OLD."planned_remediation_version", OLD."publish_date", OLD."ransomware_used", OLD."refs", OLD."reporter_id", OLD."review_requested_by_id", OLD."risk_accepted", OLD."sast_sink_object", OLD."sast_source_file_path", OLD."sast_source_line", OLD."sast_source_object", OLD."scanner_confidence", OLD."service", OLD."severity", OLD."severity_justification", OLD."sla_expiration_date", OLD."sla_start_date", OLD."sonarqube_issue_id", OLD."static_finding", OLD."steps_to_reproduce", OLD."test_id", OLD."thread_id", OLD."title", OLD."under_defect_review", OLD."under_review", OLD."unique_id_from_tool", OLD."updated", OLD."url", OLD."verified", OLD."vuln_id_from_tool"); RETURN NULL;', hash="0b0ae774839868caab7908236804d2b14393a699", operation="DELETE", pgid="pgtrigger_delete_delete_72933", table="dojo_finding", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="finding_group", - trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."test_id"); RETURN NULL;', hash="bcad4bd5b2d4c90eede0665d18169e85f5f14257", operation="INSERT", pgid="pgtrigger_insert_insert_94bd2", table="dojo_finding_group", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="finding_group", - trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."creator_id" IS DISTINCT FROM (NEW."creator_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id"))', func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."test_id"); RETURN NULL;', hash="bc709885f7ae1a3e00bb01e453bfd461ea3ac298", operation="UPDATE", pgid="pgtrigger_update_update_37b5f", table="dojo_finding_group", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="finding_group", - trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."creator_id", OLD."id", OLD."modified", OLD."name", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."test_id"); RETURN NULL;', hash="e573c51b932f142bef508cc995f8f4e6657c1d62", operation="DELETE", pgid="pgtrigger_delete_delete_24b41", table="dojo_finding_group", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="product", - trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL;', hash="b5851c1970f7b7c91e09d80dc365cbe2579c1220", operation="INSERT", pgid="pgtrigger_insert_insert_d5d32", table="dojo_product", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="product", - trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."async_updating" IS DISTINCT FROM (NEW."async_updating") OR OLD."business_criticality" IS DISTINCT FROM (NEW."business_criticality") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."disable_sla_breach_notifications" IS DISTINCT FROM (NEW."disable_sla_breach_notifications") OR OLD."enable_full_risk_acceptance" IS DISTINCT FROM (NEW."enable_full_risk_acceptance") OR OLD."enable_product_tag_inheritance" IS DISTINCT FROM (NEW."enable_product_tag_inheritance") OR OLD."enable_simple_risk_acceptance" IS DISTINCT FROM (NEW."enable_simple_risk_acceptance") OR OLD."external_audience" IS DISTINCT FROM (NEW."external_audience") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."internet_accessible" IS DISTINCT FROM (NEW."internet_accessible") OR OLD."lifecycle_id" IS DISTINCT FROM (NEW."lifecycle_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."origin_id" IS DISTINCT FROM (NEW."origin_id") OR OLD."platform_id" IS DISTINCT FROM (NEW."platform_id") OR OLD."prod_numeric_grade" IS DISTINCT FROM (NEW."prod_numeric_grade") OR OLD."prod_type_id" IS DISTINCT FROM (NEW."prod_type_id") OR OLD."product_manager_id" IS DISTINCT FROM (NEW."product_manager_id") OR OLD."revenue" IS DISTINCT FROM (NEW."revenue") OR OLD."sla_configuration_id" IS DISTINCT FROM (NEW."sla_configuration_id") OR OLD."team_manager_id" IS DISTINCT FROM (NEW."team_manager_id") OR OLD."technical_contact_id" IS DISTINCT FROM (NEW."technical_contact_id") OR OLD."tid" IS DISTINCT FROM (NEW."tid") OR OLD."user_records" IS DISTINCT FROM (NEW."user_records"))', func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL;', hash="b5793f361239e1329aea5ee48f4b68ba6d9c5f0f", operation="UPDATE", pgid="pgtrigger_update_update_e7040", table="dojo_product", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="product", - trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (OLD."archive_batch", OLD."archived_at", OLD."async_updating", OLD."business_criticality", OLD."created", OLD."description", OLD."disable_sla_breach_notifications", OLD."enable_full_risk_acceptance", OLD."enable_product_tag_inheritance", OLD."enable_simple_risk_acceptance", OLD."external_audience", OLD."id", OLD."internet_accessible", OLD."lifecycle_id", OLD."name", OLD."origin_id", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."platform_id", OLD."prod_numeric_grade", OLD."prod_type_id", OLD."product_manager_id", OLD."revenue", OLD."sla_configuration_id", OLD."team_manager_id", OLD."technical_contact_id", OLD."tid", OLD."updated", OLD."user_records"); RETURN NULL;', hash="b680a761758c22da5777b8b70f718169dfaf58b5", operation="DELETE", pgid="pgtrigger_delete_delete_064dd", table="dojo_product", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="product_type", - trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."updated"); RETURN NULL;', hash="c22c7686452daedc2b9216ac67df591501e319f2", operation="INSERT", pgid="pgtrigger_insert_insert_2d109", table="dojo_product_type", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="product_type", - trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."critical_product" IS DISTINCT FROM (NEW."critical_product") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."key_product" IS DISTINCT FROM (NEW."key_product") OR OLD."name" IS DISTINCT FROM (NEW."name"))', func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."updated"); RETURN NULL;', hash="f0b2de3b71e7b546d0efe2cb7950638c095d85fd", operation="UPDATE", pgid="pgtrigger_update_update_a0136", table="dojo_product_type", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="product_type", - trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."critical_product", OLD."description", OLD."id", OLD."key_product", OLD."name", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."updated"); RETURN NULL;', hash="7d8aada72ff77dd0e91e25d2324c57b8d8500509", operation="DELETE", pgid="pgtrigger_delete_delete_66b18", table="dojo_product_type", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="test", - trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash="477f6a297658d54b13ef83b4f4b19b0e76f2bb27", operation="INSERT", pgid="pgtrigger_insert_insert_ecfc1", table="dojo_test", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="test", - trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."api_scan_configuration_id" IS DISTINCT FROM (NEW."api_scan_configuration_id") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."engagement_id" IS DISTINCT FROM (NEW."engagement_id") OR OLD."environment_id" IS DISTINCT FROM (NEW."environment_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."percent_complete" IS DISTINCT FROM (NEW."percent_complete") OR OLD."scan_type" IS DISTINCT FROM (NEW."scan_type") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_type_id" IS DISTINCT FROM (NEW."test_type_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash="50e41edef10c98f5e20b9c43a324c49f5b897f88", operation="UPDATE", pgid="pgtrigger_update_update_c40f8", table="dojo_test", when="AFTER")), - ), - pgtrigger.migrations.AddTrigger( - model_name="test", - trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (OLD."api_scan_configuration_id", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."commit_hash", OLD."created", OLD."description", OLD."engagement_id", OLD."environment_id", OLD."id", OLD."lead_id", OLD."percent_complete", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."scan_type", OLD."target_end", OLD."target_start", OLD."test_type_id", OLD."title", OLD."updated", OLD."version"); RETURN NULL;', hash="0b9eda2793d6208cb855751dc6c39f8d6819cd2d", operation="DELETE", pgid="pgtrigger_delete_delete_66d18", table="dojo_test", when="AFTER")), + migrations.SeparateDatabaseAndState( + state_operations=[ + pgtrigger.migrations.RemoveTrigger( + model_name="endpoint", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="endpoint", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="endpoint", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="engagement", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="engagement", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="engagement", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding_group", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding_group", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="finding_group", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product_type", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product_type", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="product_type", + name="delete_delete", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="test", + name="insert_insert", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="test", + name="update_update", + ), + pgtrigger.migrations.RemoveTrigger( + model_name="test", + name="delete_delete", + ), + migrations.AddField( + model_name="app_analysis", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="app_analysis", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="dojometa", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="dojometa", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint_status", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpoint_status", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpointevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="endpointevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement_presets", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagement_presets", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagementevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="engagementevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_group", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_group", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_groupevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="finding_groupevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingvulnerabilityreference", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="findingvulnerabilityreference", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_issue", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_issue", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_project", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="jira_project", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="languages", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="languages", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationfindingreference", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationfindingreference", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationproductreference", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="locationproductreference", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="objects_product", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="objects_product", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_api_scan_configuration", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_api_scan_configuration", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_type", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_type", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_typeevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="product_typeevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="productevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="productevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import_finding_action", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="test_import_finding_action", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="testevent", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="testevent", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="tool_product_settings", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="tool_product_settings", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="vulnerability_id", + name="archive_batch", + field=models.UUIDField(blank=True, editable=False, null=True), + ), + migrations.AddField( + model_name="vulnerability_id", + name="archived_at", + field=models.DateTimeField(blank=True, editable=False, null=True), + ), + pgtrigger.migrations.AddTrigger( + model_name="endpoint", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash="4aa86c99a53e2afc8a2e7bbc9dce7e87cfe93c99", operation="INSERT", pgid="pgtrigger_insert_insert_c7973", table="dojo_endpoint", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="endpoint", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition="WHEN (OLD.* IS DISTINCT FROM NEW.*)", func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (NEW."archive_batch", NEW."archived_at", NEW."fragment", NEW."host", NEW."id", NEW."path", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."port", NEW."product_id", NEW."protocol", NEW."query", NEW."userinfo"); RETURN NULL;', hash="187a4d67775847794459c2d4249fe13e333b2118", operation="UPDATE", pgid="pgtrigger_update_update_2b19a", table="dojo_endpoint", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="endpoint", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_endpointevent" ("archive_batch", "archived_at", "fragment", "host", "id", "path", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "port", "product_id", "protocol", "query", "userinfo") VALUES (OLD."archive_batch", OLD."archived_at", OLD."fragment", OLD."host", OLD."id", OLD."path", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."port", OLD."product_id", OLD."protocol", OLD."query", OLD."userinfo"); RETURN NULL;', hash="c30fc33fac55999df702b7c9c249f64513bf7497", operation="DELETE", pgid="pgtrigger_delete_delete_dd1f9", table="dojo_endpoint", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="engagement", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash="5b48232cfe7dc67a91eebfd023a4ccb6eb920c39", operation="INSERT", pgid="pgtrigger_insert_insert_125f1", table="dojo_engagement", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="engagement", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."api_test" IS DISTINCT FROM (NEW."api_test") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."check_list" IS DISTINCT FROM (NEW."check_list") OR OLD."cicd_build_server_id" IS DISTINCT FROM (NEW."cicd_build_server_id") OR OLD."cicd_orchestration_engine_id" IS DISTINCT FROM (NEW."cicd_orchestration_engine_id") OR OLD."cicd_scm_server_id" IS DISTINCT FROM (NEW."cicd_scm_server_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."deduplication_on_engagement" IS DISTINCT FROM (NEW."deduplication_on_engagement") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."done_testing" IS DISTINCT FROM (NEW."done_testing") OR OLD."engagement_type" IS DISTINCT FROM (NEW."engagement_type") OR OLD."first_contacted" IS DISTINCT FROM (NEW."first_contacted") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."pen_test" IS DISTINCT FROM (NEW."pen_test") OR OLD."preset_id" IS DISTINCT FROM (NEW."preset_id") OR OLD."product_id" IS DISTINCT FROM (NEW."product_id") OR OLD."progress" IS DISTINCT FROM (NEW."progress") OR OLD."reason" IS DISTINCT FROM (NEW."reason") OR OLD."report_type_id" IS DISTINCT FROM (NEW."report_type_id") OR OLD."requester_id" IS DISTINCT FROM (NEW."requester_id") OR OLD."source_code_management_uri" IS DISTINCT FROM (NEW."source_code_management_uri") OR OLD."status" IS DISTINCT FROM (NEW."status") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_strategy" IS DISTINCT FROM (NEW."test_strategy") OR OLD."threat_model" IS DISTINCT FROM (NEW."threat_model") OR OLD."tmodel_path" IS DISTINCT FROM (NEW."tmodel_path") OR OLD."tracker" IS DISTINCT FROM (NEW."tracker") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (NEW."active", NEW."api_test", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."check_list", NEW."cicd_build_server_id", NEW."cicd_orchestration_engine_id", NEW."cicd_scm_server_id", NEW."commit_hash", NEW."created", NEW."deduplication_on_engagement", NEW."description", NEW."done_testing", NEW."engagement_type", NEW."first_contacted", NEW."id", NEW."lead_id", NEW."name", NEW."pen_test", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."preset_id", NEW."product_id", NEW."progress", NEW."reason", NEW."report_type_id", NEW."requester_id", NEW."source_code_management_uri", NEW."status", NEW."target_end", NEW."target_start", NEW."test_strategy", NEW."threat_model", NEW."tmodel_path", NEW."tracker", NEW."updated", NEW."version"); RETURN NULL;', hash="8990b78ab9370e3cd1ec2b85dd89d52834d5aaf6", operation="UPDATE", pgid="pgtrigger_update_update_65136", table="dojo_engagement", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="engagement", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_engagementevent" ("active", "api_test", "archive_batch", "archived_at", "branch_tag", "build_id", "check_list", "cicd_build_server_id", "cicd_orchestration_engine_id", "cicd_scm_server_id", "commit_hash", "created", "deduplication_on_engagement", "description", "done_testing", "engagement_type", "first_contacted", "id", "lead_id", "name", "pen_test", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "preset_id", "product_id", "progress", "reason", "report_type_id", "requester_id", "source_code_management_uri", "status", "target_end", "target_start", "test_strategy", "threat_model", "tmodel_path", "tracker", "updated", "version") VALUES (OLD."active", OLD."api_test", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."check_list", OLD."cicd_build_server_id", OLD."cicd_orchestration_engine_id", OLD."cicd_scm_server_id", OLD."commit_hash", OLD."created", OLD."deduplication_on_engagement", OLD."description", OLD."done_testing", OLD."engagement_type", OLD."first_contacted", OLD."id", OLD."lead_id", OLD."name", OLD."pen_test", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."preset_id", OLD."product_id", OLD."progress", OLD."reason", OLD."report_type_id", OLD."requester_id", OLD."source_code_management_uri", OLD."status", OLD."target_end", OLD."target_start", OLD."test_strategy", OLD."threat_model", OLD."tmodel_path", OLD."tracker", OLD."updated", OLD."version"); RETURN NULL;', hash="0de881cdff9409808f24eb0258bdd61ae9ddc60e", operation="DELETE", pgid="pgtrigger_delete_delete_9f4df", table="dojo_engagement", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash="bfca827e3bf9d38085346f34984b62bfc9efa036", operation="INSERT", pgid="pgtrigger_insert_insert_2fbbb", table="dojo_finding", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."active" IS DISTINCT FROM (NEW."active") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."component_name" IS DISTINCT FROM (NEW."component_name") OR OLD."component_version" IS DISTINCT FROM (NEW."component_version") OR OLD."cve" IS DISTINCT FROM (NEW."cve") OR OLD."cvssv3" IS DISTINCT FROM (NEW."cvssv3") OR OLD."cvssv3_score" IS DISTINCT FROM (NEW."cvssv3_score") OR OLD."cvssv4" IS DISTINCT FROM (NEW."cvssv4") OR OLD."cvssv4_score" IS DISTINCT FROM (NEW."cvssv4_score") OR OLD."cwe" IS DISTINCT FROM (NEW."cwe") OR OLD."date" IS DISTINCT FROM (NEW."date") OR OLD."defect_review_requested_by_id" IS DISTINCT FROM (NEW."defect_review_requested_by_id") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."duplicate" IS DISTINCT FROM (NEW."duplicate") OR OLD."duplicate_finding_id" IS DISTINCT FROM (NEW."duplicate_finding_id") OR OLD."dynamic_finding" IS DISTINCT FROM (NEW."dynamic_finding") OR OLD."effort_for_fixing" IS DISTINCT FROM (NEW."effort_for_fixing") OR OLD."epss_percentile" IS DISTINCT FROM (NEW."epss_percentile") OR OLD."epss_score" IS DISTINCT FROM (NEW."epss_score") OR OLD."false_p" IS DISTINCT FROM (NEW."false_p") OR OLD."file_path" IS DISTINCT FROM (NEW."file_path") OR OLD."fix_available" IS DISTINCT FROM (NEW."fix_available") OR OLD."fix_version" IS DISTINCT FROM (NEW."fix_version") OR OLD."hash_code" IS DISTINCT FROM (NEW."hash_code") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."impact" IS DISTINCT FROM (NEW."impact") OR OLD."is_mitigated" IS DISTINCT FROM (NEW."is_mitigated") OR OLD."kev_date" IS DISTINCT FROM (NEW."kev_date") OR OLD."known_exploited" IS DISTINCT FROM (NEW."known_exploited") OR OLD."last_reviewed" IS DISTINCT FROM (NEW."last_reviewed") OR OLD."last_reviewed_by_id" IS DISTINCT FROM (NEW."last_reviewed_by_id") OR OLD."line" IS DISTINCT FROM (NEW."line") OR OLD."mitigated" IS DISTINCT FROM (NEW."mitigated") OR OLD."mitigated_by_id" IS DISTINCT FROM (NEW."mitigated_by_id") OR OLD."mitigation" IS DISTINCT FROM (NEW."mitigation") OR OLD."nb_occurences" IS DISTINCT FROM (NEW."nb_occurences") OR OLD."numerical_severity" IS DISTINCT FROM (NEW."numerical_severity") OR OLD."out_of_scope" IS DISTINCT FROM (NEW."out_of_scope") OR OLD."param" IS DISTINCT FROM (NEW."param") OR OLD."payload" IS DISTINCT FROM (NEW."payload") OR OLD."planned_remediation_date" IS DISTINCT FROM (NEW."planned_remediation_date") OR OLD."planned_remediation_version" IS DISTINCT FROM (NEW."planned_remediation_version") OR OLD."publish_date" IS DISTINCT FROM (NEW."publish_date") OR OLD."ransomware_used" IS DISTINCT FROM (NEW."ransomware_used") OR OLD."refs" IS DISTINCT FROM (NEW."refs") OR OLD."reporter_id" IS DISTINCT FROM (NEW."reporter_id") OR OLD."review_requested_by_id" IS DISTINCT FROM (NEW."review_requested_by_id") OR OLD."risk_accepted" IS DISTINCT FROM (NEW."risk_accepted") OR OLD."sast_sink_object" IS DISTINCT FROM (NEW."sast_sink_object") OR OLD."sast_source_file_path" IS DISTINCT FROM (NEW."sast_source_file_path") OR OLD."sast_source_line" IS DISTINCT FROM (NEW."sast_source_line") OR OLD."sast_source_object" IS DISTINCT FROM (NEW."sast_source_object") OR OLD."scanner_confidence" IS DISTINCT FROM (NEW."scanner_confidence") OR OLD."service" IS DISTINCT FROM (NEW."service") OR OLD."severity" IS DISTINCT FROM (NEW."severity") OR OLD."severity_justification" IS DISTINCT FROM (NEW."severity_justification") OR OLD."sla_expiration_date" IS DISTINCT FROM (NEW."sla_expiration_date") OR OLD."sla_start_date" IS DISTINCT FROM (NEW."sla_start_date") OR OLD."sonarqube_issue_id" IS DISTINCT FROM (NEW."sonarqube_issue_id") OR OLD."static_finding" IS DISTINCT FROM (NEW."static_finding") OR OLD."steps_to_reproduce" IS DISTINCT FROM (NEW."steps_to_reproduce") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id") OR OLD."thread_id" IS DISTINCT FROM (NEW."thread_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."under_defect_review" IS DISTINCT FROM (NEW."under_defect_review") OR OLD."under_review" IS DISTINCT FROM (NEW."under_review") OR OLD."unique_id_from_tool" IS DISTINCT FROM (NEW."unique_id_from_tool") OR OLD."url" IS DISTINCT FROM (NEW."url") OR OLD."verified" IS DISTINCT FROM (NEW."verified") OR OLD."vuln_id_from_tool" IS DISTINCT FROM (NEW."vuln_id_from_tool"))', func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (NEW."active", NEW."archive_batch", NEW."archived_at", NEW."component_name", NEW."component_version", NEW."created", NEW."cve", NEW."cvssv3", NEW."cvssv3_score", NEW."cvssv4", NEW."cvssv4_score", NEW."cwe", NEW."date", NEW."defect_review_requested_by_id", NEW."description", NEW."duplicate", NEW."duplicate_finding_id", NEW."dynamic_finding", NEW."effort_for_fixing", NEW."epss_percentile", NEW."epss_score", NEW."false_p", NEW."file_path", NEW."fix_available", NEW."fix_version", NEW."hash_code", NEW."id", NEW."impact", NEW."is_mitigated", NEW."kev_date", NEW."known_exploited", NEW."last_reviewed", NEW."last_reviewed_by_id", NEW."last_status_update", NEW."line", NEW."mitigated", NEW."mitigated_by_id", NEW."mitigation", NEW."nb_occurences", NEW."numerical_severity", NEW."out_of_scope", NEW."param", NEW."payload", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."planned_remediation_date", NEW."planned_remediation_version", NEW."publish_date", NEW."ransomware_used", NEW."refs", NEW."reporter_id", NEW."review_requested_by_id", NEW."risk_accepted", NEW."sast_sink_object", NEW."sast_source_file_path", NEW."sast_source_line", NEW."sast_source_object", NEW."scanner_confidence", NEW."service", NEW."severity", NEW."severity_justification", NEW."sla_expiration_date", NEW."sla_start_date", NEW."sonarqube_issue_id", NEW."static_finding", NEW."steps_to_reproduce", NEW."test_id", NEW."thread_id", NEW."title", NEW."under_defect_review", NEW."under_review", NEW."unique_id_from_tool", NEW."updated", NEW."url", NEW."verified", NEW."vuln_id_from_tool"); RETURN NULL;', hash="7b1c5da1fc67ea4d10b0d6e9ec42fbf428ad6d47", operation="UPDATE", pgid="pgtrigger_update_update_92175", table="dojo_finding", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_findingevent" ("active", "archive_batch", "archived_at", "component_name", "component_version", "created", "cve", "cvssv3", "cvssv3_score", "cvssv4", "cvssv4_score", "cwe", "date", "defect_review_requested_by_id", "description", "duplicate", "duplicate_finding_id", "dynamic_finding", "effort_for_fixing", "epss_percentile", "epss_score", "false_p", "file_path", "fix_available", "fix_version", "hash_code", "id", "impact", "is_mitigated", "kev_date", "known_exploited", "last_reviewed", "last_reviewed_by_id", "last_status_update", "line", "mitigated", "mitigated_by_id", "mitigation", "nb_occurences", "numerical_severity", "out_of_scope", "param", "payload", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "planned_remediation_date", "planned_remediation_version", "publish_date", "ransomware_used", "refs", "reporter_id", "review_requested_by_id", "risk_accepted", "sast_sink_object", "sast_source_file_path", "sast_source_line", "sast_source_object", "scanner_confidence", "service", "severity", "severity_justification", "sla_expiration_date", "sla_start_date", "sonarqube_issue_id", "static_finding", "steps_to_reproduce", "test_id", "thread_id", "title", "under_defect_review", "under_review", "unique_id_from_tool", "updated", "url", "verified", "vuln_id_from_tool") VALUES (OLD."active", OLD."archive_batch", OLD."archived_at", OLD."component_name", OLD."component_version", OLD."created", OLD."cve", OLD."cvssv3", OLD."cvssv3_score", OLD."cvssv4", OLD."cvssv4_score", OLD."cwe", OLD."date", OLD."defect_review_requested_by_id", OLD."description", OLD."duplicate", OLD."duplicate_finding_id", OLD."dynamic_finding", OLD."effort_for_fixing", OLD."epss_percentile", OLD."epss_score", OLD."false_p", OLD."file_path", OLD."fix_available", OLD."fix_version", OLD."hash_code", OLD."id", OLD."impact", OLD."is_mitigated", OLD."kev_date", OLD."known_exploited", OLD."last_reviewed", OLD."last_reviewed_by_id", OLD."last_status_update", OLD."line", OLD."mitigated", OLD."mitigated_by_id", OLD."mitigation", OLD."nb_occurences", OLD."numerical_severity", OLD."out_of_scope", OLD."param", OLD."payload", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."planned_remediation_date", OLD."planned_remediation_version", OLD."publish_date", OLD."ransomware_used", OLD."refs", OLD."reporter_id", OLD."review_requested_by_id", OLD."risk_accepted", OLD."sast_sink_object", OLD."sast_source_file_path", OLD."sast_source_line", OLD."sast_source_object", OLD."scanner_confidence", OLD."service", OLD."severity", OLD."severity_justification", OLD."sla_expiration_date", OLD."sla_start_date", OLD."sonarqube_issue_id", OLD."static_finding", OLD."steps_to_reproduce", OLD."test_id", OLD."thread_id", OLD."title", OLD."under_defect_review", OLD."under_review", OLD."unique_id_from_tool", OLD."updated", OLD."url", OLD."verified", OLD."vuln_id_from_tool"); RETURN NULL;', hash="0b0ae774839868caab7908236804d2b14393a699", operation="DELETE", pgid="pgtrigger_delete_delete_72933", table="dojo_finding", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding_group", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."test_id"); RETURN NULL;', hash="bcad4bd5b2d4c90eede0665d18169e85f5f14257", operation="INSERT", pgid="pgtrigger_insert_insert_94bd2", table="dojo_finding_group", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding_group", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."creator_id" IS DISTINCT FROM (NEW."creator_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."test_id" IS DISTINCT FROM (NEW."test_id"))', func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."creator_id", NEW."id", NEW."modified", NEW."name", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."test_id"); RETURN NULL;', hash="bc709885f7ae1a3e00bb01e453bfd461ea3ac298", operation="UPDATE", pgid="pgtrigger_update_update_37b5f", table="dojo_finding_group", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="finding_group", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_finding_groupevent" ("archive_batch", "archived_at", "created", "creator_id", "id", "modified", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "test_id") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."creator_id", OLD."id", OLD."modified", OLD."name", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."test_id"); RETURN NULL;', hash="e573c51b932f142bef508cc995f8f4e6657c1d62", operation="DELETE", pgid="pgtrigger_delete_delete_24b41", table="dojo_finding_group", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL;', hash="b5851c1970f7b7c91e09d80dc365cbe2579c1220", operation="INSERT", pgid="pgtrigger_insert_insert_d5d32", table="dojo_product", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."async_updating" IS DISTINCT FROM (NEW."async_updating") OR OLD."business_criticality" IS DISTINCT FROM (NEW."business_criticality") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."disable_sla_breach_notifications" IS DISTINCT FROM (NEW."disable_sla_breach_notifications") OR OLD."enable_full_risk_acceptance" IS DISTINCT FROM (NEW."enable_full_risk_acceptance") OR OLD."enable_product_tag_inheritance" IS DISTINCT FROM (NEW."enable_product_tag_inheritance") OR OLD."enable_simple_risk_acceptance" IS DISTINCT FROM (NEW."enable_simple_risk_acceptance") OR OLD."external_audience" IS DISTINCT FROM (NEW."external_audience") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."internet_accessible" IS DISTINCT FROM (NEW."internet_accessible") OR OLD."lifecycle_id" IS DISTINCT FROM (NEW."lifecycle_id") OR OLD."name" IS DISTINCT FROM (NEW."name") OR OLD."origin_id" IS DISTINCT FROM (NEW."origin_id") OR OLD."platform_id" IS DISTINCT FROM (NEW."platform_id") OR OLD."prod_numeric_grade" IS DISTINCT FROM (NEW."prod_numeric_grade") OR OLD."prod_type_id" IS DISTINCT FROM (NEW."prod_type_id") OR OLD."product_manager_id" IS DISTINCT FROM (NEW."product_manager_id") OR OLD."revenue" IS DISTINCT FROM (NEW."revenue") OR OLD."sla_configuration_id" IS DISTINCT FROM (NEW."sla_configuration_id") OR OLD."team_manager_id" IS DISTINCT FROM (NEW."team_manager_id") OR OLD."technical_contact_id" IS DISTINCT FROM (NEW."technical_contact_id") OR OLD."tid" IS DISTINCT FROM (NEW."tid") OR OLD."user_records" IS DISTINCT FROM (NEW."user_records"))', func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (NEW."archive_batch", NEW."archived_at", NEW."async_updating", NEW."business_criticality", NEW."created", NEW."description", NEW."disable_sla_breach_notifications", NEW."enable_full_risk_acceptance", NEW."enable_product_tag_inheritance", NEW."enable_simple_risk_acceptance", NEW."external_audience", NEW."id", NEW."internet_accessible", NEW."lifecycle_id", NEW."name", NEW."origin_id", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."platform_id", NEW."prod_numeric_grade", NEW."prod_type_id", NEW."product_manager_id", NEW."revenue", NEW."sla_configuration_id", NEW."team_manager_id", NEW."technical_contact_id", NEW."tid", NEW."updated", NEW."user_records"); RETURN NULL;', hash="b5793f361239e1329aea5ee48f4b68ba6d9c5f0f", operation="UPDATE", pgid="pgtrigger_update_update_e7040", table="dojo_product", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_productevent" ("archive_batch", "archived_at", "async_updating", "business_criticality", "created", "description", "disable_sla_breach_notifications", "enable_full_risk_acceptance", "enable_product_tag_inheritance", "enable_simple_risk_acceptance", "external_audience", "id", "internet_accessible", "lifecycle_id", "name", "origin_id", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "platform_id", "prod_numeric_grade", "prod_type_id", "product_manager_id", "revenue", "sla_configuration_id", "team_manager_id", "technical_contact_id", "tid", "updated", "user_records") VALUES (OLD."archive_batch", OLD."archived_at", OLD."async_updating", OLD."business_criticality", OLD."created", OLD."description", OLD."disable_sla_breach_notifications", OLD."enable_full_risk_acceptance", OLD."enable_product_tag_inheritance", OLD."enable_simple_risk_acceptance", OLD."external_audience", OLD."id", OLD."internet_accessible", OLD."lifecycle_id", OLD."name", OLD."origin_id", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."platform_id", OLD."prod_numeric_grade", OLD."prod_type_id", OLD."product_manager_id", OLD."revenue", OLD."sla_configuration_id", OLD."team_manager_id", OLD."technical_contact_id", OLD."tid", OLD."updated", OLD."user_records"); RETURN NULL;', hash="b680a761758c22da5777b8b70f718169dfaf58b5", operation="DELETE", pgid="pgtrigger_delete_delete_064dd", table="dojo_product", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product_type", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."updated"); RETURN NULL;', hash="c22c7686452daedc2b9216ac67df591501e319f2", operation="INSERT", pgid="pgtrigger_insert_insert_2d109", table="dojo_product_type", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product_type", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."critical_product" IS DISTINCT FROM (NEW."critical_product") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."key_product" IS DISTINCT FROM (NEW."key_product") OR OLD."name" IS DISTINCT FROM (NEW."name"))', func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (NEW."archive_batch", NEW."archived_at", NEW."created", NEW."critical_product", NEW."description", NEW."id", NEW."key_product", NEW."name", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."updated"); RETURN NULL;', hash="f0b2de3b71e7b546d0efe2cb7950638c095d85fd", operation="UPDATE", pgid="pgtrigger_update_update_a0136", table="dojo_product_type", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="product_type", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_product_typeevent" ("archive_batch", "archived_at", "created", "critical_product", "description", "id", "key_product", "name", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "updated") VALUES (OLD."archive_batch", OLD."archived_at", OLD."created", OLD."critical_product", OLD."description", OLD."id", OLD."key_product", OLD."name", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."updated"); RETURN NULL;', hash="7d8aada72ff77dd0e91e25d2324c57b8d8500509", operation="DELETE", pgid="pgtrigger_delete_delete_66b18", table="dojo_product_type", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="test", + trigger=pgtrigger.compiler.Trigger(name="insert_insert", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash="477f6a297658d54b13ef83b4f4b19b0e76f2bb27", operation="INSERT", pgid="pgtrigger_insert_insert_ecfc1", table="dojo_test", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="test", + trigger=pgtrigger.compiler.Trigger(name="update_update", sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD."api_scan_configuration_id" IS DISTINCT FROM (NEW."api_scan_configuration_id") OR OLD."archive_batch" IS DISTINCT FROM (NEW."archive_batch") OR OLD."archived_at" IS DISTINCT FROM (NEW."archived_at") OR OLD."branch_tag" IS DISTINCT FROM (NEW."branch_tag") OR OLD."build_id" IS DISTINCT FROM (NEW."build_id") OR OLD."commit_hash" IS DISTINCT FROM (NEW."commit_hash") OR OLD."description" IS DISTINCT FROM (NEW."description") OR OLD."engagement_id" IS DISTINCT FROM (NEW."engagement_id") OR OLD."environment_id" IS DISTINCT FROM (NEW."environment_id") OR OLD."id" IS DISTINCT FROM (NEW."id") OR OLD."lead_id" IS DISTINCT FROM (NEW."lead_id") OR OLD."percent_complete" IS DISTINCT FROM (NEW."percent_complete") OR OLD."scan_type" IS DISTINCT FROM (NEW."scan_type") OR OLD."target_end" IS DISTINCT FROM (NEW."target_end") OR OLD."target_start" IS DISTINCT FROM (NEW."target_start") OR OLD."test_type_id" IS DISTINCT FROM (NEW."test_type_id") OR OLD."title" IS DISTINCT FROM (NEW."title") OR OLD."version" IS DISTINCT FROM (NEW."version"))', func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (NEW."api_scan_configuration_id", NEW."archive_batch", NEW."archived_at", NEW."branch_tag", NEW."build_id", NEW."commit_hash", NEW."created", NEW."description", NEW."engagement_id", NEW."environment_id", NEW."id", NEW."lead_id", NEW."percent_complete", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."scan_type", NEW."target_end", NEW."target_start", NEW."test_type_id", NEW."title", NEW."updated", NEW."version"); RETURN NULL;', hash="50e41edef10c98f5e20b9c43a324c49f5b897f88", operation="UPDATE", pgid="pgtrigger_update_update_c40f8", table="dojo_test", when="AFTER")), + ), + pgtrigger.migrations.AddTrigger( + model_name="test", + trigger=pgtrigger.compiler.Trigger(name="delete_delete", sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "dojo_testevent" ("api_scan_configuration_id", "archive_batch", "archived_at", "branch_tag", "build_id", "commit_hash", "created", "description", "engagement_id", "environment_id", "id", "lead_id", "percent_complete", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "scan_type", "target_end", "target_start", "test_type_id", "title", "updated", "version") VALUES (OLD."api_scan_configuration_id", OLD."archive_batch", OLD."archived_at", OLD."branch_tag", OLD."build_id", OLD."commit_hash", OLD."created", OLD."description", OLD."engagement_id", OLD."environment_id", OLD."id", OLD."lead_id", OLD."percent_complete", _pgh_attach_context(), NOW(), \'delete\', OLD."id", OLD."scan_type", OLD."target_end", OLD."target_start", OLD."test_type_id", OLD."title", OLD."updated", OLD."version"); RETURN NULL;', hash="0b9eda2793d6208cb855751dc6c39f8d6819cd2d", operation="DELETE", pgid="pgtrigger_delete_delete_66d18", table="dojo_test", when="AFTER")), + ), + ], + database_operations=[ + migrations.RunSQL(sql=[FORWARD_SQL], reverse_sql=[BACKWARD_SQL]), + ], ), ] From 20247099363f89119459cbff6e57ed1480f0def9 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Wed, 28 Oct 2026 23:07:09 -0600 Subject: [PATCH 5/5] feat(dedupe): let a plugin set excess duplicates aside instead of deleting them register_excess_duplicate_handler installs one handler for the chunks the excess-duplicate task removes. It runs inside the chunk's transaction with the rows locked; when it returns True nothing is deleted. With no handler, or one that returns False, the chunk is deleted as before. Co-Authored-By: Claude Opus 5.5 --- dojo/tasks.py | 19 ++++++++- unittests/test_excess_duplicate_handler.py | 47 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 unittests/test_excess_duplicate_handler.py diff --git a/dojo/tasks.py b/dojo/tasks.py index deb9b6028dd..0bd8d9cab3e 100644 --- a/dojo/tasks.py +++ b/dojo/tasks.py @@ -29,6 +29,23 @@ # Findings locked and re-checked per transaction by _delete_excess_duplicates. DUPE_DELETE_CHUNK_SIZE = 1000 +# A plugin may set excess duplicates aside instead of deleting them. The handler gets each +# chunk's queryset inside the chunk's transaction, with the rows already locked, and returns +# True when it has dealt with them. It must leave them out of Finding.objects, or the next run +# selects them again. With no handler, or one that returns False, the chunk is deleted. +_excess_duplicate_handler = None + + +def register_excess_duplicate_handler(func): + global _excess_duplicate_handler # noqa: PLW0603 + _excess_duplicate_handler = func + + +def _remove_excess_duplicates(findings): + if _excess_duplicate_handler is not None and _excess_duplicate_handler(findings): + return + bulk_delete_findings(findings, order_desc=True) + from dojo.notifications.tasks import ( # noqa: E402, F401 -- backward compat add_alerts, @@ -216,7 +233,7 @@ def _delete_excess_duplicates(ids_to_delete): if skipped := len(chunk) - len(still_settled): logger.info("skipping %s excess duplicates that an import is writing, or that were saved or deleted since they were selected", skipped) if still_settled: - bulk_delete_findings(Finding.objects.filter(id__in=still_settled), order_desc=True) + _remove_excess_duplicates(Finding.objects.filter(id__in=still_settled)) deleted_ids.extend(still_settled) return deleted_ids diff --git a/unittests/test_excess_duplicate_handler.py b/unittests/test_excess_duplicate_handler.py new file mode 100644 index 00000000000..5a6f344e1b9 --- /dev/null +++ b/unittests/test_excess_duplicate_handler.py @@ -0,0 +1,47 @@ +""" +A plugin can set excess duplicates aside instead of deleting them. + +``register_excess_duplicate_handler`` installs one handler for the chunks the excess-duplicate +task removes. When the handler returns True it has dealt with the chunk and nothing is deleted; +with no handler, or one that returns False, the chunk is deleted as before. Only the hand-off is +tested here, so ``bulk_delete_findings`` is mocked and no database is touched. +""" +from unittest.mock import Mock, patch + +from django.test import SimpleTestCase + +from dojo import tasks + + +class ExcessDuplicateHandlerTest(SimpleTestCase): + def setUp(self): + self.addCleanup(tasks.register_excess_duplicate_handler, None) + self.chunk = Mock(name="chunk") + + @patch("dojo.tasks.bulk_delete_findings") + def test_without_a_handler_the_chunk_is_deleted(self, delete): + tasks.register_excess_duplicate_handler(None) + + tasks._remove_excess_duplicates(self.chunk) + + delete.assert_called_once_with(self.chunk, order_desc=True) + + @patch("dojo.tasks.bulk_delete_findings") + def test_a_handler_that_takes_the_chunk_stops_the_delete(self, delete): + handler = Mock(return_value=True) + tasks.register_excess_duplicate_handler(handler) + + tasks._remove_excess_duplicates(self.chunk) + + handler.assert_called_once_with(self.chunk) + delete.assert_not_called() + + @patch("dojo.tasks.bulk_delete_findings") + def test_a_handler_that_declines_leaves_the_delete_in_place(self, delete): + handler = Mock(return_value=False) + tasks.register_excess_duplicate_handler(handler) + + tasks._remove_excess_duplicates(self.chunk) + + handler.assert_called_once_with(self.chunk) + delete.assert_called_once_with(self.chunk, order_desc=True)