From e4e69bf2d5b70369b3990323dd137f071864d091 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 10:36:58 +0200 Subject: [PATCH 01/25] fix: risk remediation plan --- .../(app)/compliance-assessments/[id=uuid]/plan/+page.svelte | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 frontend/src/routes/(app)/compliance-assessments/[id=uuid]/plan/+page.svelte diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/plan/+page.svelte new file mode 100644 index 0000000000..e69de29bb2 From 9d4d2a1f189bc36a4f4d26cd2e092cdde3ebeeee Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 12:26:19 +0200 Subject: [PATCH 02/25] feat: add action plan button --- frontend/messages/en.json | 3 ++- .../[id=uuid]/+page.svelte | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index abb19b6678..a273e827d5 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -515,5 +515,6 @@ "selectedImplementationGroups": "Selected implementation groups", "implementationGroupsDefinition": "Implementation groups definition", "threatRadarChart": "Threat radar", - "noThreatsMapped": "No threats mapped. Consider attaching threats to your risk scenarios for a better overview." + "noThreatsMapped": "No threats mapped. Consider attaching threats to your risk scenarios for a better overview.", + "actionPlan": "Action plan" } diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte index 3218f48c91..b3fb0f3a36 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte @@ -181,17 +181,22 @@ colors={compliance_assessment_donut_values.values.map((object) => object.itemStyle.color)} /> -
- {m.exportButton()} - {#if canEditObject} - {m.edit()} +
+ {m.exportButton()} - {/if} + {#if canEditObject} + {m.edit()} + {/if} +
+ {m.actionPlan()}
From 6d1ce8a89d1c3c1f51949322623a603ac9578337 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 12:55:04 +0200 Subject: [PATCH 03/25] fix: remove useless info in remediation plan --- .../(app)/risk-assessments/[id=uuid]/plan/+page.server.ts | 7 ------- .../(app)/risk-assessments/[id=uuid]/plan/+page.svelte | 8 -------- 2 files changed, 15 deletions(-) diff --git a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.server.ts b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.server.ts index 0fa35ac4a0..4f4d044d82 100644 --- a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.server.ts +++ b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.server.ts @@ -8,12 +8,5 @@ export const load = (async ({ fetch, params }) => { const res = await fetch(endpoint); const risk_assessment = await res.json(); - const project = await fetch(`${BASE_API_URL}/projects/${risk_assessment.project.id}/`).then( - (res) => res.json() - ); - const folder = await fetch(`${BASE_API_URL}/folders/${project.folder.id}/`).then((res) => - res.json() - ); - risk_assessment.folder = folder; return { URLModel, risk_assessment }; }) satisfies PageServerLoad; diff --git a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte index a393597957..a47c427e4a 100644 --- a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte +++ b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte @@ -31,14 +31,6 @@
-

- {m.domain()}: - {data.risk_assessment.folder.name} -

-

/

{m.project()}: Date: Wed, 15 May 2024 13:02:34 +0200 Subject: [PATCH 04/25] fix: remediation plan measures --- .../risk-assessments/[id=uuid]/plan/+page.svelte | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte index a47c427e4a..1dac1ca133 100644 --- a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte +++ b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte @@ -17,10 +17,10 @@ const measureStatusColorMap = (treatment: string) => { const map: Record = { - open: 'bg-orange-200', - 'in progress': 'bg-blue-200', - 'on hold': 'bg-red-200', - done: 'bg-success-200' + '--': 'bg-gray-200', + 'planned': 'bg-blue-200', + 'inactive': 'bg-red-200', + active: 'bg-green-200' }; if (treatment !== null) { return map[treatment.toLowerCase()]; @@ -84,7 +84,7 @@ # {m.name()} {m.description()} - {m.type()} + {m.category()} {m.referenceControl()} {m.eta()} {m.effort()} @@ -99,7 +99,7 @@ M.{index + 1} {measure.name ?? '--'} {measure.description ?? '--'} - {measure.type ?? '--'} + {measure.category ?? '--'} {measure.reference_control ? measure.reference_control.str : '--'} @@ -109,9 +109,9 @@ {measure.status} + >{measure.status ?? '--'} From a8cbac9d468728f9384a02a248b460811ce18a1c Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 14:56:42 +0200 Subject: [PATCH 05/25] feat: prepare action plan UI --- .../[id=uuid]/action-plan/+page.server.ts | 12 ++++++ .../[id=uuid]/action-plan/+page.svelte | 40 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts create mode 100644 frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts new file mode 100644 index 0000000000..30f8443c9c --- /dev/null +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts @@ -0,0 +1,12 @@ +import { BASE_API_URL } from '$lib/utils/constants'; + +import type { PageServerLoad } from './$types'; + +export const load = (async ({ fetch, params }) => { + const URLModel = 'compliance-assessments'; + const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/`; + + const res = await fetch(endpoint); + const compliance_assessment = await res.json(); + return { URLModel, compliance_assessment }; +}) satisfies PageServerLoad; \ No newline at end of file diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte new file mode 100644 index 0000000000..46b6575ed5 --- /dev/null +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte @@ -0,0 +1,40 @@ + + +

+ +

{m.associatedRiskScenarios()}:

\ No newline at end of file From 2712e5adbcef2fffee3f9341bf7ca985facfe715 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 15:30:37 +0200 Subject: [PATCH 06/25] feat: prepare action plan API --- backend/core/models.py | 3 +++ backend/core/views.py | 27 +++++++++++++++++++ frontend/src/lib/utils/locales.ts | 3 ++- .../[id=uuid]/+page.svelte | 2 +- .../[id=uuid]/plan/+page.svelte | 0 5 files changed, 33 insertions(+), 2 deletions(-) delete mode 100644 frontend/src/routes/(app)/compliance-assessments/[id=uuid]/plan/+page.svelte diff --git a/backend/core/models.py b/backend/core/models.py index 73ff08b8ec..0ca553bdcc 100644 --- a/backend/core/models.py +++ b/backend/core/models.py @@ -1319,6 +1319,9 @@ def get_selected_implementation_groups(self): if group.get("ref_id") in self.selected_implementation_groups ] + def get_requirement_assessments(self): + return RequirementAssessment.objects.filter(compliance_assessment=self) + def get_requirements_status_count(self): requirements_status_count = [] for st in RequirementAssessment.Status: diff --git a/backend/core/views.py b/backend/core/views.py index bc70c85623..05349415d3 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -1188,6 +1188,33 @@ def selected_implementation_groups(self, request, pk): } return Response(implementation_group_choices) + @action(detail=True, methods=["get"], name="Get action plan data") + def action_plan(self, request, pk): + (viewable_objects, _, _) = RoleAssignment.get_accessible_object_ids( + folder=Folder.get_root_folder(), + user=request.user, + object_type=ComplianceAssessment, + ) + if UUID(pk) in viewable_objects: + response = {"planned": dict(), "active": dict(), "inactive": dict(), "none": dict()} + compliance_assessment_object = self.get_object() + requirement_assessments_objects = ( + compliance_assessment_object.get_requirement_assessments() + ) + applied_controls = AppliedControlReadSerializer( + AppliedControl.objects.filter( + requirement_assessments__in=requirement_assessments_objects + ), + many=True, + ).data + for applied_control in applied_controls: + response[applied_control["status"].lower()].update( + applied_control + ) if applied_control["status"] else response["none"].update( + applied_control + ) + return Response(response) + def perform_create(self, serializer): """ Create RequirementAssessment objects for the newly created ComplianceAssessment diff --git a/frontend/src/lib/utils/locales.ts b/frontend/src/lib/utils/locales.ts index 71ba70738c..849354c78a 100644 --- a/frontend/src/lib/utils/locales.ts +++ b/frontend/src/lib/utils/locales.ts @@ -334,7 +334,8 @@ export function localItems(languageTag: string): LocalItems { }), attemptToRemoveOnlyAdminUserGroup: m.attemptToRemoveOnlyAdminUserGroup({ languageTag: languageTag - }) + }), + actionPlan: m.actionPlan({ languageTag: languageTag }), }; return LOCAL_ITEMS; } diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte index b3fb0f3a36..69bd1421f2 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte @@ -194,7 +194,7 @@ > {/if}
- {m.actionPlan()} diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/plan/+page.svelte deleted file mode 100644 index e69de29bb2..0000000000 From 12d52ff1734c93a5774a0a29ef8ebc2a8566ca3f Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 17:16:24 +0200 Subject: [PATCH 07/25] feat: add audit action plan --- backend/core/views.py | 16 ++- frontend/messages/en.json | 5 +- frontend/messages/fr.json | 4 +- frontend/src/lib/utils/locales.ts | 1 + .../[id=uuid]/action-plan/+page.server.ts | 5 +- .../[id=uuid]/action-plan/+page.svelte | 136 ++++++++++++++++-- 6 files changed, 142 insertions(+), 25 deletions(-) diff --git a/backend/core/views.py b/backend/core/views.py index 05349415d3..dce44f5935 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -1196,7 +1196,12 @@ def action_plan(self, request, pk): object_type=ComplianceAssessment, ) if UUID(pk) in viewable_objects: - response = {"planned": dict(), "active": dict(), "inactive": dict(), "none": dict()} + response = { + "planned": list(), + "active": list(), + "inactive": list(), + "none": list(), + } compliance_assessment_object = self.get_object() requirement_assessments_objects = ( compliance_assessment_object.get_requirement_assessments() @@ -1204,15 +1209,14 @@ def action_plan(self, request, pk): applied_controls = AppliedControlReadSerializer( AppliedControl.objects.filter( requirement_assessments__in=requirement_assessments_objects - ), + ).distinct(), many=True, ).data for applied_control in applied_controls: - response[applied_control["status"].lower()].update( - applied_control - ) if applied_control["status"] else response["none"].update( + applied_control["requirements_count"] = RequirementAssessment.objects.filter(compliance_assessment=compliance_assessment_object).filter(applied_controls=applied_control["id"]).count() + response[applied_control["status"].lower()].append( applied_control - ) + ) if applied_control["status"] else response["none"].append(applied_control) return Response(response) def perform_create(self, serializer): diff --git a/frontend/messages/en.json b/frontend/messages/en.json index a273e827d5..a9aecab193 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -516,5 +516,8 @@ "implementationGroupsDefinition": "Implementation groups definition", "threatRadarChart": "Threat radar", "noThreatsMapped": "No threats mapped. Consider attaching threats to your risk scenarios for a better overview.", - "actionPlan": "Action plan" + "actionPlan": "Action plan", + "noStatus": "No status", + "actionPlanHelpText": "Separated by status and sorted by eta", + "requirementsCount": "Requirements count" } diff --git a/frontend/messages/fr.json b/frontend/messages/fr.json index 054a35e362..bf8a1d3b76 100644 --- a/frontend/messages/fr.json +++ b/frontend/messages/fr.json @@ -164,8 +164,8 @@ "currentRisk": "Risque courant", "residualRisk": "Risque résiduel", "planned": "Planifié", - "active": "Active", - "inactive": "Inactive", + "active": "Actif", + "inactive": "Inactif", "watchlist": "Liste de surveillance", "watchlistDescription": "Objets expirés ou expirant bientôt", "measuresToReview": "Mesures à revoir", diff --git a/frontend/src/lib/utils/locales.ts b/frontend/src/lib/utils/locales.ts index 849354c78a..6722f27ae2 100644 --- a/frontend/src/lib/utils/locales.ts +++ b/frontend/src/lib/utils/locales.ts @@ -336,6 +336,7 @@ export function localItems(languageTag: string): LocalItems { languageTag: languageTag }), actionPlan: m.actionPlan({ languageTag: languageTag }), + requirementsCount: m.requirementsCount({ languageTag: languageTag }), }; return LOCAL_ITEMS; } diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts index 30f8443c9c..7b2360ca0f 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts @@ -5,8 +5,11 @@ import type { PageServerLoad } from './$types'; export const load = (async ({ fetch, params }) => { const URLModel = 'compliance-assessments'; const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/`; + const actionPlanEndpoint = `${BASE_API_URL}/${URLModel}/${params.id}/action_plan/`; const res = await fetch(endpoint); + const actionPlanRes = await fetch(actionPlanEndpoint); const compliance_assessment = await res.json(); - return { URLModel, compliance_assessment }; + const actionPlan = await actionPlanRes.json(); + return { URLModel, compliance_assessment, actionPlan }; }) satisfies PageServerLoad; \ No newline at end of file diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte index 46b6575ed5..f50fe90ad1 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte @@ -1,24 +1,67 @@ -
+

{m.project()}:

- -

{m.associatedRiskScenarios()}:

\ No newline at end of file +
+
+

{m.associatedAppliedControls()}

+

+ {m.actionPlanHelpText()} +

+
+
+ + {m.planned()} + {m.active()} + {m.inactive()} + {m.noStatus()} + +
+ {#if tabSet === 0} + + {/if} + {#if tabSet === 1} + + {/if} + {#if tabSet === 2} + + {/if} + {#if tabSet === 3} + + {/if} +
+
+
+
+ +
From 9bee2ac317af2701f2bf1a3a912b93002c41eba5 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 17:18:46 +0200 Subject: [PATCH 08/25] chore: run format --- backend/core/views.py | 12 +- frontend/src/lib/utils/locales.ts | 2 +- .../[id=uuid]/+page.svelte | 2 +- .../[id=uuid]/action-plan/+page.server.ts | 8 +- .../[id=uuid]/action-plan/+page.svelte | 236 ++++++++++-------- .../[id=uuid]/plan/+page.svelte | 4 +- 6 files changed, 146 insertions(+), 118 deletions(-) diff --git a/backend/core/views.py b/backend/core/views.py index dce44f5935..3b63a2bb00 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -1213,10 +1213,18 @@ def action_plan(self, request, pk): many=True, ).data for applied_control in applied_controls: - applied_control["requirements_count"] = RequirementAssessment.objects.filter(compliance_assessment=compliance_assessment_object).filter(applied_controls=applied_control["id"]).count() + applied_control["requirements_count"] = ( + RequirementAssessment.objects.filter( + compliance_assessment=compliance_assessment_object + ) + .filter(applied_controls=applied_control["id"]) + .count() + ) response[applied_control["status"].lower()].append( applied_control - ) if applied_control["status"] else response["none"].append(applied_control) + ) if applied_control["status"] else response["none"].append( + applied_control + ) return Response(response) def perform_create(self, serializer): diff --git a/frontend/src/lib/utils/locales.ts b/frontend/src/lib/utils/locales.ts index 6722f27ae2..44ec410b88 100644 --- a/frontend/src/lib/utils/locales.ts +++ b/frontend/src/lib/utils/locales.ts @@ -336,7 +336,7 @@ export function localItems(languageTag: string): LocalItems { languageTag: languageTag }), actionPlan: m.actionPlan({ languageTag: languageTag }), - requirementsCount: m.requirementsCount({ languageTag: languageTag }), + requirementsCount: m.requirementsCount({ languageTag: languageTag }) }; return LOCAL_ITEMS; } diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte index 69bd1421f2..e96ee0975f 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte @@ -195,7 +195,7 @@ {/if}
{m.actionPlan()}{m.actionPlan()} diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts index 7b2360ca0f..b625af9820 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.server.ts @@ -5,11 +5,11 @@ import type { PageServerLoad } from './$types'; export const load = (async ({ fetch, params }) => { const URLModel = 'compliance-assessments'; const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/`; - const actionPlanEndpoint = `${BASE_API_URL}/${URLModel}/${params.id}/action_plan/`; + const actionPlanEndpoint = `${BASE_API_URL}/${URLModel}/${params.id}/action_plan/`; const res = await fetch(endpoint); - const actionPlanRes = await fetch(actionPlanEndpoint); + const actionPlanRes = await fetch(actionPlanEndpoint); const compliance_assessment = await res.json(); - const actionPlan = await actionPlanRes.json(); + const actionPlan = await actionPlanRes.json(); return { URLModel, compliance_assessment, actionPlan }; -}) satisfies PageServerLoad; \ No newline at end of file +}) satisfies PageServerLoad; diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte index f50fe90ad1..bab9322deb 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte @@ -6,59 +6,87 @@ export let data; - let tabSet = 0; + let tabSet = 0; - const plannedAppliedControls: TableSource = { + const plannedAppliedControls: TableSource = { head: { name: 'name', category: 'category', eta: 'eta', - expiry_date: 'expiryDate', - effort: 'effort', - requirements_count: 'requirementsCount' + expiry_date: 'expiryDate', + effort: 'effort', + requirements_count: 'requirementsCount' }, - body: tableSourceMapper(data.actionPlan.planned, ['name', 'category', 'eta', 'expiry_date', 'efforts', 'requirements_count']), - meta: data.actionPlan.planned, + body: tableSourceMapper(data.actionPlan.planned, [ + 'name', + 'category', + 'eta', + 'expiry_date', + 'efforts', + 'requirements_count' + ]), + meta: data.actionPlan.planned }; - - const activeAppliedControls: TableSource = { - head: { - name: 'name', - category: 'category', - eta: 'eta', - expiry_date: 'expiryDate', - effort: 'effort', - requirements_count: 'requirementsCount' - }, - body: tableSourceMapper(data.actionPlan.active, ['name', 'category', 'eta', 'expiry_date', 'efforts', 'requirements_count']), - meta: data.actionPlan.active, - }; - const inactiveAppliedControls: TableSource = { - head: { - name: 'name', - category: 'category', - eta: 'eta', - expiry_date: 'expiryDate', - effort: 'effort', - requirements_count: 'requirementsCount' - }, - body: tableSourceMapper(data.actionPlan.inactive, ['name', 'category', 'eta', 'expiry_date', 'efforts', 'requirements_count']), - meta: data.actionPlan.inactive, - }; + const activeAppliedControls: TableSource = { + head: { + name: 'name', + category: 'category', + eta: 'eta', + expiry_date: 'expiryDate', + effort: 'effort', + requirements_count: 'requirementsCount' + }, + body: tableSourceMapper(data.actionPlan.active, [ + 'name', + 'category', + 'eta', + 'expiry_date', + 'efforts', + 'requirements_count' + ]), + meta: data.actionPlan.active + }; - const noneAppliedControls: TableSource = { - head: { - name: 'name', - category: 'category', - eta: 'eta', - expiry_date: 'expiryDate', - effort: 'effort', - requirements_count: 'requirementsCount' - }, - body: tableSourceMapper(data.actionPlan.none, ['name', 'category', 'eta', 'expiry_date', 'efforts', 'requirements_count']), - meta: data.actionPlan.none, - }; + const inactiveAppliedControls: TableSource = { + head: { + name: 'name', + category: 'category', + eta: 'eta', + expiry_date: 'expiryDate', + effort: 'effort', + requirements_count: 'requirementsCount' + }, + body: tableSourceMapper(data.actionPlan.inactive, [ + 'name', + 'category', + 'eta', + 'expiry_date', + 'efforts', + 'requirements_count' + ]), + meta: data.actionPlan.inactive + }; + + const noneAppliedControls: TableSource = { + head: { + name: 'name', + category: 'category', + eta: 'eta', + expiry_date: 'expiryDate', + effort: 'effort', + requirements_count: 'requirementsCount' + }, + body: tableSourceMapper(data.actionPlan.none, [ + 'name', + 'category', + 'eta', + 'expiry_date', + 'efforts', + 'requirements_count' + ]), + meta: data.actionPlan.none + };
@@ -66,7 +94,8 @@ {m.project()}: {data.compliance_assessment.project.str}{data.compliance_assessment.project.str}

/

@@ -80,67 +109,58 @@

-
-

{m.associatedAppliedControls()}

-

- {m.actionPlanHelpText()} -

-
-
- - {m.planned()} - {m.active()} - {m.inactive()} - {m.noStatus()} - -
- {#if tabSet === 0} - - {/if} - {#if tabSet === 1} - - {/if} - {#if tabSet === 2} - - {/if} - {#if tabSet === 3} - - {/if} -
-
-
-
- +
+

{m.associatedAppliedControls()}

+

+ {m.actionPlanHelpText()} +

+
+
+ + {m.planned()} + {m.active()} + {m.inactive()} + {m.noStatus()} + +
+ {#if tabSet === 0} + + {/if} + {#if tabSet === 1} + + {/if} + {#if tabSet === 2} + + {/if} + {#if tabSet === 3} + + {/if} +
+
+
+
diff --git a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte index 1dac1ca133..ca86602caa 100644 --- a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte +++ b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/plan/+page.svelte @@ -18,8 +18,8 @@ const measureStatusColorMap = (treatment: string) => { const map: Record = { '--': 'bg-gray-200', - 'planned': 'bg-blue-200', - 'inactive': 'bg-red-200', + planned: 'bg-blue-200', + inactive: 'bg-red-200', active: 'bg-green-200' }; if (treatment !== null) { From 71e8ff02837c2d9485a0af6ddf50b5b17f16569d Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 18:57:57 +0200 Subject: [PATCH 09/25] feat: create action plan pdf --- .../core/templates/core/action_plan_pdf.html | 60 +++++++++++++++++++ backend/core/templatetags/core_extras.py | 7 +++ backend/core/views.py | 43 +++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 backend/core/templates/core/action_plan_pdf.html diff --git a/backend/core/templates/core/action_plan_pdf.html b/backend/core/templates/core/action_plan_pdf.html new file mode 100644 index 0000000000..875c2dfd52 --- /dev/null +++ b/backend/core/templates/core/action_plan_pdf.html @@ -0,0 +1,60 @@ +{% extends 'core/base_pdf.html' %} +{% block content %} +{% load i18n core_extras %} + + + +
+

Action plan

+
+

{% trans "Domain" %}: {{ compliance_assessment.project.folder }}

+

/

+

{% trans "Project" %}: {{ compliance_assessment.project.name }}

+

/

+

{% trans "Audit" %}: {{ compliance_assessment.name }} - {{ compliance_assessment.version }}

+
+

{% trans "Associated applied controls" %}:

+

{% trans "Separated by status and sorted by eta" %}

+ {% for status, applied_controls in context.items%} + {% for status_color, color in color_map.items %} + {% if status_color == status %} +

{% trans status|title %}:

+ {% endif %} + {% endfor %} +
+
+ + + + + + + + + + + + + + {% for applied_control in applied_controls %} + + + + + + + + + + {% endfor %} + +
{% trans "Name" %}{% trans "Description" %}{% trans "Category" %}{% trans "ETA" %}{% trans "Expiry date" %}{% trans "Effort" %}{% trans "Requirements count" %}
{{ applied_control.name }}{{ applied_control.description }}{{ applied_control.category }}{{ applied_control.eta }}{{ applied_control.expiry_date }}{{ applied_control.effort }}{% get_requirements_count applied_control compliance_assessment %}
+
+
+ {% endfor %} +
+{% endblock %} diff --git a/backend/core/templatetags/core_extras.py b/backend/core/templatetags/core_extras.py index 0aebc1e5b6..90f0691974 100644 --- a/backend/core/templatetags/core_extras.py +++ b/backend/core/templatetags/core_extras.py @@ -2,6 +2,7 @@ from ciso_assistant.settings import VERSION, BUILD, DEBUG from core.utils import COUNTRY_FLAGS, LANGUAGES +from core.models import RequirementAssessment register = template.Library() @@ -15,6 +16,12 @@ def app_version(): def app_build(): return f"{BUILD} (dev)" if DEBUG else BUILD +@register.simple_tag() +def get_requirements_count(applied_control, compliance_assessment): + return RequirementAssessment.objects.filter( + compliance_assessment=compliance_assessment + ).filter(applied_controls=applied_control).count() + @register.filter("class") def _class(obj): diff --git a/backend/core/views.py b/backend/core/views.py index 3b63a2bb00..64a8ceb89f 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -1226,6 +1226,49 @@ def action_plan(self, request, pk): applied_control ) return Response(response) + + @action(detail=True, name="Get action plan PDF") + def action_plan_pdf(self, request, pk): + (object_ids_view, _, _) = RoleAssignment.get_accessible_object_ids( + Folder.get_root_folder(), request.user, ComplianceAssessment + ) + if UUID(pk) in object_ids_view: + context = { + "planned": list(), + "active": list(), + "inactive": list(), + "no status": list(), + } + color_map = { + "planned": "#93c5fd", + "active": "#86efac", + "inactive": "#fca5a5", + "no status": "#e5e7eb", + } + compliance_assessment_object = self.get_object() + requirement_assessments_objects = ( + compliance_assessment_object.get_requirement_assessments() + ) + applied_controls = AppliedControl.objects.filter( + requirement_assessments__in=requirement_assessments_objects + ).distinct().order_by("eta") + for applied_control in applied_controls: + context[applied_control.status].append( + applied_control + ) if applied_control.status else context["no status"].append( + applied_control + ) + data = { + "color_map": color_map, + "context": context, + "compliance_assessment": compliance_assessment_object, + } + html = render_to_string("core/action_plan_pdf.html", data) + pdf_file = HTML(string=html).write_pdf() + response = HttpResponse(pdf_file, content_type="application/pdf") + return response + else: + return Response({"error": "Permission denied"}) def perform_create(self, serializer): """ From 880f2b1332dfcea7b5e422d3ce6bade8ba85c78e Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 19:13:12 +0200 Subject: [PATCH 10/25] feat: add frontend export function --- .../core/templates/core/action_plan_pdf.html | 2 ++ frontend/messages/en.json | 3 +- .../[id=uuid]/+page.svelte | 28 +++++++++++++++++-- .../[id=uuid]/action-plan/+page.svelte | 9 ++++++ .../action-plan/export/pdf/+server.ts | 22 +++++++++++++++ 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/export/pdf/+server.ts diff --git a/backend/core/templates/core/action_plan_pdf.html b/backend/core/templates/core/action_plan_pdf.html index 875c2dfd52..11c3d3ac86 100644 --- a/backend/core/templates/core/action_plan_pdf.html +++ b/backend/core/templates/core/action_plan_pdf.html @@ -16,6 +16,8 @@

Action plan

{% trans "Project" %}: {{ compliance_assessment.project.name }}

/

{% trans "Audit" %}: {{ compliance_assessment.name }} - {{ compliance_assessment.version }}

+

/

+

{% trans "Framework" %}: {{ compliance_assessment.framework }}

{% trans "Associated applied controls" %}:

{% trans "Separated by status and sorted by eta" %}

diff --git a/frontend/messages/en.json b/frontend/messages/en.json index a9aecab193..16cd0cd8f7 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -519,5 +519,6 @@ "actionPlan": "Action plan", "noStatus": "No status", "actionPlanHelpText": "Separated by status and sorted by eta", - "requirementsCount": "Requirements count" + "requirementsCount": "Requirements count", + "asZIP": "as ZIP" } diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte index e96ee0975f..8ac67b039a 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte @@ -2,7 +2,8 @@ import { page } from '$app/stores'; import RecursiveTreeView from '$lib/components/TreeView/RecursiveTreeView.svelte'; import { breadcrumbObject } from '$lib/utils/stores'; - import type { TreeViewNode } from '@skeletonlabs/skeleton'; + import type { PopupSettings, TreeViewNode } from '@skeletonlabs/skeleton'; + import { popup } from '@skeletonlabs/skeleton'; import type { PageData } from './$types'; import TreeViewItemContent from './TreeViewItemContent.svelte'; import TreeViewItemLead from './TreeViewItemLead.svelte'; @@ -103,6 +104,12 @@ expandedNodes = $expandedNodesState; $: expandedNodesState.set(expandedNodes); + + const popupDownload: PopupSettings = { + event: 'click', + target: 'popupDownload', + placement: 'bottom' + };
@@ -183,9 +190,24 @@
- {m.exportButton()}{m.exportButton()} +
+

{m.complianceAssessment()}

+ ... {m.asZIP()} +

{m.actionPlan()}

+ ... {m.asPDF()} +
{#if canEditObject} {data.compliance_assessment.name} - {data.compliance_assessment.version}

+

/

+

+ {m.framework()}: + {data.compliance_assessment.framework.str} +

diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/export/pdf/+server.ts b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/export/pdf/+server.ts new file mode 100644 index 0000000000..41a8d50ed5 --- /dev/null +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/export/pdf/+server.ts @@ -0,0 +1,22 @@ +import { BASE_API_URL } from '$lib/utils/constants'; + +import { error } from '@sveltejs/kit'; +import type { RequestHandler } from './$types'; +export const GET: RequestHandler = async ({ fetch, params }) => { + const URLModel = 'compliance-assessments'; + const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/action_plan_pdf/`; + + const res = await fetch(endpoint); + if (!res.ok) { + error(400, 'Error fetching the PDF file'); + } + + const fileName = `AP-${params.id}-${new Date().toISOString()}.pdf`; + + return new Response(await res.blob(), { + headers: { + 'Content-Type': 'text/pdf', + 'Content-Disposition': `attachment; filename="${fileName}"` + } + }); +}; From f963edba863f9cd8097e6ff54bbb459c6549bb28 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene <90701924+Mohamed-Hacene@users.noreply.github.com> Date: Wed, 15 May 2024 19:15:22 +0200 Subject: [PATCH 11/25] =?UTF-8?q?chore:=20update=20translations=20with=20F?= =?UTF-8?q?ink=20=F0=9F=90=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/messages/fr.json | 7 ++++++- frontend/messages/pt.json | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/frontend/messages/fr.json b/frontend/messages/fr.json index bf8a1d3b76..6be6342844 100644 --- a/frontend/messages/fr.json +++ b/frontend/messages/fr.json @@ -515,5 +515,10 @@ "selectedImplementationGroups": "Groupes d'implémentation sélectionnés", "implementationGroupsDefinition": "Définition des groupes d'implémentation", "threatRadarChart": "Radar des menaces", - "noThreatsMapped": "Aucune menace n'a été attachée. Pensez à lier les menaces à vos scénarios de risque pour une meilleure visibilité." + "noThreatsMapped": "Aucune menace n'a été attachée. Pensez à lier les menaces à vos scénarios de risque pour une meilleure visibilité.", + "actionPlan": "Plan d'action", + "noStatus": "Pas de statut", + "actionPlanHelpText": "Séparé par statut et trié par eta", + "requirementsCount": "Nombre d'exigences", + "asZIP": "en ZIP" } diff --git a/frontend/messages/pt.json b/frontend/messages/pt.json index d55fc2e418..971a5d17c5 100644 --- a/frontend/messages/pt.json +++ b/frontend/messages/pt.json @@ -515,5 +515,10 @@ "selectedImplementationGroups": "Grupos de implementação selecionados", "implementationGroupsDefinition": "Definição de grupos de implementação", "threatRadarChart": "Radar de ameaças", - "noThreatsMapped": "Nenhuma ameaça mapeada. Considere anexar ameaças aos seus cenários de risco para ter uma visão geral melhor." + "noThreatsMapped": "Nenhuma ameaça mapeada. Considere anexar ameaças aos seus cenários de risco para ter uma visão geral melhor.", + "actionPlan": "Plano de ação", + "noStatus": "Sem status", + "actionPlanHelpText": "Separados por status e classificados por eta", + "requirementsCount": "Contagem de requisitos", + "asZIP": "em ZIP" } From bf0b73728a84781f130f257332b677a4b531fd2e Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Wed, 15 May 2024 19:18:37 +0200 Subject: [PATCH 12/25] chore: run ruff format --- backend/core/templatetags/core_extras.py | 11 ++++++++--- backend/core/views.py | 10 +++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/backend/core/templatetags/core_extras.py b/backend/core/templatetags/core_extras.py index 90f0691974..8fa6edbc5a 100644 --- a/backend/core/templatetags/core_extras.py +++ b/backend/core/templatetags/core_extras.py @@ -16,11 +16,16 @@ def app_version(): def app_build(): return f"{BUILD} (dev)" if DEBUG else BUILD + @register.simple_tag() def get_requirements_count(applied_control, compliance_assessment): - return RequirementAssessment.objects.filter( - compliance_assessment=compliance_assessment - ).filter(applied_controls=applied_control).count() + return ( + RequirementAssessment.objects.filter( + compliance_assessment=compliance_assessment + ) + .filter(applied_controls=applied_control) + .count() + ) @register.filter("class") diff --git a/backend/core/views.py b/backend/core/views.py index 64a8ceb89f..1ff753f9c8 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -1226,7 +1226,7 @@ def action_plan(self, request, pk): applied_control ) return Response(response) - + @action(detail=True, name="Get action plan PDF") def action_plan_pdf(self, request, pk): (object_ids_view, _, _) = RoleAssignment.get_accessible_object_ids( @@ -1249,9 +1249,13 @@ def action_plan_pdf(self, request, pk): requirement_assessments_objects = ( compliance_assessment_object.get_requirement_assessments() ) - applied_controls = AppliedControl.objects.filter( + applied_controls = ( + AppliedControl.objects.filter( requirement_assessments__in=requirement_assessments_objects - ).distinct().order_by("eta") + ) + .distinct() + .order_by("eta") + ) for applied_control in applied_controls: context[applied_control.status].append( applied_control From 68733f0962b1fef6782094b8babfa3e717dd3389 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 10:47:08 +0200 Subject: [PATCH 13/25] locale: update translation --- frontend/messages/en.json | 2 +- frontend/messages/fr.json | 2 +- frontend/messages/pt.json | 2 +- frontend/src/lib/utils/locales.ts | 2 +- .../[id=uuid]/action-plan/+page.svelte | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 5f26abbb86..2b8ef43bc6 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -519,6 +519,6 @@ "actionPlan": "Action plan", "noStatus": "No status", "actionPlanHelpText": "Separated by status and sorted by eta", - "requirementsCount": "Requirements count", + "matchingRequirements": "Matching requirements", "asZIP": "as ZIP" } diff --git a/frontend/messages/fr.json b/frontend/messages/fr.json index 56742b8fa1..a5f55419d3 100644 --- a/frontend/messages/fr.json +++ b/frontend/messages/fr.json @@ -519,6 +519,6 @@ "actionPlan": "Plan d'action", "noStatus": "Pas de statut", "actionPlanHelpText": "Séparé par statut et trié par eta", - "requirementsCount": "Nombre d'exigences", + "matchingRequirements": "Exigences associées", "asZIP": "en ZIP" } diff --git a/frontend/messages/pt.json b/frontend/messages/pt.json index eacaa18ec9..6d4518e68b 100644 --- a/frontend/messages/pt.json +++ b/frontend/messages/pt.json @@ -519,6 +519,6 @@ "actionPlan": "Plano de ação", "noStatus": "Sem status", "actionPlanHelpText": "Separados por status e classificados por eta", - "requirementsCount": "Contagem de requisitos", + "matchingRequirements": "Requisitos correspondentes", "asZIP": "em ZIP" } diff --git a/frontend/src/lib/utils/locales.ts b/frontend/src/lib/utils/locales.ts index 44ec410b88..441fd4463f 100644 --- a/frontend/src/lib/utils/locales.ts +++ b/frontend/src/lib/utils/locales.ts @@ -336,7 +336,7 @@ export function localItems(languageTag: string): LocalItems { languageTag: languageTag }), actionPlan: m.actionPlan({ languageTag: languageTag }), - requirementsCount: m.requirementsCount({ languageTag: languageTag }) + matchingRequirements: m.matchingRequirements({ languageTag: languageTag }) }; return LOCAL_ITEMS; } diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte index 919ab2189f..681194eced 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte @@ -15,7 +15,7 @@ eta: 'eta', expiry_date: 'expiryDate', effort: 'effort', - requirements_count: 'requirementsCount' + requirements_count: 'matchingRequirements' }, body: tableSourceMapper(data.actionPlan.planned, [ 'name', @@ -35,7 +35,7 @@ eta: 'eta', expiry_date: 'expiryDate', effort: 'effort', - requirements_count: 'requirementsCount' + requirements_count: 'matchingRequirements' }, body: tableSourceMapper(data.actionPlan.active, [ 'name', @@ -55,7 +55,7 @@ eta: 'eta', expiry_date: 'expiryDate', effort: 'effort', - requirements_count: 'requirementsCount' + requirements_count: 'matchingRequirements' }, body: tableSourceMapper(data.actionPlan.inactive, [ 'name', @@ -75,7 +75,7 @@ eta: 'eta', expiry_date: 'expiryDate', effort: 'effort', - requirements_count: 'requirementsCount' + requirements_count: 'matchingRequirements' }, body: tableSourceMapper(data.actionPlan.none, [ 'name', From e5c473ee1263ab52a246a44f8d5c5d561ebadc2a Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 10:48:34 +0200 Subject: [PATCH 14/25] localization: update action pdf --- backend/core/templates/core/action_plan_pdf.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/core/templates/core/action_plan_pdf.html b/backend/core/templates/core/action_plan_pdf.html index 11c3d3ac86..c38b7ed398 100644 --- a/backend/core/templates/core/action_plan_pdf.html +++ b/backend/core/templates/core/action_plan_pdf.html @@ -38,7 +38,7 @@

Action plan

{% trans "ETA" %} {% trans "Expiry date" %} {% trans "Effort" %} - {% trans "Requirements count" %} + {% trans "Matching requirements" %} From 3daaae9c00814507b72d5317b175f402a0c8f8f7 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 11:20:03 +0200 Subject: [PATCH 15/25] style: improve action plan modeltables --- .../src/lib/components/ModelTable/ModelTable.svelte | 3 ++- .../[id=uuid]/action-plan/+page.svelte | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/frontend/src/lib/components/ModelTable/ModelTable.svelte b/frontend/src/lib/components/ModelTable/ModelTable.svelte index a1c3942d70..5a91077d11 100644 --- a/frontend/src/lib/components/ModelTable/ModelTable.svelte +++ b/frontend/src/lib/components/ModelTable/ModelTable.svelte @@ -36,6 +36,7 @@ export let pagination = true; export let numberRowsPerPage = 10; export let thFiler = false; + export let tags = true; export let orderBy: { identifier: string; direction: 'asc' | 'desc' } | undefined = undefined; @@ -203,7 +204,7 @@ {@const tagList = Array.isArray(_tagList) ? _tagList : [_tagList]} {#each tagList as tag} {@const tagData = tag.values[meta[tag.key]]} - {#if tagData} + {#if tagData && tags} {@const {text, cssClasses} = tagData} {localItems(languageTag())[text]} diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte index 681194eced..2521a04312 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte @@ -126,10 +126,10 @@
- {m.planned()} - {m.active()} - {m.inactive()} - {m.noStatus()} + {m.planned()} + {m.active()} + {m.inactive()} + {m.noStatus()}
{#if tabSet === 0} @@ -139,6 +139,7 @@ search={true} rowsPerPage={true} orderBy={{ identifier: 'eta', direction: 'desc' }} + tags={false} /> {/if} {#if tabSet === 1} @@ -148,6 +149,7 @@ search={true} rowsPerPage={true} orderBy={{ identifier: 'eta', direction: 'desc' }} + tags={false} /> {/if} {#if tabSet === 2} @@ -157,6 +159,7 @@ search={true} rowsPerPage={true} orderBy={{ identifier: 'eta', direction: 'desc' }} + tags={false} /> {/if} {#if tabSet === 3} @@ -166,6 +169,7 @@ search={true} rowsPerPage={true} orderBy={{ identifier: 'eta', direction: 'desc' }} + tags={false} /> {/if}
From 97cf195f89be3b6fe6a4b525b1ff1efee358460f Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 11:24:32 +0200 Subject: [PATCH 16/25] chore: run format --- .../[id=uuid]/action-plan/+page.svelte | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte index 2521a04312..c1cb4f90af 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte @@ -126,10 +126,34 @@
- {m.planned()} - {m.active()} - {m.inactive()} - {m.noStatus()} + {m.planned()} + {m.active()} + {m.inactive()} + {m.noStatus()}
{#if tabSet === 0} From f442f2e2e5889cba796ad7346fe22c64b1656c28 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 11:30:04 +0200 Subject: [PATCH 17/25] feat: add empty case in action plan pdf --- backend/core/templates/core/action_plan_pdf.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/core/templates/core/action_plan_pdf.html b/backend/core/templates/core/action_plan_pdf.html index c38b7ed398..369900d928 100644 --- a/backend/core/templates/core/action_plan_pdf.html +++ b/backend/core/templates/core/action_plan_pdf.html @@ -52,6 +52,12 @@

Action plan

{{ applied_control.effort }} {% get_requirements_count applied_control compliance_assessment %} + {% empty %} + + +

{% trans "No entries found" %}

+ + {% endfor %} From debf73aa036afd43654f12230d11e12770986814 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 11:36:12 +0200 Subject: [PATCH 18/25] style: improve action plan pdf --- backend/core/templates/core/action_plan_pdf.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/core/templates/core/action_plan_pdf.html b/backend/core/templates/core/action_plan_pdf.html index 369900d928..53efae1bab 100644 --- a/backend/core/templates/core/action_plan_pdf.html +++ b/backend/core/templates/core/action_plan_pdf.html @@ -20,7 +20,7 @@

Action plan

{% trans "Framework" %}: {{ compliance_assessment.framework }}

{% trans "Associated applied controls" %}:

-

{% trans "Separated by status and sorted by eta" %}

+

{% trans "Separated by status and sorted by eta" %}

{% for status, applied_controls in context.items%} {% for status_color, color in color_map.items %} {% if status_color == status %} From 0cf6bf9293b88efa991d28127e0275464d598402 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 11:51:51 +0200 Subject: [PATCH 19/25] ci/cd: fix functional tests --- .github/workflows/functional-tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/functional-tests.yml b/.github/workflows/functional-tests.yml index 829891c61a..3b9b3482be 100644 --- a/.github/workflows/functional-tests.yml +++ b/.github/workflows/functional-tests.yml @@ -54,7 +54,9 @@ jobs: if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Install dependencies working-directory: ${{ env.working-directory }} - run: npm ci + run: | + npm install + npm ci - name: Install Playwright Browsers working-directory: ${{ env.working-directory }} run: npx playwright install --with-deps From e1cde1a3f3238bc00fbc33a03177c5d47e6a2328 Mon Sep 17 00:00:00 2001 From: Mohamed-Hacene Date: Thu, 16 May 2024 12:16:07 +0200 Subject: [PATCH 20/25] fix: breadcrumbs and title in plans --- frontend/src/lib/utils/locales.ts | 3 ++- frontend/src/routes/(app)/analyses-registry/+page.svelte | 6 +++--- .../[id=uuid]/action-plan/+page.svelte | 3 +++ .../routes/(app)/risk-assessments/[id=uuid]/+page.svelte | 6 +++--- .../[id=uuid]/{plan => remediation-plan}/+page.server.ts | 0 .../[id=uuid]/{plan => remediation-plan}/+page.svelte | 3 +++ .../{plan => remediation-plan}/export/csv/+server.ts | 0 .../{plan => remediation-plan}/export/pdf/+server.ts | 0 8 files changed, 14 insertions(+), 7 deletions(-) rename frontend/src/routes/(app)/risk-assessments/[id=uuid]/{plan => remediation-plan}/+page.server.ts (100%) rename frontend/src/routes/(app)/risk-assessments/[id=uuid]/{plan => remediation-plan}/+page.svelte (97%) rename frontend/src/routes/(app)/risk-assessments/[id=uuid]/{plan => remediation-plan}/export/csv/+server.ts (100%) rename frontend/src/routes/(app)/risk-assessments/[id=uuid]/{plan => remediation-plan}/export/pdf/+server.ts (100%) diff --git a/frontend/src/lib/utils/locales.ts b/frontend/src/lib/utils/locales.ts index 441fd4463f..f939759bba 100644 --- a/frontend/src/lib/utils/locales.ts +++ b/frontend/src/lib/utils/locales.ts @@ -336,7 +336,8 @@ export function localItems(languageTag: string): LocalItems { languageTag: languageTag }), actionPlan: m.actionPlan({ languageTag: languageTag }), - matchingRequirements: m.matchingRequirements({ languageTag: languageTag }) + matchingRequirements: m.matchingRequirements({ languageTag: languageTag }), + remediationPlan: m.remediationPlan({ languageTag: languageTag }), }; return LOCAL_ITEMS; } diff --git a/frontend/src/routes/(app)/analyses-registry/+page.svelte b/frontend/src/routes/(app)/analyses-registry/+page.svelte index d16d602052..7658ab2d51 100644 --- a/frontend/src/routes/(app)/analyses-registry/+page.svelte +++ b/frontend/src/routes/(app)/analyses-registry/+page.svelte @@ -23,7 +23,7 @@ @@ -49,12 +49,12 @@ >

Treatment plan

... as PDF ... as csv diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte index c1cb4f90af..8efd5bde6b 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/action-plan/+page.svelte @@ -3,9 +3,12 @@ import type { TableSource } from '$lib/components/ModelTable/types'; import { Tab, TabGroup, tableSourceMapper } from '@skeletonlabs/skeleton'; import ModelTable from '$lib/components/ModelTable/ModelTable.svelte'; + import { breadcrumbObject } from '$lib/utils/stores'; export let data; + breadcrumbObject.set(data.compliance_assessment); + let tabSet = 0; const plannedAppliedControls: TableSource = { diff --git a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/+page.svelte index 1241b287a8..6607751af8 100644 --- a/frontend/src/routes/(app)/risk-assessments/[id=uuid]/+page.svelte +++ b/frontend/src/routes/(app)/risk-assessments/[id=uuid]/+page.svelte @@ -161,7 +161,7 @@
- {m.remediationPlan()}