Skip to content
Merged
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
17 changes: 17 additions & 0 deletions dojo/db_migrations/0255_remove_system_settings_product_grade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.2.9 on 2026-01-09 23:56

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('dojo', '0254_remove_vulnerability_id_template_model'),
]

operations = [
migrations.RemoveField(
model_name='system_settings',
name='product_grade',
),
]
1 change: 0 additions & 1 deletion dojo/fixtures/defect_dojo_sample_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,6 @@
"url_prefix": "",
"team_name": "",
"enable_product_grade": true,
"product_grade": "def grade_product(crit, high, med, low):\r\n health=100\r\n if crit > 0:\r\n health = 40\r\n health = health - ((crit - 1) * 5)\r\n if high > 0:\r\n if health == 100:\r\n health = 60\r\n health = health - ((high - 1) * 3)\r\n if med > 0:\r\n if health == 100:\r\n health = 80\r\n health = health - ((med - 1) * 2)\r\n if low > 0:\r\n if health == 100:\r\n health = 95\r\n health = health - low\r\n\r\n if health < 5:\r\n health = 5\r\n\r\n return health",
"product_grade_a": 90,
"product_grade_b": 80,
"product_grade_c": 70,
Expand Down
1 change: 0 additions & 1 deletion dojo/fixtures/dojo_testdata.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@
"mail_notifications_to": "",
"enable_jira": false,
"enable_product_grade": true,
"product_grade": "def grade_product(crit, high, med, low):\r\n health=100\r\n if crit > 0:\r\n health = 40\r\n health = health - ((crit - 1) * 5)\r\n if high > 0:\r\n if health == 100:\r\n health = 60\r\n health = health - ((high - 1) * 3)\r\n if med > 0:\r\n if health == 100:\r\n health = 80\r\n health = health - ((med - 1) * 2)\r\n if low > 0:\r\n if health == 100:\r\n health = 95\r\n health = health - low\r\n\r\n if health < 5:\r\n health = 5\r\n\r\n return health",
"product_grade_a": 90,
"product_grade_b": 80,
"product_grade_c": 70,
Expand Down
1 change: 0 additions & 1 deletion dojo/fixtures/system_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"enable_deduplication": false,
"enable_jira": false,
"url_prefix": "",
"product_grade": "def grade_product(crit, high, med, low):\r\n health=100\r\n if crit > 0:\r\n health = 40\r\n health = health - ((crit - 1) * 5)\r\n if high > 0:\r\n if health == 100:\r\n health = 60\r\n health = health - ((high - 1) * 3)\r\n if med > 0:\r\n if health == 100:\r\n health = 80\r\n health = health - ((med - 1) * 2)\r\n if low > 0:\r\n if health == 100:\r\n health = 95\r\n health = health - low\r\n\r\n if health < 5:\r\n health = 5\r\n\r\n return health",
"product_grade_a": 90,
"product_grade_b": 80,
"product_grade_c": 70,
Expand Down
2 changes: 1 addition & 1 deletion dojo/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3129,7 +3129,7 @@ def clean(self):

class Meta:
model = System_Settings
exclude = ["product_grade"]
fields = "__all__"


class BenchmarkForm(forms.ModelForm):
Expand Down
35 changes: 0 additions & 35 deletions dojo/management/commands/system_settings.py

This file was deleted.

16 changes: 1 addition & 15 deletions dojo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,6 @@ class System_Settings(models.Model):
url_prefix = models.CharField(max_length=300, default="", blank=True, help_text=_("URL prefix if DefectDojo is installed in it's own virtual subdirectory."))
team_name = models.CharField(max_length=100, default="", blank=True)
enable_product_grade = models.BooleanField(default=False, verbose_name=_("Enable Product Grading"), help_text=_("Displays a grade letter next to a product to show the overall health."))
product_grade = models.CharField(max_length=800, blank=True)
product_grade_a = models.IntegerField(default=90,
verbose_name=_("Grade A"),
help_text=_("Percentage score for an "
Expand Down Expand Up @@ -685,19 +684,6 @@ def clean(self):
})


class SystemSettingsFormAdmin(forms.ModelForm):
product_grade = forms.CharField(widget=forms.Textarea)

class Meta:
model = System_Settings
fields = ["product_grade"]


class System_SettingsAdmin(admin.ModelAdmin):
form = SystemSettingsFormAdmin
fields = ("product_grade",)


def get_current_date():
return timezone.now().date()

Expand Down Expand Up @@ -4854,7 +4840,7 @@ def __str__(self):
admin.site.register(Tool_Type)
admin.site.register(Cred_User)
admin.site.register(Cred_Mapping)
admin.site.register(System_Settings, System_SettingsAdmin)
admin.site.register(System_Settings)
admin.site.register(SLA_Configuration)
admin.site.register(CWE)
admin.site.register(Regulation)
Expand Down
34 changes: 25 additions & 9 deletions dojo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import crum
import cvss
import vobject
from asteval import Interpreter
from auditlog.models import LogEntry
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
Expand Down Expand Up @@ -1224,6 +1223,26 @@ def get_setting(setting):
return getattr(settings, setting)


def grade_product(crit, high, med, low):
health = 100
if crit > 0:
health = 40
health -= ((crit - 1) * 5)
if high > 0:
if health == 100:
health = 60
health -= ((high - 1) * 3)
if med > 0:
if health == 100:
health = 80
health -= ((med - 1) * 2)
if low > 0:
if health == 100:
health = 95
health -= low
return max(health, 5)


@dojo_model_to_id
@dojo_async_task(signature=True)
@app.task
Expand Down Expand Up @@ -1276,17 +1295,14 @@ def calculate_grade_internal(product, *args, **kwargs):
medium = severity_count["numerical_severity__count"]
elif severity_count["severity"] == "Low":
low = severity_count["numerical_severity__count"]
aeval = Interpreter()
aeval(system_settings.product_grade)
grade_product = f"grade_product({critical}, {high}, {medium}, {low})"
prod_numeric_grade = aeval(grade_product)
if prod_numeric_grade != product.prod_numeric_grade:
logger.debug("Updating product %s grade from %s to %s", product.id, product.prod_numeric_grade, prod_numeric_grade)
product.prod_numeric_grade = prod_numeric_grade
grade = grade_product(critical, high, medium, low)
if grade != product.prod_numeric_grade:
logger.debug("Updating product %s grade from %s to %s", product.id, product.prod_numeric_grade, grade)
product.prod_numeric_grade = grade
super(Product, product).save()
else:
# Use %s to safely handle None grades without formatter errors
logger.debug("Product %s grade %s is up to date", product.id, prod_numeric_grade)
logger.debug("Product %s grade %s is up to date", product.id, product.prod_numeric_grade)


def perform_product_grading(product):
Expand Down
4 changes: 2 additions & 2 deletions unittests/test_importers_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,9 @@ def test_import_reimport_reimport_performance_pghistory_no_async_with_product_gr
self.system_settings(enable_product_grade=True)

self._import_reimport_performance(
expected_num_queries1=315,
expected_num_queries1=320,
expected_num_async_tasks1=8,
expected_num_queries2=241,
expected_num_queries2=246,
expected_num_async_tasks2=19,
expected_num_queries3=123,
expected_num_async_tasks3=18,
Expand Down