diff --git a/backend/app_tests/api/test_api_requirement_assessments.py b/backend/app_tests/api/test_api_requirement_assessments.py index 2f6d59e114..646b0ed6d8 100644 --- a/backend/app_tests/api/test_api_requirement_assessments.py +++ b/backend/app_tests/api/test_api_requirement_assessments.py @@ -113,7 +113,7 @@ def test_get_requirement_assessments(self, authenticated_client): }, { "folder": str(folder.id), - "compliance_assessment": str(compliance_assessment.id), + "compliance_assessment": {"id": str(compliance_assessment.id), "str": compliance_assessment.name}, "requirement": str(RequirementNode.objects.all()[0].id), }, -1, @@ -143,6 +143,9 @@ def test_create_requirement_assessments(self, authenticated_client): "requirement": str(RequirementNode.objects.all()[0].id), "security_measures": [str(security_measure.id)], }, + { + "compliance_assessment": {"id": str(compliance_assessment.id), "str": compliance_assessment.name} + }, base_count=-1, ) @@ -186,7 +189,7 @@ def test_update_requirement_assessments(self, authenticated_client): }, { "folder": str(Folder.get_root_folder().id), - "compliance_assessment": str(compliance_assessment.id), + "compliance_assessment": {"id": str(compliance_assessment.id), "str": compliance_assessment.name}, "requirement": str(RequirementNode.objects.all()[0].id), }, ) diff --git a/backend/core/serializers.py b/backend/core/serializers.py index 6a283edd40..1ef5af2d7c 100644 --- a/backend/core/serializers.py +++ b/backend/core/serializers.py @@ -395,6 +395,8 @@ class Meta: class RequirementAssessmentReadSerializer(BaseModelSerializer): name = serializers.CharField(source="__str__") + compliance_assessment = FieldsRelatedField() + class Meta: model = RequirementAssessment diff --git a/backend/core/views.py b/backend/core/views.py index 2706cd9c41..cf11287105 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -502,6 +502,7 @@ class SecurityMeasureViewSet(BaseModelViewSet): "effort", "risk_scenarios", "requirement_assessments", + "evidences" ] search_fields = ["name", "description", "risk_scenarios", "requirement_assessments"] @@ -1161,7 +1162,7 @@ class RequirementAssessmentViewSet(BaseModelViewSet): """ model = RequirementAssessment - filterset_fields = ["folder"] + filterset_fields = ["folder", "evidences"] search_fields = ["name", "description"] @action(detail=False, name="Get updatable measures") diff --git a/frontend/.eslintignore b/frontend/.eslintignore index 38972655fa..1a5c5a0c10 100644 --- a/frontend/.eslintignore +++ b/frontend/.eslintignore @@ -6,6 +6,8 @@ node_modules .env .env.* !.env.example +/tests/reports/* +/tests/results/* # Ignore files for PNPM, NPM and YARN pnpm-lock.yaml diff --git a/frontend/.prettierignore b/frontend/.prettierignore index 38972655fa..1a5c5a0c10 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -6,6 +6,8 @@ node_modules .env .env.* !.env.example +/tests/reports/* +/tests/results/* # Ignore files for PNPM, NPM and YARN pnpm-lock.yaml diff --git a/frontend/src/lib/components/Forms/ModelForm.svelte b/frontend/src/lib/components/Forms/ModelForm.svelte index ac2d13af6f..d28a68a181 100644 --- a/frontend/src/lib/components/Forms/ModelForm.svelte +++ b/frontend/src/lib/components/Forms/ModelForm.svelte @@ -248,20 +248,6 @@ label="Domain" hide={initialData.security_measures || initialData.requirement_assessments} /> - -
-{@html display} +{display} diff --git a/frontend/src/lib/components/ModelTable/ModelTable.svelte b/frontend/src/lib/components/ModelTable/ModelTable.svelte index 7dea3386ed..198d8f424d 100644 --- a/frontend/src/lib/components/ModelTable/ModelTable.svelte +++ b/frontend/src/lib/components/ModelTable/ModelTable.svelte @@ -77,7 +77,7 @@ if (['Enter', 'Space'].includes(event.code)) onRowClick(event, rowIndex); } - export let identifierField: string = 'id'; + export let identifierField = 'id'; export let deleteForm: SuperValidated | undefined = undefined; diff --git a/frontend/src/lib/components/TreeView/RecursiveTreeViewItem.svelte b/frontend/src/lib/components/TreeView/RecursiveTreeViewItem.svelte index 97a69d79bd..38a1f6d33d 100644 --- a/frontend/src/lib/components/TreeView/RecursiveTreeViewItem.svelte +++ b/frontend/src/lib/components/TreeView/RecursiveTreeViewItem.svelte @@ -151,13 +151,13 @@ }} > {#if typeof node.content === 'string'} - {@html node.content} + {node.content} {:else} {/if} {#if typeof node.lead === 'string'} - {@html node.lead} + {node.lead} {:else} {/if} diff --git a/frontend/src/lib/components/fragments/WatchlistExceptions.svelte b/frontend/src/lib/components/fragments/WatchlistExceptions.svelte index 3df630c49f..98e3538f9b 100644 --- a/frontend/src/lib/components/fragments/WatchlistExceptions.svelte +++ b/frontend/src/lib/components/fragments/WatchlistExceptions.svelte @@ -43,21 +43,21 @@ request_path )}'" > - + {#if acceptance.approver == user.id && acceptance.state == 'submitted'} action requested {/if} {acceptance.name} - - + + {acceptance.folder.str} - - + + {acceptance.approver.str} - - + + {#if acceptanceState(acceptance.expiry_date) === 'expired'} expired {:else if acceptanceState(acceptance.expiry_date) === 'upcoming'} @@ -66,7 +66,7 @@ today {/if} {formatStringToDate(acceptance.expiry_date)} - + {/each} {:else} diff --git a/frontend/src/lib/utils/crud.ts b/frontend/src/lib/utils/crud.ts index 3896c05b77..eef2cf2017 100644 --- a/frontend/src/lib/utils/crud.ts +++ b/frontend/src/lib/utils/crud.ts @@ -270,7 +270,8 @@ export const URL_MODEL_MAP: ModelMap = { selectFields: [{ field: 'status' }], foreignKeyFields: [ { field: 'security_measures', urlModel: 'security-measures' }, - { field: 'evidences', urlModel: 'evidences' } + { field: 'evidences', urlModel: 'evidences' }, + { field: 'compliance_assessment', urlModel: 'compliance-assessments' } ] }, libraries: { diff --git a/frontend/src/lib/utils/csrf.ts b/frontend/src/lib/utils/csrf.ts index ea42c2573d..b817397a7c 100644 --- a/frontend/src/lib/utils/csrf.ts +++ b/frontend/src/lib/utils/csrf.ts @@ -6,7 +6,9 @@ async function getCsrfToken() { credentials: 'include' }).then((res) => res.json()); return response.csrfToken; - } catch (error) {} + } catch (error) { + console.error(error); + } } export const csrfToken = await getCsrfToken(); diff --git a/frontend/src/lib/utils/table.ts b/frontend/src/lib/utils/table.ts index fc30db848a..f1ccf135df 100644 --- a/frontend/src/lib/utils/table.ts +++ b/frontend/src/lib/utils/table.ts @@ -84,6 +84,10 @@ export const listViewFields = { head: ['Name', 'Framework', 'Description', 'Project'], body: ['name', 'framework', 'description', 'project'] }, + 'requirement-assessments': { + head: ['Name', 'Description', 'Compliance Assessment'], + body: ['name', 'description', 'compliance_assessment'] + }, evidences: { head: ['Name', 'File', 'Description'], body: ['name', 'attachment', 'description'] 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 9503b8f77a..5a4be38805 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/+page.svelte @@ -49,7 +49,7 @@ if (node.children && Object.keys(node.children).length > 0) { for (const childId in node.children) { - if (node.children.hasOwnProperty(childId)) { + if (Object.prototype.hasOwnProperty.call(node.children, childId)) { const childNode = node.children[childId]; countStatus(childNode, statusCounts); } diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemContent.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemContent.svelte index e1ed2a83ce..24bda2ce25 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemContent.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemContent.svelte @@ -10,7 +10,7 @@ export let security_functions: Record[] | undefined = undefined; export let children: Record> | undefined = undefined; export let canEditRequirementAssessment: boolean; - export let status: string | undefined = undefined; + // export let status: string | undefined = undefined; export let statusCounts: Record | undefined; $: hasChildren = children && Object.keys(children).length > 0; @@ -87,7 +87,7 @@ {#if threats || security_functions}
(showInfo = !showInfo)} on:keydown={(_) => (showInfo = !showInfo)} diff --git a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemLead.svelte b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemLead.svelte index d6f5857a3b..4106c9430b 100644 --- a/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemLead.svelte +++ b/frontend/src/routes/(app)/compliance-assessments/[id=uuid]/TreeViewItemLead.svelte @@ -1,5 +1,5 @@
- {#each Object.entries(data.evidence).filter( ([key, _]) => ['name', 'description', 'folder', 'security_measures', 'requirement_assessments', 'attachment', 'link', 'comment'].includes(key) ) as [key, value]} + {#each Object.entries(data.evidence).filter( ([key, _]) => ['name', 'description', 'folder', 'attachment', 'link', 'comment'].includes(key) ) as [key, value]}
{#if key === 'urn'} @@ -123,6 +132,31 @@ {/if}
+
+ + Security measures + Requirement assessments + + {#if tabSet === 0} +
+ +
+ {/if} + {#if tabSet === 1} +
+ +
+ {/if} +
+
+
{#if data.evidence.attachment}
diff --git a/frontend/src/routes/(app)/frameworks/[id=uuid]/TreeViewItemContent.svelte b/frontend/src/routes/(app)/frameworks/[id=uuid]/TreeViewItemContent.svelte index b36c4e3d72..12632f19b5 100644 --- a/frontend/src/routes/(app)/frameworks/[id=uuid]/TreeViewItemContent.svelte +++ b/frontend/src/routes/(app)/frameworks/[id=uuid]/TreeViewItemContent.svelte @@ -26,8 +26,11 @@ {#if (threats && threats.length > 0) || (security_functions && security_functions.length > 0)}
(showInfo = !showInfo)} + on:keydown={(_) => (showInfo = !showInfo)} > Learn more
diff --git a/frontend/src/routes/(app)/libraries/+page.server.ts b/frontend/src/routes/(app)/libraries/+page.server.ts index 54bfa5aaff..8b724e657c 100644 --- a/frontend/src/routes/(app)/libraries/+page.server.ts +++ b/frontend/src/routes/(app)/libraries/+page.server.ts @@ -18,7 +18,7 @@ export const load = (async ({ fetch }) => { const libraries: Library[] = await res.json().then((res) => res.results); function countObjects(library: Library) { - let result: { [key: string]: any } = new Object(); + const result: { [key: string]: any } = new Object(); for (const [key, value] of Object.entries(library.objects)) { if (Array.isArray(value)) { const str = key.charAt(0).toUpperCase() + key.slice(1).replace('_', ' ');