From 0a74c8da80424fa19f851353ebfd7817c0d8611e Mon Sep 17 00:00:00 2001 From: Abderrahmane Smimite Date: Tue, 29 Oct 2024 07:52:51 +0100 Subject: [PATCH 01/10] wip --- backend/core/views.py | 21 + frontend/src/lib/utils/table.ts | 772 +++++++++--------- .../(internal)/assets/graph/+page.server.ts | 13 + .../(internal)/assets/graph/+page.svelte | 11 + 4 files changed, 431 insertions(+), 386 deletions(-) create mode 100644 frontend/src/routes/(app)/(internal)/assets/graph/+page.server.ts create mode 100644 frontend/src/routes/(app)/(internal)/assets/graph/+page.svelte diff --git a/backend/core/views.py b/backend/core/views.py index a632f5399..69f549fd3 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -299,6 +299,27 @@ class AssetViewSet(BaseModelViewSet): def type(self, request): return Response(dict(Asset.Type.choices)) + @action(detail=False, name="Get assets tree") + def tree(self, request): + tree = {"name": "Global", "children": []} + + (viewable_objects, _, _) = RoleAssignment.get_accessible_object_ids( + folder=Folder.get_root_folder(), + user=request.user, + object_type=Folder, + ) + folders_list = list() + for folder in ( + Folder.objects.exclude(content_type="GL") + .filter(id__in=viewable_objects, parent_folder=Folder.get_root_folder()) + .distinct() + ): + entry = {"name": folder.name, "children": get_folder_content(folder)} + folders_list.append(entry) + tree.update({"children": folders_list}) + + return Response(tree) + class ReferenceControlViewSet(BaseModelViewSet): """ diff --git a/frontend/src/lib/utils/table.ts b/frontend/src/lib/utils/table.ts index a0dc14d91..cf62bb5c7 100644 --- a/frontend/src/lib/utils/table.ts +++ b/frontend/src/lib/utils/table.ts @@ -10,206 +10,206 @@ import * as m from '$paraglide/messages'; type JSONObject = { [key: string]: JSONObject } | JSONObject[] | string | number | boolean | null; interface ListViewFilterConfig { - component: ComponentType; - filter?: (columnValue: any, value: any) => boolean; - getColumn?: (row: Row) => Row[keyof Row]; - filterProps?: (rows: any[], field: string) => { [key: string]: any }; - extraProps?: { [key: string]: any }; - alwaysDisplay?: boolean; - alwaysDefined?: boolean; - hide?: boolean; + component: ComponentType; + filter?: (columnValue: any, value: any) => boolean; + getColumn?: (row: Row) => Row[keyof Row]; + filterProps?: (rows: any[], field: string) => { [key: string]: any }; + extraProps?: { [key: string]: any }; + alwaysDisplay?: boolean; + alwaysDefined?: boolean; + hide?: boolean; } interface ListViewFieldsConfig { - [key: string]: { - head: string[]; - body: string[]; - meta?: string[]; - breadcrumb_link_disabled?: boolean; - filters?: { - [key: string]: ListViewFilterConfig; - }; - }; + [key: string]: { + head: string[]; + body: string[]; + meta?: string[]; + breadcrumb_link_disabled?: boolean; + filters?: { + [key: string]: ListViewFilterConfig; + }; + }; } const PROJECT_STATUS_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.meta.lc_status, - extraProps: { - defaultOptionName: 'status' - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => row.meta.lc_status, + extraProps: { + defaultOptionName: 'status' + }, + alwaysDisplay: true }; const DOMAIN_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.folder.str, - alwaysDefined: true, - extraProps: { - defaultOptionName: 'domain' - } + component: SelectFilter, + getColumn: (row) => row.folder.str, + alwaysDefined: true, + extraProps: { + defaultOptionName: 'domain' + } }; const DOMAIN_FILTER_FROM_META: ListViewFilterConfig = { - ...DOMAIN_FILTER, - getColumn: (row) => row.meta.folder.str + ...DOMAIN_FILTER, + getColumn: (row) => row.meta.folder.str }; const DOMAIN_FILTER_FROM_META_PROJECT: ListViewFilterConfig = { - ...DOMAIN_FILTER, - getColumn: (row) => row.meta.project.folder.str + ...DOMAIN_FILTER, + getColumn: (row) => row.meta.project.folder.str }; const PROJECT_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.project.str, - extraProps: { - defaultOptionName: 'project' // Make translations - } + component: SelectFilter, + getColumn: (row) => row.project.str, + extraProps: { + defaultOptionName: 'project' // Make translations + } }; const PROJECT_FILTER_FROM_META: ListViewFilterConfig = { - ...PROJECT_FILTER, - getColumn: (row) => row.meta.project.str + ...PROJECT_FILTER, + getColumn: (row) => row.meta.project.str }; const STATUS_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.meta.status, - extraProps: { - defaultOptionName: 'status' - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => row.meta.status, + extraProps: { + defaultOptionName: 'status' + }, + alwaysDisplay: true }; const TREATMENT_FILTER: ListViewFilterConfig = { - // I could make a function just make the code less repeatitive and long for nothing - component: SelectFilter, - getColumn: (row) => row.meta.treatment, - extraProps: { - defaultOptionName: 'treatment' - } + // I could make a function just make the code less repeatitive and long for nothing + component: SelectFilter, + getColumn: (row) => row.meta.treatment, + extraProps: { + defaultOptionName: 'treatment' + } }; const STATE_FILTER: ListViewFilterConfig = { - // I could make a function just make the code less repeatitive and long for nothing - component: SelectFilter, - getColumn: (row) => row.meta.state, - extraProps: { - defaultOptionName: 'state' - } + // I could make a function just make the code less repeatitive and long for nothing + component: SelectFilter, + getColumn: (row) => row.meta.state, + extraProps: { + defaultOptionName: 'state' + } }; const APPROVER_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => { - if (row.first_name && row.last_name) { - return `${row.first_name} ${row.last_name}`; - } - return row.meta.approver.str; // This display the email in the approver filter, is this a problem because of email leak risks ? - }, - extraProps: { - defaultOptionName: 'approver' - } + component: SelectFilter, + getColumn: (row) => { + if (row.first_name && row.last_name) { + return `${row.first_name} ${row.last_name}`; + } + return row.meta.approver.str; // This display the email in the approver filter, is this a problem because of email leak risks ? + }, + extraProps: { + defaultOptionName: 'approver' + } }; const RISK_ASSESSMENT_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.meta.risk_assessment.name, - extraProps: { - defaultOptionName: 'riskAssessment' - } + component: SelectFilter, + getColumn: (row) => row.meta.risk_assessment.name, + extraProps: { + defaultOptionName: 'riskAssessment' + } }; const PROVIDER_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => { - return row.provider; - }, - extraProps: { - defaultOptionName: 'provider' - } + component: SelectFilter, + getColumn: (row) => { + return row.provider; + }, + extraProps: { + defaultOptionName: 'provider' + } }; const PROVIDER_FILTER_FOR_LIBRARIES: ListViewFilterConfig = { - ...PROVIDER_FILTER, - getColumn: (row) => { - return row.meta.provider; - }, - alwaysDisplay: true + ...PROVIDER_FILTER, + getColumn: (row) => { + return row.meta.provider; + }, + alwaysDisplay: true }; const THREAT_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => (row.meta.threats.length ? row.meta.threats.map((t) => t.str) : null), - extraProps: { - defaultOptionName: 'threat' - } + component: SelectFilter, + getColumn: (row) => (row.meta.threats.length ? row.meta.threats.map((t) => t.str) : null), + extraProps: { + defaultOptionName: 'threat' + } }; const ASSET_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => (row.meta.assets.length ? row.meta.assets.map((t) => t.str) : null), - extraProps: { - defaultOptionName: 'asset' - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => (row.meta.assets.length ? row.meta.assets.map((t) => t.str) : null), + extraProps: { + defaultOptionName: 'asset' + }, + alwaysDisplay: true }; const FRAMEWORK_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.framework.ref_id, - extraProps: { - defaultOptionName: 'framework' // Make translations - } + component: SelectFilter, + getColumn: (row) => row.framework.ref_id, + extraProps: { + defaultOptionName: 'framework' // Make translations + } }; const LANGUAGE_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.locales, - extraProps: { - defaultOptionName: 'language', // Make translations - optionLabels: LOCALE_DISPLAY_MAP - } + component: SelectFilter, + getColumn: (row) => row.locales, + extraProps: { + defaultOptionName: 'language', // Make translations + optionLabels: LOCALE_DISPLAY_MAP + } }; const ASSET_TYPE_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.meta.type, - extraProps: { - defaultOptionName: 'type' // Make translations - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => row.meta.type, + extraProps: { + defaultOptionName: 'type' // Make translations + }, + alwaysDisplay: true }; const CATEGORY_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.meta.category, - extraProps: { - defaultOptionName: 'category' // Make translations - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => row.meta.category, + extraProps: { + defaultOptionName: 'category' // Make translations + }, + alwaysDisplay: true }; const CSF_FUNCTION_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => row.meta.csf_function, - extraProps: { - defaultOptionName: 'csfFunction' // Make translations - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => row.meta.csf_function, + extraProps: { + defaultOptionName: 'csfFunction' // Make translations + }, + alwaysDisplay: true }; const OWNER_FILTER: ListViewFilterConfig = { - component: SelectFilter, - getColumn: (row) => { - const owner = row?.meta?.owner; - return owner && owner.length ? owner.map((o) => o.str) : null; - }, - extraProps: { - defaultOptionName: 'owner' - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => { + const owner = row?.meta?.owner; + return owner && owner.length ? owner.map((o) => o.str) : null; + }, + extraProps: { + defaultOptionName: 'owner' + }, + alwaysDisplay: true }; /* const HAS_RISK_MATRIX_FILTER: ListViewFilterConfig = { component: CheckboxFilter, @@ -228,259 +228,259 @@ const OWNER_FILTER: ListViewFilterConfig = { }; */ const LIBRARY_TYPE_FILTER = { - component: SelectFilter, - getColumn: (row) => { - const overviewKeys = new Set(row.overview.map((overviewRow) => overviewRow.split(':')[0])); - const libraryDatatypeSet = new Set([ - 'framework', - 'risk_matrix', - 'threats', - 'requirement_mapping_set', - 'reference_controls' - ]); - const datatypes = [...libraryDatatypeSet].filter((datatype) => overviewKeys.has(datatype)); - return datatypes; - }, - extraProps: { - defaultOptionName: 'objectType', - optionLabels: { - reference_controls: 'referenceControls', - requirement_mapping_set: 'requirementMappingSet', - risk_matrix: 'riskMatrix' - } - }, - alwaysDisplay: true + component: SelectFilter, + getColumn: (row) => { + const overviewKeys = new Set(row.overview.map((overviewRow) => overviewRow.split(':')[0])); + const libraryDatatypeSet = new Set([ + 'framework', + 'risk_matrix', + 'threats', + 'requirement_mapping_set', + 'reference_controls' + ]); + const datatypes = [...libraryDatatypeSet].filter((datatype) => overviewKeys.has(datatype)); + return datatypes; + }, + extraProps: { + defaultOptionName: 'objectType', + optionLabels: { + reference_controls: 'referenceControls', + requirement_mapping_set: 'requirementMappingSet', + risk_matrix: 'riskMatrix' + } + }, + alwaysDisplay: true }; export const listViewFields: ListViewFieldsConfig = { - folders: { - head: ['name', 'description', 'parentDomain'], - body: ['name', 'description', 'parent_folder'] - }, - projects: { - head: ['name', 'description', 'domain'], - body: ['name', 'description', 'folder'], - filters: { - folder: DOMAIN_FILTER, - lc_status: PROJECT_STATUS_FILTER - } - }, - 'risk-matrices': { - head: ['name', 'description', 'provider', 'domain'], - body: ['name', 'description', 'provider', 'folder'], - meta: ['id', 'urn'], - filters: { - folder: DOMAIN_FILTER - } - }, - vulnerabilities: { - head: ['ref_id', 'name', 'description', 'folder'], - body: ['ref_id', 'name', 'description', 'folder'] - }, - 'risk-assessments': { - head: ['name', 'riskMatrix', 'description', 'riskScenarios', 'project'], - body: ['str', 'risk_matrix', 'description', 'risk_scenarios_count', 'project'], - filters: { - folder: { ...DOMAIN_FILTER_FROM_META_PROJECT, alwaysDisplay: true }, - project: PROJECT_FILTER, - status: { ...STATUS_FILTER, alwaysDisplay: true } - } - }, - threats: { - head: ['ref', 'name', 'description', 'provider', 'domain'], - body: ['ref_id', 'name', 'description', 'provider', 'folder'], - meta: ['id', 'urn'], - filters: { - folder: DOMAIN_FILTER - } - }, - 'risk-scenarios': { - head: ['name', 'threats', 'riskAssessment', 'appliedControls', 'currentLevel', 'residualLevel'], - body: [ - 'name', - 'threats', - 'risk_assessment', - 'applied_controls', - 'current_level', - 'residual_level' - ], - filters: { - folder: { ...DOMAIN_FILTER_FROM_META_PROJECT, alwaysDisplay: true }, - project: { ...PROJECT_FILTER_FROM_META, alwaysDisplay: true }, - treatment: { ...TREATMENT_FILTER, alwaysDisplay: true }, - risk_assessment: RISK_ASSESSMENT_FILTER, - threats: THREAT_FILTER, - assets: ASSET_FILTER - } - }, - 'risk-acceptances': { - head: ['name', 'description', 'riskScenarios'], - body: ['name', 'description', 'risk_scenarios'], - filters: { - folder: DOMAIN_FILTER_FROM_META, - state: STATE_FILTER, - approver: APPROVER_FILTER - } - }, - 'applied-controls': { - head: [ - 'name', - 'description', - 'category', - 'csfFunction', - 'eta', - 'owner', - 'domain', - 'referenceControl' - ], - body: [ - 'name', - 'description', - 'category', - 'csf_function', - 'eta', - 'owner', - 'folder', - 'reference_control' - ], - filters: { - folder: DOMAIN_FILTER, - status: STATUS_FILTER, - category: CATEGORY_FILTER, - csf_function: CSF_FUNCTION_FILTER, - owner: OWNER_FILTER - } - }, - policies: { - head: ['name', 'description', 'csfFunction', 'eta', 'domain', 'referenceControl'], - body: ['name', 'description', 'csf_function', 'eta', 'folder', 'reference_control'], - filters: { - folder: DOMAIN_FILTER - } - }, - 'reference-controls': { - head: ['ref', 'name', 'description', 'category', 'csfFunction', 'provider', 'domain'], - body: ['ref_id', 'name', 'description', 'category', 'csf_function', 'provider', 'folder'], - meta: ['id', 'urn'], - filters: { - folder: { ...DOMAIN_FILTER, alwaysDisplay: true }, - category: CATEGORY_FILTER, - provider: PROVIDER_FILTER, - csf_function: CSF_FUNCTION_FILTER - } - }, - assets: { - head: ['name', 'description', 'businessValue', 'domain'], - body: ['name', 'description', 'business_value', 'folder'], - filters: { - folder: DOMAIN_FILTER, - type: ASSET_TYPE_FILTER - } - }, - users: { - head: ['email', 'firstName', 'lastName'], - body: ['email', 'first_name', 'last_name'] - }, - 'user-groups': { - head: ['name'], - body: ['localization_dict'], - meta: ['id', 'builtin'] - }, - roles: { - head: ['name', 'description'], - body: ['name', 'description'] - }, - 'role-assignments': { - head: ['user', 'userGroup', 'role', 'perimeter'], - body: ['user', 'user_group', 'role', 'perimeter_folders'] - }, - frameworks: { - head: ['name', 'description', 'provider', 'complianceAssessments', 'domain'], - body: ['name', 'description', 'provider', 'compliance_assessments', 'folder'], - meta: ['id', 'urn'], - filters: { - folder: DOMAIN_FILTER, - provider: PROVIDER_FILTER - } - }, - 'compliance-assessments': { - head: ['name', 'framework', 'description', 'project'], - body: ['name', 'framework', 'description', 'project'], - filters: { - folder: { ...DOMAIN_FILTER_FROM_META_PROJECT, alwaysDisplay: true }, // alwaysDisplay shoudln't be mandatory here something is wrong - project: PROJECT_FILTER, - framework: FRAMEWORK_FILTER, - status: STATUS_FILTER - } - }, - 'requirement-assessments': { - head: ['name', 'description', 'complianceAssessment'], - body: ['name', 'description', 'compliance_assessment'], - breadcrumb_link_disabled: true - }, - evidences: { - head: ['name', 'file', 'size', 'description'], - body: ['name', 'attachment', 'size', 'description'], - filters: { - folder: { ...DOMAIN_FILTER_FROM_META, alwaysDisplay: true } // This filter should also be displayed even without alwaysDisplay - } - }, - requirements: { - head: ['ref', 'name', 'description', 'framework'], - body: ['ref_id', 'name', 'description', 'framework'], - meta: ['id', 'urn'] - }, - libraries: { - head: ['provider', 'name', 'description', 'language', 'overview'], - body: ['provider', 'name', 'description', 'locales', 'overview'] - }, - 'stored-libraries': { - head: ['provider', 'name', 'description', 'language', 'overview'], - body: ['provider', 'name', 'description', 'locales', 'overview'], - filters: { - locales: LANGUAGE_FILTER, - provider: PROVIDER_FILTER_FOR_LIBRARIES, - objectType: LIBRARY_TYPE_FILTER - } - }, - 'loaded-libraries': { - head: ['provider', 'name', 'description', 'language', 'overview'], - body: ['provider', 'name', 'description', 'locales', 'overview'], - filters: { - locales: LANGUAGE_FILTER, - provider: PROVIDER_FILTER_FOR_LIBRARIES, - objectType: LIBRARY_TYPE_FILTER - } - }, - 'sso-settings': { - head: ['name', 'provider', 'providerId'], - body: ['name', 'provider', 'provider_id'] - }, - 'requirement-mapping-sets': { - head: ['sourceFramework', 'targetFramework'], - body: ['source_framework', 'target_framework'] - }, - entities: { - head: ['name', 'description', 'domain', 'ownedFolders'], - body: ['name', 'description', 'folder', 'owned_folders'], - filters: { - folder: DOMAIN_FILTER - } - }, - 'entity-assessments': { - head: ['name', 'description', 'project', 'entity'], - body: ['name', 'description', 'project', 'entity'], - filters: { - project: PROJECT_FILTER, - status: STATUS_FILTER - } - }, - solutions: { - head: ['name', 'description', 'providerEntity', 'recipientEntity', 'criticality'], - body: ['name', 'description', 'provider_entity', 'recipient_entity', 'criticality'] - }, - representatives: { - head: ['email', 'entity', 'role'], - body: ['email', 'entity', 'role'] - } + folders: { + head: ['name', 'description', 'parentDomain'], + body: ['name', 'description', 'parent_folder'] + }, + projects: { + head: ['name', 'description', 'domain'], + body: ['name', 'description', 'folder'], + filters: { + folder: DOMAIN_FILTER, + lc_status: PROJECT_STATUS_FILTER + } + }, + 'risk-matrices': { + head: ['name', 'description', 'provider', 'domain'], + body: ['name', 'description', 'provider', 'folder'], + meta: ['id', 'urn'], + filters: { + folder: DOMAIN_FILTER + } + }, + vulnerabilities: { + head: ['ref_id', 'name', 'description', 'folder'], + body: ['ref_id', 'name', 'description', 'folder'] + }, + 'risk-assessments': { + head: ['name', 'riskMatrix', 'description', 'riskScenarios', 'project'], + body: ['str', 'risk_matrix', 'description', 'risk_scenarios_count', 'project'], + filters: { + folder: { ...DOMAIN_FILTER_FROM_META_PROJECT, alwaysDisplay: true }, + project: PROJECT_FILTER, + status: { ...STATUS_FILTER, alwaysDisplay: true } + } + }, + threats: { + head: ['ref', 'name', 'description', 'provider', 'domain'], + body: ['ref_id', 'name', 'description', 'provider', 'folder'], + meta: ['id', 'urn'], + filters: { + folder: DOMAIN_FILTER + } + }, + 'risk-scenarios': { + head: ['name', 'threats', 'riskAssessment', 'appliedControls', 'currentLevel', 'residualLevel'], + body: [ + 'name', + 'threats', + 'risk_assessment', + 'applied_controls', + 'current_level', + 'residual_level' + ], + filters: { + folder: { ...DOMAIN_FILTER_FROM_META_PROJECT, alwaysDisplay: true }, + project: { ...PROJECT_FILTER_FROM_META, alwaysDisplay: true }, + treatment: { ...TREATMENT_FILTER, alwaysDisplay: true }, + risk_assessment: RISK_ASSESSMENT_FILTER, + threats: THREAT_FILTER, + assets: ASSET_FILTER + } + }, + 'risk-acceptances': { + head: ['name', 'description', 'riskScenarios'], + body: ['name', 'description', 'risk_scenarios'], + filters: { + folder: DOMAIN_FILTER_FROM_META, + state: STATE_FILTER, + approver: APPROVER_FILTER + } + }, + 'applied-controls': { + head: [ + 'name', + 'description', + 'category', + 'csfFunction', + 'eta', + 'owner', + 'domain', + 'referenceControl' + ], + body: [ + 'name', + 'description', + 'category', + 'csf_function', + 'eta', + 'owner', + 'folder', + 'reference_control' + ], + filters: { + folder: DOMAIN_FILTER, + status: STATUS_FILTER, + category: CATEGORY_FILTER, + csf_function: CSF_FUNCTION_FILTER, + owner: OWNER_FILTER + } + }, + policies: { + head: ['name', 'description', 'csfFunction', 'eta', 'domain', 'referenceControl'], + body: ['name', 'description', 'csf_function', 'eta', 'folder', 'reference_control'], + filters: { + folder: DOMAIN_FILTER + } + }, + 'reference-controls': { + head: ['ref', 'name', 'description', 'category', 'csfFunction', 'provider', 'domain'], + body: ['ref_id', 'name', 'description', 'category', 'csf_function', 'provider', 'folder'], + meta: ['id', 'urn'], + filters: { + folder: { ...DOMAIN_FILTER, alwaysDisplay: true }, + category: CATEGORY_FILTER, + provider: PROVIDER_FILTER, + csf_function: CSF_FUNCTION_FILTER + } + }, + assets: { + head: ['name', 'description', 'businessValue', 'domain', 'parents'], + body: ['name', 'description', 'business_value', 'folder', 'parent_assets'], + filters: { + folder: DOMAIN_FILTER, + type: ASSET_TYPE_FILTER + } + }, + users: { + head: ['email', 'firstName', 'lastName'], + body: ['email', 'first_name', 'last_name'] + }, + 'user-groups': { + head: ['name'], + body: ['localization_dict'], + meta: ['id', 'builtin'] + }, + roles: { + head: ['name', 'description'], + body: ['name', 'description'] + }, + 'role-assignments': { + head: ['user', 'userGroup', 'role', 'perimeter'], + body: ['user', 'user_group', 'role', 'perimeter_folders'] + }, + frameworks: { + head: ['name', 'description', 'provider', 'complianceAssessments', 'domain'], + body: ['name', 'description', 'provider', 'compliance_assessments', 'folder'], + meta: ['id', 'urn'], + filters: { + folder: DOMAIN_FILTER, + provider: PROVIDER_FILTER + } + }, + 'compliance-assessments': { + head: ['name', 'framework', 'description', 'project'], + body: ['name', 'framework', 'description', 'project'], + filters: { + folder: { ...DOMAIN_FILTER_FROM_META_PROJECT, alwaysDisplay: true }, // alwaysDisplay shoudln't be mandatory here something is wrong + project: PROJECT_FILTER, + framework: FRAMEWORK_FILTER, + status: STATUS_FILTER + } + }, + 'requirement-assessments': { + head: ['name', 'description', 'complianceAssessment'], + body: ['name', 'description', 'compliance_assessment'], + breadcrumb_link_disabled: true + }, + evidences: { + head: ['name', 'file', 'size', 'description'], + body: ['name', 'attachment', 'size', 'description'], + filters: { + folder: { ...DOMAIN_FILTER_FROM_META, alwaysDisplay: true } // This filter should also be displayed even without alwaysDisplay + } + }, + requirements: { + head: ['ref', 'name', 'description', 'framework'], + body: ['ref_id', 'name', 'description', 'framework'], + meta: ['id', 'urn'] + }, + libraries: { + head: ['provider', 'name', 'description', 'language', 'overview'], + body: ['provider', 'name', 'description', 'locales', 'overview'] + }, + 'stored-libraries': { + head: ['provider', 'name', 'description', 'language', 'overview'], + body: ['provider', 'name', 'description', 'locales', 'overview'], + filters: { + locales: LANGUAGE_FILTER, + provider: PROVIDER_FILTER_FOR_LIBRARIES, + objectType: LIBRARY_TYPE_FILTER + } + }, + 'loaded-libraries': { + head: ['provider', 'name', 'description', 'language', 'overview'], + body: ['provider', 'name', 'description', 'locales', 'overview'], + filters: { + locales: LANGUAGE_FILTER, + provider: PROVIDER_FILTER_FOR_LIBRARIES, + objectType: LIBRARY_TYPE_FILTER + } + }, + 'sso-settings': { + head: ['name', 'provider', 'providerId'], + body: ['name', 'provider', 'provider_id'] + }, + 'requirement-mapping-sets': { + head: ['sourceFramework', 'targetFramework'], + body: ['source_framework', 'target_framework'] + }, + entities: { + head: ['name', 'description', 'domain', 'ownedFolders'], + body: ['name', 'description', 'folder', 'owned_folders'], + filters: { + folder: DOMAIN_FILTER + } + }, + 'entity-assessments': { + head: ['name', 'description', 'project', 'entity'], + body: ['name', 'description', 'project', 'entity'], + filters: { + project: PROJECT_FILTER, + status: STATUS_FILTER + } + }, + solutions: { + head: ['name', 'description', 'providerEntity', 'recipientEntity', 'criticality'], + body: ['name', 'description', 'provider_entity', 'recipient_entity', 'criticality'] + }, + representatives: { + head: ['email', 'entity', 'role'], + body: ['email', 'entity', 'role'] + } }; diff --git a/frontend/src/routes/(app)/(internal)/assets/graph/+page.server.ts b/frontend/src/routes/(app)/(internal)/assets/graph/+page.server.ts new file mode 100644 index 000000000..8d697268f --- /dev/null +++ b/frontend/src/routes/(app)/(internal)/assets/graph/+page.server.ts @@ -0,0 +1,13 @@ + +import { BASE_API_URL } from '$lib/utils/constants'; + +import type { PageServerLoad } from './$types'; + +export const load = (async ({ fetch }) => { + const endpoint = `${BASE_API_URL}/assets/tree/`; + + const res = await fetch(endpoint); + const data = await res.json(); + + return { data }; +}) satisfies PageServerLoad; diff --git a/frontend/src/routes/(app)/(internal)/assets/graph/+page.svelte b/frontend/src/routes/(app)/(internal)/assets/graph/+page.svelte new file mode 100644 index 000000000..52b035925 --- /dev/null +++ b/frontend/src/routes/(app)/(internal)/assets/graph/+page.svelte @@ -0,0 +1,11 @@ + + +
+
+ +
+
From 05cc41eb860494f7da06ef8fd4fe6735e9a462b8 Mon Sep 17 00:00:00 2001 From: Abderrahmane Smimite Date: Thu, 31 Oct 2024 08:16:39 +0100 Subject: [PATCH 02/10] fixup --- frontend/src/lib/utils/table.ts | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/frontend/src/lib/utils/table.ts b/frontend/src/lib/utils/table.ts index cf62bb5c7..8f929e4fe 100644 --- a/frontend/src/lib/utils/table.ts +++ b/frontend/src/lib/utils/table.ts @@ -50,6 +50,19 @@ const DOMAIN_FILTER: ListViewFilterConfig = { } }; +const LABELS_FILTER: ListViewFilterConfig = { + component: SelectFilter, + getColumn: (row) => { + return row.filtering_labels && row.filtering_labels.length > 0 + ? row.filtering_labels.map((filtering_label) => filtering_label.str) + : ['']; + }, + alwaysDefined: true, + extraProps: { + defaultOptionName: 'filtering_labels' + } +}; + const DOMAIN_FILTER_FROM_META: ListViewFilterConfig = { ...DOMAIN_FILTER, getColumn: (row) => row.meta.folder.str @@ -265,6 +278,10 @@ export const listViewFields: ListViewFieldsConfig = { lc_status: PROJECT_STATUS_FILTER } }, + 'filtering-labels': { + head: ['label'], + body: ['label'] + }, 'risk-matrices': { head: ['name', 'description', 'provider', 'domain'], body: ['name', 'description', 'provider', 'folder'], @@ -274,8 +291,12 @@ export const listViewFields: ListViewFieldsConfig = { } }, vulnerabilities: { - head: ['ref_id', 'name', 'description', 'folder'], - body: ['ref_id', 'name', 'description', 'folder'] + head: ['ref_id', 'name', 'description', 'applied_controls', 'folder', 'labels'], + body: ['ref_id', 'name', 'description', 'applied_controls', 'folder', 'filtering_labels'], + filters: { + folder: DOMAIN_FILTER, + filtering_labels: LABELS_FILTER + } }, 'risk-assessments': { head: ['name', 'riskMatrix', 'description', 'riskScenarios', 'project'], @@ -370,8 +391,8 @@ export const listViewFields: ListViewFieldsConfig = { } }, assets: { - head: ['name', 'description', 'businessValue', 'domain', 'parents'], - body: ['name', 'description', 'business_value', 'folder', 'parent_assets'], + head: ['name', 'description', 'businessValue', 'domain'], + body: ['name', 'description', 'business_value', 'folder'], filters: { folder: DOMAIN_FILTER, type: ASSET_TYPE_FILTER From 3b981539ee8e8527df71c0eefc5d94fa97b8ce02 Mon Sep 17 00:00:00 2001 From: Abderrahmane Smimite Date: Thu, 31 Oct 2024 08:41:17 +0100 Subject: [PATCH 03/10] split component --- .../components/DataViz/GraphExplorer.svelte | 208 ++++++++++++++++++ .../mapping/[id=uuid]/+page.svelte | 208 +----------------- 2 files changed, 214 insertions(+), 202 deletions(-) create mode 100644 frontend/src/lib/components/DataViz/GraphExplorer.svelte diff --git a/frontend/src/lib/components/DataViz/GraphExplorer.svelte b/frontend/src/lib/components/DataViz/GraphExplorer.svelte new file mode 100644 index 000000000..1dca41e66 --- /dev/null +++ b/frontend/src/lib/components/DataViz/GraphExplorer.svelte @@ -0,0 +1,208 @@ + + +
+ + { + if (event.key === 'Enter') searchNode(searchQuery); + }} + /> + + + +
+
diff --git a/frontend/src/routes/(app)/(internal)/experimental/mapping/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/(internal)/experimental/mapping/[id=uuid]/+page.svelte index 9789e4df3..b5aab97b3 100644 --- a/frontend/src/routes/(app)/(internal)/experimental/mapping/[id=uuid]/+page.svelte +++ b/frontend/src/routes/(app)/(internal)/experimental/mapping/[id=uuid]/+page.svelte @@ -1,209 +1,13 @@ -
- - { - if (event.key === 'Enter') searchNode(searchQuery); - }} - /> - - - +
+
+ +
-
From 53539e059ddcc3d982f4d28541e40752f5845d26 Mon Sep 17 00:00:00 2001 From: Abderrahmane Smimite Date: Thu, 31 Oct 2024 09:01:53 +0100 Subject: [PATCH 04/10] Clean up: reusable component --- .../components/DataViz/GraphExplorer.svelte | 312 +++++++++--------- .../mapping/[id=uuid]/+page.svelte | 2 +- 2 files changed, 159 insertions(+), 155 deletions(-) diff --git a/frontend/src/lib/components/DataViz/GraphExplorer.svelte b/frontend/src/lib/components/DataViz/GraphExplorer.svelte index 1dca41e66..22d00129b 100644 --- a/frontend/src/lib/components/DataViz/GraphExplorer.svelte +++ b/frontend/src/lib/components/DataViz/GraphExplorer.svelte @@ -1,193 +1,197 @@
- + { - if (event.key === 'Enter') searchNode(searchQuery); - }} /> - + +
-
+