Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/CA-681-create-crud-endpoints-for…
Browse files Browse the repository at this point in the history
…-ebios-models' into CA-672-Step-1.1-1.2
  • Loading branch information
Mohamed-Hacene committed Dec 4, 2024
2 parents 2023fd5 + bc11fb0 commit 4c5090b
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 21 deletions.
20 changes: 20 additions & 0 deletions backend/core/startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,26 @@
"view_ebiosrmstudy",
"change_ebiosrmstudy",
"delete_ebiosrmstudy",
"add_fearedevent",
"view_fearedevent",
"change_fearedevent",
"delete_fearedevent",
"add_roto",
"view_roto",
"change_roto",
"delete_roto",
"add_stakeholder",
"view_stakeholder",
"change_stakeholder",
"delete_stakeholder",
"add_attackpath",
"view_attackpath",
"change_attackpath",
"delete_attackpath",
"add_operationalscenario",
"view_operationalscenario",
"change_operationalscenario",
"delete_operationalscenario",
]

THIRD_PARTY_RESPONDENT_PERMISSIONS_LIST = [
Expand Down
1 change: 1 addition & 0 deletions backend/core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
path("iam/", include("iam.urls")),
path("serdes/", include("serdes.urls")),
path("settings/", include("global_settings.urls")),
path("ebios-rm/", include("ebios_rm.urls")),
path("csrf/", get_csrf_token, name="get_csrf_token"),
path("build/", get_build, name="get_build"),
path("evidences/<uuid:pk>/upload/", UploadAttachmentView.as_view(), name="upload"),
Expand Down
5 changes: 4 additions & 1 deletion backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ def get_queryset(self):
return None
object_ids_view = None
if self.request.method == "GET":
if q := re.match("/api/[\w-]+/([0-9a-f-]+)", self.request.path):
if q := re.match(
"/api/[\w-]+/([\w-]+/)?([0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}(,[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})+)",
self.request.path,
):
""""get_queryset is called by Django even for an individual object via get_object
https://stackoverflow.com/questions/74048193/why-does-a-retrieve-request-end-up-calling-get-queryset"""
id = UUID(q.group(1))
Expand Down
51 changes: 48 additions & 3 deletions backend/ebios_rm/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.1.1 on 2024-12-03 12:57
# Generated by Django 5.1.1 on 2024-12-04 13:02

import django.core.validators
import django.db.models.deletion
Expand Down Expand Up @@ -54,7 +54,7 @@ class Migration(migrations.Migration):
"due_date",
models.DateField(blank=True, null=True, verbose_name="Due date"),
),
("ref_id", models.CharField(max_length=100)),
("ref_id", models.CharField(blank=True, max_length=100)),
(
"version",
models.CharField(
Expand Down Expand Up @@ -206,6 +206,15 @@ class Migration(migrations.Migration):
"justification",
models.TextField(blank=True, verbose_name="Justification"),
),
(
"folder",
models.ForeignKey(
default=iam.models.Folder.get_root_folder_id,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_folder",
to="iam.folder",
),
),
(
"ebios_rm_study",
models.ForeignKey(
Expand Down Expand Up @@ -250,7 +259,7 @@ class Migration(migrations.Migration):
"description",
models.TextField(blank=True, null=True, verbose_name="Description"),
),
("ref_id", models.CharField(max_length=100)),
("ref_id", models.CharField(blank=True, max_length=100)),
(
"gravity",
models.SmallIntegerField(default=-1, verbose_name="Gravity"),
Expand Down Expand Up @@ -281,6 +290,15 @@ class Migration(migrations.Migration):
verbose_name="EBIOS RM study",
),
),
(
"folder",
models.ForeignKey(
default=iam.models.Folder.get_root_folder_id,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_folder",
to="iam.folder",
),
),
(
"qualifications",
models.ManyToManyField(
Expand Down Expand Up @@ -353,6 +371,15 @@ class Migration(migrations.Migration):
verbose_name="EBIOS RM study",
),
),
(
"folder",
models.ForeignKey(
default=iam.models.Folder.get_root_folder_id,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_folder",
to="iam.folder",
),
),
(
"threats",
models.ManyToManyField(
Expand Down Expand Up @@ -489,6 +516,15 @@ class Migration(migrations.Migration):
verbose_name="Feared events",
),
),
(
"folder",
models.ForeignKey(
default=iam.models.Folder.get_root_folder_id,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_folder",
to="iam.folder",
),
),
],
options={
"verbose_name": "RO/TO couple",
Expand Down Expand Up @@ -656,6 +692,15 @@ class Migration(migrations.Migration):
verbose_name="Entity",
),
),
(
"folder",
models.ForeignKey(
default=iam.models.Folder.get_root_folder_id,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_folder",
to="iam.folder",
),
),
],
options={
"verbose_name": "Stakeholder",
Expand Down
34 changes: 27 additions & 7 deletions backend/ebios_rm/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class Status(models.TextChoices):
default=Entity.get_main_entity,
)

ref_id = models.CharField(max_length=100)
ref_id = models.CharField(max_length=100, blank=True)
version = models.CharField(
max_length=100,
blank=True,
Expand Down Expand Up @@ -102,7 +102,7 @@ class Meta:
ordering = ["created_at"]


class FearedEvent(NameDescriptionMixin):
class FearedEvent(NameDescriptionMixin, FolderMixin):
ebios_rm_study = models.ForeignKey(
EbiosRMStudy,
verbose_name=_("EBIOS RM study"),
Expand All @@ -123,7 +123,7 @@ class FearedEvent(NameDescriptionMixin):
help_text=_("Qualifications carried by the feared event"),
)

ref_id = models.CharField(max_length=100)
ref_id = models.CharField(max_length=100, blank=True)
gravity = models.SmallIntegerField(default=-1, verbose_name=_("Gravity"))
is_selected = models.BooleanField(verbose_name=_("Is selected"), default=False)
justification = models.TextField(verbose_name=_("Justification"), blank=True)
Expand All @@ -133,8 +133,12 @@ class Meta:
verbose_name_plural = _("Feared events")
ordering = ["created_at"]

def save(self, *args, **kwargs):
self.folder = self.ebios_rm_study.folder
super().save(*args, **kwargs)

class RoTo(AbstractBaseModel):

class RoTo(AbstractBaseModel, FolderMixin):
class RiskOrigin(models.TextChoices):
STATE = "state", _("State")
ORGANIZED_CRIME = "organized_crime", _("Organized crime")
Expand Down Expand Up @@ -207,8 +211,12 @@ class Meta:
verbose_name_plural = _("RO/TO couples")
ordering = ["created_at"]

def save(self, *args, **kwargs):
self.folder = self.ebios_rm_study.folder
super().save(*args, **kwargs)


class Stakeholder(AbstractBaseModel):
class Stakeholder(AbstractBaseModel, FolderMixin):
class Category(models.TextChoices):
CLIENT = "client", _("Client")
PARTNER = "partner", _("Partner")
Expand Down Expand Up @@ -290,6 +298,10 @@ class Meta:
verbose_name_plural = _("Stakeholders")
ordering = ["created_at"]

def save(self, *args, **kwargs):
self.folder = self.ebios_rm_study.folder
super().save(*args, **kwargs)

@staticmethod
def _compute_criticality(
dependency: int, penetration: int, maturity: int, trust: int
Expand Down Expand Up @@ -317,7 +329,7 @@ def residual_criticality(self):
)


class AttackPath(AbstractBaseModel):
class AttackPath(AbstractBaseModel, FolderMixin):
ebios_rm_study = models.ForeignKey(
EbiosRMStudy,
verbose_name=_("EBIOS RM study"),
Expand Down Expand Up @@ -345,8 +357,12 @@ class Meta:
verbose_name_plural = _("Attack paths")
ordering = ["created_at"]

def save(self, *args, **kwargs):
self.folder = self.ebios_rm_study.folder
super().save(*args, **kwargs)

class OperationalScenario(AbstractBaseModel):

class OperationalScenario(AbstractBaseModel, FolderMixin):
ebios_rm_study = models.ForeignKey(
EbiosRMStudy,
verbose_name=_("EBIOS RM study"),
Expand Down Expand Up @@ -376,3 +392,7 @@ class Meta:
verbose_name = _("Operational scenario")
verbose_name_plural = _("Operational scenarios")
ordering = ["created_at"]

def save(self, *args, **kwargs):
self.folder = self.ebios_rm_study.folder
super().save(*args, **kwargs)
45 changes: 36 additions & 9 deletions backend/ebios_rm/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,31 @@
AssessmentReadSerializer,
)
from core.models import StoredLibrary, RiskMatrix
from .models import EbiosRMStudy
from .models import EbiosRMStudy, FearedEvent
from rest_framework import serializers
import logging


class EbiosRMStudyWriteSerializer(BaseModelSerializer):
risk_matrix = serializers.PrimaryKeyRelatedField(
queryset=RiskMatrix.objects.all(), required=False
)

def create(self, validated_data):
if not validated_data.get("risk_matrix"):
try:
ebios_matrix_library = StoredLibrary.objects.get(
urn="urn:intuitem:risk:library:risk-matrix-4x4-ebios-rm"
)
ebios_matrix_library.load()

validated_data["risk_matrix"] = RiskMatrix.objects.get(
ebios_matrix = RiskMatrix.objects.filter(
urn="urn:intuitem:risk:matrix:risk-matrix-4x4-ebios-rm"
)
).first()
if not ebios_matrix:
ebios_matrix_library = StoredLibrary.objects.get(
urn="urn:intuitem:risk:library:risk-matrix-4x4-ebios-rm"
)
ebios_matrix_library.load()
ebios_matrix = RiskMatrix.objects.get(
urn="urn:intuitem:risk:matrix:risk-matrix-4x4-ebios-rm"
)
validated_data["risk_matrix"] = ebios_matrix
except (StoredLibrary.DoesNotExist, RiskMatrix.DoesNotExist) as e:
logging.error(f"Error loading risk matrix: {str(e)}")
raise serializers.ValidationError(
Expand All @@ -33,15 +41,34 @@ class Meta:
exclude = ["created_at", "updated_at"]


class EbiosRMStudyReadSerializer(AssessmentReadSerializer):
class EbiosRMStudyReadSerializer(BaseModelSerializer):
str = serializers.CharField(source="__str__")
project = FieldsRelatedField(["id", "folder"])
folder = FieldsRelatedField()
risk_matrix = FieldsRelatedField()
reference_entity = FieldsRelatedField()
assets = FieldsRelatedField(many=True)
compliance_assessments = FieldsRelatedField(many=True)
risk_assessments = FieldsRelatedField(many=True)
authors = FieldsRelatedField(many=True)
reviewers = FieldsRelatedField(many=True)

class Meta:
model = EbiosRMStudy
fields = "__all__"


class FearedEventWriteSerializer(BaseModelSerializer):
class Meta:
model = FearedEvent
exclude = ["created_at", "updated_at", "folder"]


class FearedEventReadSerializer(BaseModelSerializer):
str = serializers.CharField(source="__str__")
ebios_rm_study = FieldsRelatedField()
folder = FieldsRelatedField()

class Meta:
model = FearedEvent
fields = "__all__"
13 changes: 13 additions & 0 deletions backend/ebios_rm/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.urls import include, path
from rest_framework import routers

from ebios_rm.views import EbiosRMStudyViewSet, FearedEventViewSet

router = routers.DefaultRouter()

router.register(r"studies", EbiosRMStudyViewSet, basename="studies")
router.register(r"feared-events", FearedEventViewSet, basename="feared-events")

urlpatterns = [
path("", include(router.urls)),
]
6 changes: 5 additions & 1 deletion backend/ebios_rm/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from core.views import BaseModelViewSet as AbstractBaseModelViewSet
from .models import EbiosRMStudy
from .models import EbiosRMStudy, FearedEvent
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from rest_framework.decorators import action
Expand All @@ -23,3 +23,7 @@ class EbiosRMStudyViewSet(BaseModelViewSet):
@action(detail=False, name="Get status choices")
def status(self, request):
return Response(dict(EbiosRMStudy.Status.choices))


class FearedEventViewSet(BaseModelViewSet):
model = FearedEvent
Binary file modified features.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4c5090b

Please sign in to comment.