From 752794c69cd650abe802286b93bf784110e8898b Mon Sep 17 00:00:00 2001 From: melinoix Date: Wed, 20 Nov 2024 17:34:08 +0100 Subject: [PATCH 01/12] still have to connect api point + migration --- .../migrations/0037_riskscenario_ref_id.py | 19 ++++++++++ backend/core/models.py | 17 ++++++--- backend/core/serializers.py | 1 - backend/core/views.py | 22 ++++++++++-- .../Forms/ModelForm/RiskScenarioForm.svelte | 36 +++++++++++++++++++ .../RiskMatrix/RiskScenarioItem.stories.ts | 2 +- .../RiskMatrix/RiskScenarioItem.svelte | 2 +- frontend/src/lib/utils/schemas.ts | 3 +- frontend/src/lib/utils/table.ts | 2 ++ 9 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 backend/core/migrations/0037_riskscenario_ref_id.py diff --git a/backend/core/migrations/0037_riskscenario_ref_id.py b/backend/core/migrations/0037_riskscenario_ref_id.py new file mode 100644 index 000000000..9aad60a9e --- /dev/null +++ b/backend/core/migrations/0037_riskscenario_ref_id.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.1 on 2024-11-20 12:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0036_asset_owner"), + ] + + operations = [ + migrations.AddField( + model_name="riskscenario", + name="ref_id", + field=models.CharField( + blank=True, max_length=100, verbose_name="Reference ID" + ), + ), + ] diff --git a/backend/core/models.py b/backend/core/models.py index c1c2ec8b9..9e8d377f2 100644 --- a/backend/core/models.py +++ b/backend/core/models.py @@ -2026,6 +2026,18 @@ class RiskScenario(NameDescriptionMixin): verbose_name=_("Treatment status"), ) + @classmethod + def get_default_ref_id(cls, risk_assessment: RiskAssessment): + """return associated risk assessment id""" + scenarios_ref_ids = [x.ref_id for x in risk_assessment.risk_scenarios.all()] + nb_scenarios = len(scenarios_ref_ids) + 1 + candidates = [f"R.{i}" for i in range(nb_scenarios)] + return next(x for x in candidates if x not in scenarios_ref_ids) + + ref_id = models.CharField( + max_length=100, blank=False, verbose_name=_("Reference ID") + ) + qualifications = models.JSONField(default=list, verbose_name=_("Qualifications")) strength_of_knowledge = models.IntegerField( @@ -2153,11 +2165,6 @@ def get_strength_of_knowledge(self): def __str__(self): return str(self.parent_project()) + _(": ") + str(self.name) - @property - def rid(self): - """return associated risk assessment id""" - return f"R.{self.scoped_id(scope=RiskScenario.objects.filter(risk_assessment=self.risk_assessment))}" - def save(self, *args, **kwargs): if self.current_proba >= 0 and self.current_impact >= 0: self.current_level = risk_scoring( diff --git a/backend/core/serializers.py b/backend/core/serializers.py index a27692c3e..91ce52ff4 100644 --- a/backend/core/serializers.py +++ b/backend/core/serializers.py @@ -306,7 +306,6 @@ class RiskScenarioReadSerializer(RiskScenarioWriteSerializer): applied_controls = FieldsRelatedField(many=True) existing_applied_controls = FieldsRelatedField(many=True) - rid = serializers.CharField() owner = FieldsRelatedField(many=True) diff --git a/backend/core/views.py b/backend/core/views.py index 557e28bd6..329bff8c2 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -592,7 +592,7 @@ def treatment_plan_csv(self, request, pk): ): risk_scenarios = ",".join( [ - f"{scenario.rid}: {scenario.name}" + f"{scenario.ref_id}: {scenario.name}" for scenario in mtg.risk_scenarios.all() ] ) @@ -628,7 +628,7 @@ def risk_assessment_csv(self, request, pk): writer = csv.writer(response, delimiter=";") columns = [ - "rid", + "ref_id", "threats", "name", "description", @@ -646,7 +646,7 @@ def risk_assessment_csv(self, request, pk): ) threats = ",".join([t.name for t in scenario.threats.all()]) row = [ - scenario.rid, + scenario.ref_id, threats, scenario.name, scenario.description, @@ -1146,6 +1146,22 @@ def count_per_level(self, request): def per_status(self, request): return Response({"results": risk_per_status(request.user)}) + @action(detail=False, methods=["get"], name="Get the smallest ref_id available") + def default_ref_id(self, request): + risk_assessment_id = request.query_params.get("risk_assessment") + if not risk_assessment_id: + return Response( + {"error": "Missing 'risk_assessment' parameter."}, status=400 + ) + try: + risk_assessment = RiskAssessment.objects.get(pk=risk_assessment_id) + + # Use the class method to compute the default ref_id + default_ref_id = RiskScenario.get_default_ref_id(risk_assessment) + return Response({"results": default_ref_id}) + except Exception as e: + return Response({"error": str(e)}, status=400) + class RiskAcceptanceViewSet(BaseModelViewSet): """ diff --git a/frontend/src/lib/components/Forms/ModelForm/RiskScenarioForm.svelte b/frontend/src/lib/components/Forms/ModelForm/RiskScenarioForm.svelte index b89866439..37531427a 100644 --- a/frontend/src/lib/components/Forms/ModelForm/RiskScenarioForm.svelte +++ b/frontend/src/lib/components/Forms/ModelForm/RiskScenarioForm.svelte @@ -1,6 +1,7 @@