Skip to content

Commit

Permalink
Merge branch 'main' into make_library_store_order_deterministic
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-intuitem committed Dec 5, 2024
2 parents 958db84 + 1f13026 commit acb41f1
Show file tree
Hide file tree
Showing 36 changed files with 484 additions and 240 deletions.
2 changes: 1 addition & 1 deletion backend/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ def duplicate_and_link_object(new_obj, duplicate_object, target_folder, field_na

# Get parent and sub-folders of the target folder
target_parent_folders = target_folder.get_parent_folders()
sub_folders = target_folder.sub_folders()
sub_folders = target_folder.get_sub_folders()

# Get all related objects for the specified field
related_objects = getattr(source_object, field_name).all()
Expand Down
3 changes: 0 additions & 3 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1787,9 +1787,6 @@ def risk_assessments(self):
def projects(self):
return {risk_assessment.project for risk_assessment in self.risk_assessments}

def parent_project(self):
pass

def __str__(self):
return self.name

Expand Down
11 changes: 9 additions & 2 deletions backend/core/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,15 @@ class AppliedControlReadSerializer(AppliedControlWriteSerializer):

ranking_score = serializers.IntegerField(source="get_ranking_score")
owner = FieldsRelatedField(many=True)
has_evidences = serializers.BooleanField()
eta_missed = serializers.BooleanField()
# These properties shouldn't be displayed in the frontend detail view as they are simple derivations from fields already displayed in the detail view.
# has_evidences = serializers.BooleanField()
# eta_missed = serializers.BooleanField()


class AppliedControlDuplicateSerializer(BaseModelSerializer):
class Meta:
model = AppliedControl
fields = ["name", "description", "folder"]


class PolicyWriteSerializer(AppliedControlWriteSerializer):
Expand Down
3 changes: 2 additions & 1 deletion backend/core/startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,8 @@ def startup(sender: AppConfig, **kwargs):

# Create default Qualifications
try:
Qualification.create_default_qualifications()
if Qualification.objects.count() == 0:
Qualification.create_default_qualifications()
except Exception as e:
logger.error("Error creating default qualifications", exc_info=e)

Expand Down
70 changes: 50 additions & 20 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@ def export_csv(self, request):
"csf_function",
"status",
"eta",
"priority",
"owner",
]
writer.writerow(columns)
Expand All @@ -1031,6 +1032,7 @@ def export_csv(self, request):
control.csf_function,
control.status,
control.eta,
control.priority,
]
if len(control.owner.all()) > 0:
owners = ",".join([o.email for o in control.owner.all()])
Expand Down Expand Up @@ -1154,6 +1156,53 @@ def get_timeline_info(self, request):
colorMap[domain.name] = next(color_cycle)
return Response({"entries": entries, "colorMap": colorMap})

@action(
detail=True,
name="Duplicate applied control",
methods=["post"],
serializer_class=AppliedControlDuplicateSerializer,
)
def duplicate(self, request, pk):
(object_ids_view, _, _) = RoleAssignment.get_accessible_object_ids(
Folder.get_root_folder(), request.user, AppliedControl
)
if UUID(pk) not in object_ids_view:
return Response(
{"results": "applied control duplicated"},
status=status.HTTP_404_NOT_FOUND,
)

applied_control = self.get_object()
data = request.data
new_folder = Folder.objects.get(id=data["folder"])
duplicate_applied_control = AppliedControl.objects.create(
reference_control=applied_control.reference_control,
name=data["name"],
description=data["description"],
folder=new_folder,
ref_id=applied_control.ref_id,
category=applied_control.category,
csf_function=applied_control.csf_function,
priority=applied_control.priority,
status=applied_control.status,
start_date=applied_control.start_date,
eta=applied_control.eta,
expiry_date=applied_control.expiry_date,
link=applied_control.link,
effort=applied_control.effort,
cost=applied_control.cost,
)
duplicate_applied_control.owner.set(applied_control.owner.all())
if data["duplicate_evidences"]:
duplicate_related_objects(
applied_control, duplicate_applied_control, new_folder, "evidences"
)
duplicate_applied_control.save()

return Response(
{"results": AppliedControlReadSerializer(duplicate_applied_control).data}
)

@action(detail=False, methods=["get"])
def ids(self, request):
my_map = dict()
Expand Down Expand Up @@ -2014,26 +2063,7 @@ def action_plan(self, request, pk):
)
)
applied_controls = [
{
"id": applied_control.id,
"name": applied_control.name,
"description": applied_control.description,
"status": applied_control.status,
"category": applied_control.category,
"csf_function": applied_control.csf_function,
"eta": applied_control.eta,
"expiry_date": applied_control.expiry_date,
"link": applied_control.link,
"effort": applied_control.effort,
"cost": applied_control.cost,
"owners": [
{
"id": owner.id,
"email": owner.email,
}
for owner in applied_control.owner.all()
],
}
AppliedControlReadSerializer(applied_control).data
for applied_control in AppliedControl.objects.filter(
requirement_assessments__in=requirement_assessments_objects
).distinct()
Expand Down
34 changes: 16 additions & 18 deletions backend/iam/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Inspired from Azure IAM model"""

from collections import defaultdict
from typing import Any, List, Self, Tuple
from typing import Any, List, Self, Tuple, Generator
import uuid
from allauth.account.models import EmailAddress
from django.utils import timezone
Expand Down Expand Up @@ -101,24 +101,22 @@ class Meta:
def __str__(self) -> str:
return self.name.__str__()

def sub_folders(self) -> List[Self]:
def get_sub_folders(self) -> Generator[Self, None, None]:
"""Return the list of subfolders"""

def sub_folders_in(f, sub_folder_list):
for sub_folder in f.folder_set.all():
sub_folder_list.append(sub_folder)
sub_folders_in(sub_folder, sub_folder_list)
return sub_folder_list
def sub_folders_in(folder):
for sub_folder in folder.folder_set.all():
yield sub_folder
yield from sub_folders_in(sub_folder)

return sub_folders_in(self, [])
yield from sub_folders_in(self)

def get_parent_folders(self) -> List[Self]:
# Should we update data-model.md now that this method is a generator ?
def get_parent_folders(self) -> Generator[Self, None, None]:
"""Return the list of parent folders"""
return (
[self.parent_folder] + Folder.get_parent_folders(self.parent_folder)
if self.parent_folder
else []
)
current_folder = self
while (current_folder := current_folder.parent_folder) is not None:
yield current_folder

@staticmethod
def _navigate_structure(start, path):
Expand Down Expand Up @@ -657,11 +655,11 @@ def get_accessible_folders(
]:
for f in ra.perimeter_folders.all():
folders_set.add(f)
folders_set.update(f.sub_folders())
folders_set.update(f.get_sub_folders())
# calculate perimeter
perimeter = set()
perimeter.add(folder)
perimeter.update(folder.sub_folders())
perimeter.update(folder.get_sub_folders())
# return filtered result
return [
x.id
Expand Down Expand Up @@ -698,7 +696,7 @@ def get_accessible_object_ids(
folder_for_object = {x: Folder.get_folder(x) for x in all_objects}
perimeter = set()
perimeter.add(folder)
perimeter.update(folder.sub_folders())
perimeter.update(folder.get_sub_folders())
for ra in [
x
for x in RoleAssignment.get_role_assignments(user)
Expand All @@ -707,7 +705,7 @@ def get_accessible_object_ids(
ra_permissions = ra.role.permissions.all()
for my_folder in perimeter & set(ra.perimeter_folders.all()):
target_folders = (
[my_folder] + my_folder.sub_folders()
[my_folder, *my_folder.get_sub_folders()]
if ra.is_recursive
else [my_folder]
)
Expand Down
10 changes: 5 additions & 5 deletions backend/library/libraries/cyber_essentials.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
urn: urn:intuitem:risk:library:cyber_essentials_requirements_for_it_infrastructure
locale: en
ref_id: ' Cyber Essentials: Requirements for IT infrastructure '
name: ' Cyber Essentials: Requirements for IT infrastructure v3.1'
ref_id: Cyber Essentials: Requirements for IT infrastructure
name: Cyber Essentials: Requirements for IT infrastructure v3.1
description: "Cyber Essentials is a set of baseline technical controls produced by\
\ the UK Government and security industry to help organisations \u2013 large and\
\ small \u2013 improve their cyber security defences and demonstrate a public commitment\
\ to their network security and the standards to which they operate. \nhttps://www.ncsc.gov.uk/files/Cyber-Essentials-Requirements-for-Infrastructure-v3-1-January-2023.pdf"
copyright: 'Information
Licence : https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/'
version: 1
version: 2
provider: NCSC
packager: intuitem
objects:
framework:
urn: urn:intuitem:risk:framework:cyber_essentials_requirements_for_it_infrastructure
ref_id: ' Cyber Essentials: Requirements for IT infrastructure '
name: ' Cyber Essentials: Requirements for IT infrastructure v3.1'
ref_id: Cyber Essentials: Requirements for IT infrastructure
name: Cyber Essentials: Requirements for IT infrastructure v3.1
description: "Cyber Essentials is a set of baseline technical controls produced\
\ by the UK Government and security industry to help organisations \u2013 large\
\ and small \u2013 improve their cyber security defences and demonstrate a public\
Expand Down
5 changes: 4 additions & 1 deletion frontend/messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@
"back": "خلف",
"duplicate": "ينسخ",
"duplicateRiskAssessment": "تكرار تقييم المخاطر",
"duplicateAppliedControl": "تكرار عنصر التحكم المطبق",
"size": "الحجم",
"favicon": "الرمز المفضل",
"logo": "الشعار",
Expand Down Expand Up @@ -862,5 +863,7 @@
"tagsHelpText": "تُستخدم العلامات لتصنيف العناصر وتصفيتها. يمكنك إضافة علامات في قسم \"إضافي\"",
"forgotPassword": "هل نسيت كلمة السر",
"scoreSemiColon": "نتيجة:",
"mappingInferenceHelpText": "هذه المتغيرات ثابتة ولن تتغير اعتمادًا على المصدر."
"mappingInferenceHelpText": "هذه المتغيرات ثابتة ولن تتغير اعتمادًا على المصدر.",
"bringTheEvidences": "أحضر الأدلة",
"bringTheEvidencesHelpText": "في حالة التعطيل، سيتم تكرار الكائن بدون أدلته"
}
4 changes: 3 additions & 1 deletion frontend/messages/cz.json
Original file line number Diff line number Diff line change
Expand Up @@ -852,5 +852,7 @@
"exploreButton": "Prozkoumat",
"tags": "Štítky",
"addTag": "Přidat štítek",
"tagsHelpText": "Štítky pomáhají kategorizovat a filtrovat více objektů. Můžete je spravovat v menu Extra."
"tagsHelpText": "Štítky pomáhají kategorizovat a filtrovat více objektů. Můžete je spravovat v menu Extra.",
"bringTheEvidences": "Přineste důkazy",
"bringTheEvidencesHelpText": "Pokud je zakázáno, objekt bude duplikován bez jeho důkazů"
}
5 changes: 4 additions & 1 deletion frontend/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@
"back": "Zurückkehren",
"duplicate": "Duplikat",
"duplicateRiskAssessment": "Duplizieren Sie die Risikobewertung",
"duplicateAppliedControl": "Duplizieren Sie das angewendete kontrolle",
"size": "Größe",
"favicon": "Favicon",
"logo": "Logo",
Expand Down Expand Up @@ -861,5 +862,7 @@
"tagsHelpText": "Tags werden zum Kategorisieren und Filtern der Elemente verwendet. Sie können Tags im Abschnitt Extra hinzufügen",
"forgotPassword": "Passwort vergessen",
"scoreSemiColon": "Punktzahl:",
"mappingInferenceHelpText": "Diese Variablen sind fest und ändern sich je nach Quelle nicht."
"mappingInferenceHelpText": "Diese Variablen sind fest und ändern sich je nach Quelle nicht.",
"bringTheEvidences": "Bringen Sie die Beweise",
"bringTheEvidencesHelpText": "Wenn deaktiviert, wird das Objekt ohne seine Beweise dupliziert"
}
5 changes: 4 additions & 1 deletion frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@
"back": "Back",
"duplicate": "Duplicate",
"duplicateRiskAssessment": "Duplicate the risk assessment",
"duplicateAppliedControl": "Duplicate the applied control",
"size": "Size",
"favicon": "Favicon",
"logo": "Logo",
Expand Down Expand Up @@ -919,5 +920,7 @@
"ebiosWs5_3": "Define security measures",
"ebiosWs5_4": "Assess and document residual risks",
"ebiosWs5_5": "Establish risk monitoring framework",
"activity": "Activity"
"activity": "Activity",
"bringTheEvidences": "Bring the evidences",
"bringTheEvidencesHelpText": "If disabled, the object will be duplicated without its evidences"
}
5 changes: 4 additions & 1 deletion frontend/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@
"back": "Devolver",
"duplicate": "Duplicar",
"duplicateRiskAssessment": "Duplicar la evaluación de riesgo",
"duplicateAppliedControl": "Duplicar el control aplicado",
"size": "Tamaño",
"favicon": "Favicon",
"logo": "Logo",
Expand Down Expand Up @@ -861,5 +862,7 @@
"tagsHelpText": "Las etiquetas se utilizan para categorizar y filtrar los elementos. Puedes agregar etiquetas en la sección Extra",
"forgotPassword": "Has olvidado tu contraseña",
"scoreSemiColon": "Puntaje:",
"mappingInferenceHelpText": "Estas variables son fijas y no cambiarán dependiendo de la fuente."
"mappingInferenceHelpText": "Estas variables son fijas y no cambiarán dependiendo de la fuente.",
"bringTheEvidences": "Traer las evidencias",
"bringTheEvidencesHelpText": "Si está deshabilitado, el objeto se duplicará sin sus evidencias."
}
7 changes: 5 additions & 2 deletions frontend/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@
"back": "Retour",
"duplicate": "Dupliquer",
"duplicateRiskAssessment": "Dupliquer l’évaluation de risque",
"duplicateAppliedControl": "Dupliquer la mesure appliquée",
"size": "Taille",
"favicon": "Icône de favori",
"logo": "Logo",
Expand Down Expand Up @@ -792,7 +793,7 @@
"licenseAboutToExpireWarning": "Il reste {days_left} jours avant l'expiration de votre licence.",
"proof": "Preuve",
"privacy": "Confidentialité",
"safety": "Sécurité",
"safety": "Sûreté",
"noExpirationDateSet": "Aucune date d'expiration définie",
"sumpageTotal": "Total",
"sumpageActive": "Actif",
Expand Down Expand Up @@ -895,5 +896,7 @@
"ebiosWs5_3": "Définir les mesures de sécurité",
"ebiosWs5_4": "Évaluer et documenter les risques résiduels",
"ebiosWs5_5": "Mettre en place le cadre de suivi des risques",
"activity": "Activité"
"activity": "Activité",
"bringTheEvidences": "Apportez les preuves",
"bringTheEvidencesHelpText": "Si désactivé, l'objet sera dupliqué sans ses preuves"
}
5 changes: 4 additions & 1 deletion frontend/messages/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@
"back": "वापस",
"duplicate": "प्रतिलिपि",
"duplicateRiskAssessment": "जोखिम आकलन की प्रतिलिपि बनाएँ",
"duplicateAppliedControl": "लागू नियंत्रण की प्रतिलिपि बनाएँ",
"size": "आकार",
"favicon": "फ़ेविकॉन",
"logo": "प्रतीक चिन्ह",
Expand Down Expand Up @@ -861,5 +862,7 @@
"tagsHelpText": "टैग का उपयोग आइटम को वर्गीकृत और फ़िल्टर करने के लिए किया जाता है। आप अतिरिक्त अनुभाग में टैग जोड़ सकते हैं",
"forgotPassword": "पासवर्ड भूल गए",
"scoreSemiColon": "अंक:",
"mappingInferenceHelpText": "ये चर निश्चित हैं और स्रोत के आधार पर परिवर्तित नहीं होंगे।"
"mappingInferenceHelpText": "ये चर निश्चित हैं और स्रोत के आधार पर परिवर्तित नहीं होंगे।",
"bringTheEvidences": "सबूत लाओ",
"bringTheEvidencesHelpText": "यदि अक्षम किया गया है, तो ऑब्जेक्ट को उसके साक्ष्य के बिना डुप्लिकेट किया जाएगा"
}
5 changes: 4 additions & 1 deletion frontend/messages/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@
"back": "Ripetere",
"duplicate": "Duplicare",
"duplicateRiskAssessment": "Duplicare la valutazione del rischio",
"duplicateAppliedControl": "Duplica il controllo applicato",
"size": "Dimensione",
"favicon": "Icona preferita",
"logo": "Logo",
Expand Down Expand Up @@ -861,5 +862,7 @@
"tagsHelpText": "I tag vengono utilizzati per categorizzare e filtrare gli elementi. Puoi aggiungere tag nella sezione Extra",
"forgotPassword": "Ha dimenticato la password",
"scoreSemiColon": "Punto:",
"mappingInferenceHelpText": "Queste variabili sono fisse e non cambiano a seconda della fonte."
"mappingInferenceHelpText": "Queste variabili sono fisse e non cambiano a seconda della fonte.",
"bringTheEvidences": "Portare le prove",
"bringTheEvidencesHelpText": "Se disabilitato, l'oggetto verrà duplicato senza le sue prove"
}
Loading

0 comments on commit acb41f1

Please sign in to comment.