Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ca 141 prevent deleting a library that is in use in an assessment #40

37 changes: 34 additions & 3 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.html import mark_safe
from django.db.models import Q

from .base_models import *
from .validators import validate_file_size, validate_file_name
Expand Down Expand Up @@ -40,6 +41,36 @@ class Library(ReferentialObjectMixin, AbstractBaseModel, FolderMixin):
verbose_name=_("Packager"),
)

@property
def reference_count(self) -> int:
"""
Returns the number of distinct risk and compliance assessments that reference objects from this library
"""
return (
RiskAssessment.objects.filter(
Q(risk_scenarios__threats__library=self)
| Q(risk_matrix__library=self)
| Q(risk_scenarios__security_measures__security_function__library=self)
)
.distinct()
.count()
+ ComplianceAssessment.objects.filter(
Q(framework__library=self)
| Q(
requirement_assessments__security_measures__security_function__library=self
)
)
.distinct()
.count()
)

def delete(self, *args, **kwargs):
if self.reference_count > 0:
raise ValueError(
"This library is still referenced by some risk or compliance assessments"
)
super(Library, self).delete(*args, **kwargs)


class Assessment(AbstractBaseModel, NameDescriptionMixin):
class Status(models.TextChoices):
Expand Down Expand Up @@ -804,7 +835,6 @@ class RiskScenario(AbstractBaseModel, NameDescriptionMixin):
("2", _("High")),
]


risk_assessment = models.ForeignKey(
RiskAssessment,
on_delete=models.CASCADE,
Expand Down Expand Up @@ -877,7 +907,7 @@ class RiskScenario(AbstractBaseModel, NameDescriptionMixin):
)

updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated at"))
strength_of_knowledge = models.CharField(
strength_of_knowledge = models.CharField(
max_length=20,
choices=SOK_OPTIONS,
default="--",
Expand Down Expand Up @@ -1190,7 +1220,7 @@ def get_requirements_status_count(self):
def get_measures_status_count(self):
measures_status_count = []
measures_list = []
for requirement_assessment in self.requirementassessment_set.all():
for requirement_assessment in self.requirement_assessments.all():
measures_list += requirement_assessment.security_measures.all().values_list(
"id", flat=True
)
Expand Down Expand Up @@ -1362,6 +1392,7 @@ class Status(models.TextChoices):
ComplianceAssessment,
on_delete=models.CASCADE,
verbose_name=_("Compliance assessment"),
related_name="requirement_assessments",
)
requirement = models.ForeignKey(
RequirementNode, on_delete=models.CASCADE, verbose_name=_("Requirement")
Expand Down
Loading
Loading