From 3f9201dbf41fdf80e80c014718c0cb910f65f1d5 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 26 Dec 2024 17:21:37 +0100 Subject: [PATCH] feat: filter stakeholders in study ecosystem chart --- backend/ebios_rm/helpers.py | 86 +++++++++++++++++ backend/ebios_rm/views.py | 92 ++----------------- .../workshop-3/ecosystem/+page.server.ts | 2 +- .../workshop-3/ecosystem/+page.svelte | 2 +- .../experimental/ecosystem/+page.svelte | 5 +- 5 files changed, 97 insertions(+), 90 deletions(-) create mode 100644 backend/ebios_rm/helpers.py diff --git a/backend/ebios_rm/helpers.py b/backend/ebios_rm/helpers.py new file mode 100644 index 000000000..0546ea62e --- /dev/null +++ b/backend/ebios_rm/helpers.py @@ -0,0 +1,86 @@ +from django.db.models.query import QuerySet +import math + +def ecosystem_radar_chart_data(stakeholders_queryset: QuerySet): + qs = stakeholders_queryset + + def get_exposure_segment_id(value): + if value < 3: + return 1 + if value >= 3 and value < 7: + return 2 + if value >= 7 and value <= 9: + return 3 + if value > 9: + return 4 + return 0 + + def get_reliability_cluster(value): + if value < 4: + return "clst1" + if value >= 4 and value < 6: + return "clst2" + if value >= 6 and value <= 7: + return "clst3" + if value > 7: + return "clst4" + return 1 + + """ + // data format: f1-f4 (fiabilité cyber = maturité x confiance ) to get the clusters and colors + // x,y, z + // x: criticité calculée avec cap à 5,5 + // y: the angle (output of dict to make sure they end up on the right quadrant, min: 45, max:-45) -> done on BE + // z: the size of item (exposition = dependence x penetration) based on a dict, -> done on BE + // label: name of the 3rd party entity + Angles start at 56,25 (45+45/4) and end at -45-45/4 = 303,75 + """ + + c_data = {"clst1": [], "clst2": [], "clst3": [], "clst4": []} + r_data = {"clst1": [], "clst2": [], "clst3": [], "clst4": []} + angle_offsets = {"client": 135, "partner": 225, "supplier": 45} + + cnt_c_not_displayed = 0 + cnt_r_not_displayed = 0 + for sh in qs: + # current + c_reliability = sh.current_maturity * sh.current_trust + c_exposure = sh.current_dependency * sh.current_penetration + c_exposure_val = get_exposure_segment_id(c_exposure) * 4 + + c_criticality = ( + math.floor(sh.current_criticality * 100) / 100.0 + if sh.current_criticality <= 5 + else 5.25 + ) + + angle = angle_offsets[sh.category] + ( + get_exposure_segment_id(c_exposure) * (45 / 4) + ) + + vector = [c_criticality, angle, c_exposure_val, str(sh)] + + cluser_id = get_reliability_cluster(c_reliability) + c_data[cluser_id].append(vector) + + # residual + r_reliability = sh.residual_maturity * sh.residual_trust + r_exposure = sh.residual_dependency * sh.residual_penetration + r_exposure_val = get_exposure_segment_id(r_exposure) * 4 + + r_criticality = ( + math.floor(sh.residual_criticality * 100) / 100.0 + if sh.residual_criticality <= 5 + else 5.25 + ) + + angle = angle_offsets[sh.category] + ( + get_exposure_segment_id(r_exposure) * (45 / 4) + ) + + vector = [r_criticality, angle, r_exposure_val, str(sh)] + + cluser_id = get_reliability_cluster(r_reliability) + r_data[cluser_id].append(vector) + + return {"current": c_data, "residual": r_data} \ No newline at end of file diff --git a/backend/ebios_rm/views.py b/backend/ebios_rm/views.py index 7f5786329..542cc666c 100644 --- a/backend/ebios_rm/views.py +++ b/backend/ebios_rm/views.py @@ -1,7 +1,7 @@ import django_filters as df from core.serializers import RiskMatrixReadSerializer from core.views import BaseModelViewSet as AbstractBaseModelViewSet -from core.serializers import RiskMatrixReadSerializer +from .helpers import ecosystem_radar_chart_data from .models import ( EbiosRMStudy, FearedEvent, @@ -19,8 +19,6 @@ LONG_CACHE_TTL = 60 # mn -import math - class BaseModelViewSet(AbstractBaseModelViewSet): serializers_module = "ebios_rm.serializers" @@ -85,6 +83,10 @@ def update_workshop_step_status(self, request, pk, workshop, step): workshop, step, new_status=request.data.get("status", "in_progress") ) return Response(EbiosRMStudyReadSerializer(ebios_rm_study).data) + + @action(detail=True, name="Get ecosystem radar chart data") + def ecosystem_chart_data(self, request, pk): + return Response(ecosystem_radar_chart_data(Stakeholder.objects.filter(ebios_rm_study=pk))) class FearedEventViewSet(BaseModelViewSet): @@ -161,89 +163,7 @@ def category(self, request): @action(detail=False, name="Get chart data") def chart_data(self, request): - def get_exposure_segment_id(value): - if value < 3: - return 1 - if value >= 3 and value < 7: - return 2 - if value >= 7 and value <= 9: - return 3 - if value > 9: - return 4 - return 0 - - def get_reliability_cluster(value): - if value < 4: - return "clst1" - if value >= 4 and value < 6: - return "clst2" - if value >= 6 and value <= 7: - return "clst3" - if value > 7: - return "clst4" - return 1 - - """ - // data format: f1-f4 (fiabilité cyber = maturité x confiance ) to get the clusters and colors - // x,y, z - // x: criticité calculée avec cap à 5,5 - // y: the angle (output of dict to make sure they end up on the right quadrant, min: 45, max:-45) -> done on BE - // z: the size of item (exposition = dependence x penetration) based on a dict, -> done on BE - // label: name of the 3rd party entity - Angles start at 56,25 (45+45/4) and end at -45-45/4 = 303,75 - """ - - # we can add a filter on the Stakeholder concerned by the ebios study here - qs = Stakeholder.objects.all() - - c_data = {"clst1": [], "clst2": [], "clst3": [], "clst4": []} - r_data = {"clst1": [], "clst2": [], "clst3": [], "clst4": []} - angle_offsets = {"client": 135, "partner": 225, "supplier": 45} - - cnt_c_not_displayed = 0 - cnt_r_not_displayed = 0 - for sh in qs: - # current - c_reliability = sh.current_maturity * sh.current_trust - c_exposure = sh.current_dependency * sh.current_penetration - c_exposure_val = get_exposure_segment_id(c_exposure) * 4 - - c_criticality = ( - math.floor(sh.current_criticality * 100) / 100.0 - if sh.current_criticality <= 5 - else 5.25 - ) - - angle = angle_offsets[sh.category] + ( - get_exposure_segment_id(c_exposure) * (45 / 4) - ) - - vector = [c_criticality, angle, c_exposure_val, str(sh)] - - cluser_id = get_reliability_cluster(c_reliability) - c_data[cluser_id].append(vector) - - # residual - r_reliability = sh.residual_maturity * sh.residual_trust - r_exposure = sh.residual_dependency * sh.residual_penetration - r_exposure_val = get_exposure_segment_id(r_exposure) * 4 - - r_criticality = ( - math.floor(sh.residual_criticality * 100) / 100.0 - if sh.residual_criticality <= 5 - else 5.25 - ) - - angle = angle_offsets[sh.category] + ( - get_exposure_segment_id(r_exposure) * (45 / 4) - ) - - vector = [r_criticality, angle, r_exposure_val, str(sh)] - - cluser_id = get_reliability_cluster(r_reliability) - r_data[cluser_id].append(vector) - - return Response({"current": c_data, "residual": r_data}) + return Response(ecosystem_radar_chart_data(Stakeholder.objects.all())) class StrategicScenarioViewSet(BaseModelViewSet): diff --git a/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.server.ts b/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.server.ts index 33bf83000..64d567e47 100644 --- a/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.server.ts +++ b/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.server.ts @@ -85,7 +85,7 @@ export const load: PageServerLoad = async ({ params, fetch }) => { meta: data // metaData }; - const radarEndpoint = `${BASE_API_URL}/ebios-rm/stakeholders/chart_data/`; + const radarEndpoint = `${BASE_API_URL}/ebios-rm/studies/${params.id}/ecosystem_chart_data/`; const radarRes = await fetch(radarEndpoint); const radar = await radarRes.json(); diff --git a/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.svelte b/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.svelte index afc750bcb..f17ce5b7b 100644 --- a/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.svelte +++ b/frontend/src/routes/(app)/(internal)/ebios-rm/[id=uuid]/workshop-3/ecosystem/+page.svelte @@ -55,7 +55,7 @@
- + {m.ecosystemRadar()} diff --git a/frontend/src/routes/(app)/(internal)/experimental/ecosystem/+page.svelte b/frontend/src/routes/(app)/(internal)/experimental/ecosystem/+page.svelte index d7cc6d15f..cbdd62642 100644 --- a/frontend/src/routes/(app)/(internal)/experimental/ecosystem/+page.svelte +++ b/frontend/src/routes/(app)/(internal)/experimental/ecosystem/+page.svelte @@ -2,13 +2,14 @@ import type { PageData } from './$types'; export let data: PageData; import EcosystemRadarChart from '$lib/components/Chart/EcosystemRadarChart.svelte'; + import * as m from '$paraglide/messages.js';
- +