-
Notifications
You must be signed in to change notification settings - Fork 288
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9049fc1
commit e26a0ff
Showing
15 changed files
with
324 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
2 changes: 1 addition & 1 deletion
2
...)/(internal)/libraries/[id=uuid]/+page.ts → ...rnal)/loaded-libraries/[id=uuid]/+page.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.server.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { BASE_API_URL } from '$lib/utils/constants'; | ||
import { safeTranslate } from '$lib/utils/i18n'; | ||
import * as m from '$paraglide/messages'; | ||
import { fail, type Actions } from '@sveltejs/kit'; | ||
import { setFlash } from 'sveltekit-flash-message/server'; | ||
|
||
export const actions: Actions = { | ||
load: async (event) => { | ||
const endpoint = `${BASE_API_URL}/stored-libraries/${event.params.id}/import/`; | ||
const res = await event.fetch(endpoint); // We will have to make this a POST later (we should use POST when creating a new object) | ||
if (!res.ok) { | ||
const response = await res.json(); | ||
console.error('server response:', response); | ||
setFlash({ type: 'error', message: safeTranslate(response.error) }, event); | ||
return fail(400, { error: m.errorLoadingLibrary() }); | ||
} | ||
setFlash( | ||
{ | ||
type: 'success', | ||
message: m.librarySuccessfullyLoaded() | ||
}, | ||
event | ||
); | ||
} | ||
}; |
225 changes: 225 additions & 0 deletions
225
frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
<script lang="ts"> | ||
import { page } from '$app/stores'; | ||
import Dropdown from '$lib/components/Dropdown/Dropdown.svelte'; | ||
import ModelTable from '$lib/components/ModelTable/ModelTable.svelte'; | ||
import RiskMatrix from '$lib/components/RiskMatrix/RiskMatrix.svelte'; | ||
import * as m from '$paraglide/messages'; | ||
import { formatDateOrDateTime } from '$lib/utils/datetime'; | ||
import { languageTag } from '$paraglide/runtime'; | ||
import TreeViewItemContent from '../../frameworks/[id=uuid]/TreeViewItemContent.svelte'; | ||
export let data; | ||
let loading = { form: false, library: '' }; | ||
const showRisks = true; | ||
interface LibraryObjects { | ||
[key: string]: any; | ||
} | ||
const libraryObjects: LibraryObjects = data.library.objects ?? []; | ||
const riskMatrices = libraryObjects['risk_matrix'] ?? []; | ||
const referenceControls = libraryObjects['reference_controls'] ?? []; | ||
const threats = libraryObjects['threats'] ?? []; | ||
const framework = libraryObjects['framework']; | ||
function transformToTreeView(nodes) { | ||
return nodes.map(([id, node]) => { | ||
return { | ||
id: id, | ||
content: TreeViewItemContent, | ||
contentProps: node, | ||
children: node.children ? transformToTreeView(Object.entries(node.children)) : [] | ||
}; | ||
}); | ||
} | ||
import { enhance } from '$app/forms'; | ||
import type { TableSource } from '$lib/components/ModelTable/types'; | ||
import RecursiveTreeView from '$lib/components/TreeView/RecursiveTreeView.svelte'; | ||
import { ProgressRadial, tableSourceMapper } from '@skeletonlabs/skeleton'; | ||
const riskMatricesTable: TableSource = { | ||
head: { name: 'name', description: 'description' }, | ||
body: tableSourceMapper(riskMatrices, ['name', 'description']) | ||
}; | ||
const referenceControlsTable: TableSource = { | ||
head: { | ||
ref_id: 'ref', | ||
name: 'name', | ||
description: 'description', | ||
category: 'category', | ||
csf_function: 'csfFunction' | ||
}, | ||
body: tableSourceMapper(referenceControls, [ | ||
'ref_id', | ||
'name', | ||
'description', | ||
'category', | ||
'csf_function' | ||
]) | ||
}; | ||
const threatsTable: TableSource = { | ||
head: { ref_id: 'ref', name: 'name', description: 'description' }, | ||
body: tableSourceMapper(threats, ['ref_id', 'name', 'description']) | ||
}; | ||
function riskMatricesPreview(riskMatrices: []) { | ||
let riskMatricesDumps = []; | ||
let riskMatrixDump = { | ||
json_definition: '' | ||
}; | ||
for (const riskMatrix of riskMatrices) { | ||
riskMatrixDump['json_definition'] = JSON.stringify(riskMatrix); | ||
riskMatricesDumps.push(riskMatrixDump); | ||
} | ||
return riskMatricesDumps; | ||
} | ||
$: displayImportButton = !(data.library.is_loaded ?? true); | ||
async function handleSubmit(event: { currentTarget: EventTarget & HTMLFormElement }) { | ||
const data = new FormData(event.currentTarget); | ||
const response = await fetch(event.currentTarget.action, { | ||
method: 'POST', | ||
body: data | ||
}); | ||
const result: ActionResult = deserialize(await response.text()); | ||
if (result.type === 'success') { | ||
await invalidateAll(); | ||
} | ||
applyAction(result); | ||
} | ||
</script> | ||
|
||
<div class="card bg-white p-4 shadow space-y-4"> | ||
<div class="flex flex-col space-y-2"> | ||
<span class="w-full flex flex-row justify-between"> | ||
<h1 class="font-medium text-xl">{data.library.name}</h1> | ||
<div> | ||
{#if displayImportButton} | ||
{#if loading.form} | ||
<ProgressRadial width="w-6" meter="stroke-primary-500" /> | ||
{:else} | ||
<form | ||
method="post" | ||
action="/libraries/{data.library.id}?/load" | ||
use:enhance={() => { | ||
loading.form = true; | ||
loading.library = data.library.urn; | ||
return async ({ update }) => { | ||
loading.form = false; | ||
loading.library = ''; | ||
update(); | ||
}; | ||
}} | ||
on:submit={handleSubmit} | ||
> | ||
{#if $page.data.user.is_admin} | ||
<button type="submit" class="p-1 btn text-xl hover:text-primary-500"> | ||
<i class="fa-solid fa-file-import" /> | ||
</button> | ||
{/if} | ||
</form> | ||
{/if} | ||
{/if} | ||
</div> | ||
</span> | ||
<div class="space-y-1"> | ||
<p class="text-md leading-5 text-gray-700"> | ||
<strong>{m.description()}</strong>: {data.library.description} | ||
</p> | ||
<p class="text-md leading-5 text-gray-700"> | ||
<strong>{m.provider()}</strong>: {data.library.provider} | ||
</p> | ||
<p class="text-md leading-5 text-gray-700"> | ||
<strong>{m.packager()}</strong>: {data.library.packager} | ||
</p> | ||
<p class="text-md leading-5 text-gray-700"> | ||
<strong>{m.version()}</strong>: {data.library.version} | ||
</p> | ||
{#if data.library.publication_date} | ||
<p class="text-md leading-5 text-gray-700"> | ||
<strong>{m.publicationDate()}</strong>: {formatDateOrDateTime( | ||
data.library.publication_date, | ||
languageTag() | ||
)} | ||
</p> | ||
{/if} | ||
{#if data.library.dependencies} | ||
<p class="text-md leading-5 text-gray-700"> | ||
<strong>{m.dependencies()}</strong>: | ||
</p> | ||
<ul class="list-disc list-inside"> | ||
{#each data.library.dependencies as dependency} | ||
<li>{dependency.name}</li> | ||
{/each} | ||
</ul> | ||
{/if} | ||
{#if data.library.copyright} | ||
<p class="text-md leading-5 text-gray-700"> | ||
<strong>{m.copyright()}</strong>: {data.library.copyright} | ||
</p> | ||
{/if} | ||
</div> | ||
</div> | ||
|
||
{#if riskMatrices.length > 0} | ||
<Dropdown | ||
open={riskMatrices.length == 1} | ||
style="hover:text-indigo-700" | ||
icon="fa-solid fa-table-cells-large" | ||
header="{riskMatrices.length} {m.riskMatrices()}" | ||
> | ||
<ModelTable | ||
source={riskMatricesTable} | ||
displayActions={false} | ||
pagination={false} | ||
rowCount={false} | ||
rowsPerPage={false} | ||
search={false} | ||
interactive={false} | ||
/> | ||
{#each riskMatricesPreview(riskMatrices) as riskMatrix} | ||
<RiskMatrix {riskMatrix} {showRisks} wrapperClass="mt-8" /> | ||
{/each} | ||
</Dropdown> | ||
{/if} | ||
|
||
{#if referenceControls.length > 0} | ||
<Dropdown | ||
style="hover:text-indigo-700" | ||
icon="fa-solid fa-gears" | ||
header="{referenceControls.length} {m.referenceControls()}" | ||
> | ||
<ModelTable source={referenceControlsTable} displayActions={false} interactive={false} /> | ||
</Dropdown> | ||
{/if} | ||
|
||
{#if threats.length > 0} | ||
<Dropdown | ||
style="hover:text-indigo-700" | ||
icon="fa-solid fa-biohazard" | ||
header="{threats.length} {m.threats()}" | ||
> | ||
<ModelTable source={threatsTable} displayActions={false} interactive={false} /> | ||
</Dropdown> | ||
{/if} | ||
|
||
{#if framework} | ||
<h4 class="h4 font-medium">{m.framework()}</h4> | ||
{#await data.tree} | ||
<span data-testid="loading-field"> | ||
{m.loading()}... | ||
</span> | ||
{:then tree} | ||
<RecursiveTreeView | ||
nodes={transformToTreeView(Object.entries(tree))} | ||
hover="hover:bg-initial" | ||
/> | ||
{/await} | ||
{/if} | ||
</div> |
13 changes: 13 additions & 0 deletions
13
frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { PageLoad } from './$types'; | ||
|
||
export const load: PageLoad = async ({ fetch, params, url }) => { | ||
const endpoint = `/stored-libraries/${params.id}`; | ||
const queryParams = url.searchParams.toString(); | ||
const library = await fetch(`${endpoint}?${queryParams}`).then((res) => res.json()); | ||
|
||
return { | ||
tree: fetch(`${endpoint}/tree?${queryParams}`).then((res) => res.json()) ?? {}, | ||
library, | ||
title: library.name | ||
}; | ||
}; |
Oops, something went wrong.