Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions dojo/db_migrations/0278_vulnerability_id_upper_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Add a case-insensitive expression index on Vulnerability_Id.vulnerability_id.

Enables fast UPPER(vulnerability_id) → finding lookups for CVE-keyed enrichment/threat
intel. Built CONCURRENTLY (non-atomic migration) so it does not lock dojo_vulnerability_id
on large instances. CREATE ... IF NOT EXISTS makes it idempotent and safe to co-exist with
any downstream (e.g. Pro) migration that created the same-named index first.
"""
from django.db import migrations, models
from django.db.models.functions import Upper


class Migration(migrations.Migration):
atomic = False

dependencies = [
("dojo", "0277_seed_deduplication_execution_mode"),
]

operations = [
# RunSQL (IF NOT EXISTS) does the idempotent DB work; state_operations keeps Django's
# model state in sync with the Meta index so future makemigrations is a no-op.
migrations.SeparateDatabaseAndState(
database_operations=[
migrations.RunSQL(
sql=(
"CREATE INDEX CONCURRENTLY IF NOT EXISTS dojo_vulnid_upper_idx "
"ON dojo_vulnerability_id (UPPER(vulnerability_id), finding_id)"
),
reverse_sql="DROP INDEX CONCURRENTLY IF EXISTS dojo_vulnid_upper_idx",
),
],
state_operations=[
migrations.AddIndex(
model_name="vulnerability_id",
index=models.Index(
Upper("vulnerability_id"),
"finding",
name="dojo_vulnid_upper_idx",
),
),
],
),
]
14 changes: 14 additions & 0 deletions dojo/finding/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from django.conf import settings
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models.functions import Upper
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
Expand Down Expand Up @@ -1367,6 +1368,19 @@ class Vulnerability_Id(models.Model):
finding = models.ForeignKey("dojo.Finding", editable=False, on_delete=models.CASCADE)
vulnerability_id = models.TextField(max_length=50, blank=False, null=False)

class Meta:
indexes = [
# Case-insensitive vulnerability-id → finding lookups (e.g. threat-intel /
# exploit-enrichment keyed by CVE). Scanner-provided ids are not case-normalized,
# so the index and any query must both fold with UPPER(). finding_id is included
# so the changed-key → finding fan-out is an index-only scan.
models.Index(
Upper("vulnerability_id"),
"finding",
name="dojo_vulnid_upper_idx",
),
]

def __str__(self):
return self.vulnerability_id

Expand Down
Loading