diff --git a/frontend/src/lib/components/ModelTable/LibraryActions.svelte b/frontend/src/lib/components/ModelTable/LibraryActions.svelte index 9e61d1cce..5be542d6b 100644 --- a/frontend/src/lib/components/ModelTable/LibraryActions.svelte +++ b/frontend/src/lib/components/ModelTable/LibraryActions.svelte @@ -51,7 +51,7 @@
{ loading.form = true; loading.library = library.urn; @@ -101,7 +101,7 @@ { loading.form = true; loading.library = library.urn; diff --git a/frontend/src/lib/utils/crud.ts b/frontend/src/lib/utils/crud.ts index 2b63e74a1..dfc434b8f 100644 --- a/frontend/src/lib/utils/crud.ts +++ b/frontend/src/lib/utils/crud.ts @@ -753,18 +753,14 @@ export const FIELD_COMPONENT_MAP = { evidences: { attachment: EvidenceFilePreview }, - libraries: { - locales: LanguageDisplay, + 'stored-libraries': { + locale: LanguageDisplay, [CUSTOM_ACTIONS_COMPONENT]: LibraryActions }, - // "stored-libraries": { - // locale: LanguageDisplay, - // [CUSTOM_ACTIONS_COMPONENT]: LibraryActions - // }, - // "loaded-libraries": { - // locale: LanguageDisplay - // // [CUSTOM_ACTIONS_COMPONENT]: LibraryActions - // }, + 'loaded-libraries': { + locale: LanguageDisplay + // [CUSTOM_ACTIONS_COMPONENT]: LibraryActions + }, 'user-groups': { localization_dict: UserGroupNameDisplay } diff --git a/frontend/src/lib/utils/types.ts b/frontend/src/lib/utils/types.ts index f61e0d86f..6736c3d9a 100644 --- a/frontend/src/lib/utils/types.ts +++ b/frontend/src/lib/utils/types.ts @@ -48,6 +48,8 @@ export const URL_MODEL = [ 'frameworks', 'requirements', 'requirement-assessments', + 'stored-libraries', + 'loaded-libraries', 'libraries', 'sso-settings', 'general-settings', diff --git a/frontend/src/routes/(app)/(internal)/libraries/+page.server.ts b/frontend/src/routes/(app)/(internal)/libraries/+page.server.ts index 5e2c85dd6..c5c51956c 100644 --- a/frontend/src/routes/(app)/(internal)/libraries/+page.server.ts +++ b/frontend/src/routes/(app)/(internal)/libraries/+page.server.ts @@ -15,8 +15,8 @@ import { safeTranslate } from '$lib/utils/i18n'; import { nestedDeleteFormAction } from '$lib/utils/actions'; export const load = (async ({ fetch }) => { - const stored_libraries_endpoint = `${BASE_API_URL}/stored-libraries/`; - const loaded_libaries_endpoint = `${BASE_API_URL}/loaded-libraries/`; + const stored_libraries_endpoint = `${BASE_API_URL}/stored-libraries/?limit=5000`; + const loaded_libaries_endpoint = `${BASE_API_URL}/loaded-libraries/?limit=5000`; const [stored_libraries_res, loaded_libaries_res] = await Promise.all([ fetch(stored_libraries_endpoint), diff --git a/frontend/src/routes/(app)/(internal)/libraries/+page.svelte b/frontend/src/routes/(app)/(internal)/libraries/+page.svelte index c1f85722d..721a1a26a 100644 --- a/frontend/src/routes/(app)/(internal)/libraries/+page.svelte +++ b/frontend/src/routes/(app)/(internal)/libraries/+page.svelte @@ -54,7 +54,7 @@ @@ -63,7 +63,7 @@ { - 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 - ); - }, update: async (event) => { const endpoint = `${BASE_API_URL}/loaded-libraries/${event.params.id}/update/`; const res = await event.fetch(endpoint); // We will have to make this a PATCH later (we should use PATCH when modifying an object) diff --git a/frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+page.svelte similarity index 100% rename from frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+page.svelte rename to frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+page.svelte diff --git a/frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+page.ts b/frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+page.ts similarity index 87% rename from frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+page.ts rename to frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+page.ts index 7e62b5f40..707378dca 100644 --- a/frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+page.ts +++ b/frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+page.ts @@ -1,7 +1,7 @@ import type { PageLoad } from './$types'; export const load: PageLoad = async ({ fetch, params, url }) => { - const endpoint = `/libraries/${params.id}`; + const endpoint = `/loaded-libraries/${params.id}`; const queryParams = url.searchParams.toString(); const library = await fetch(`${endpoint}?${queryParams}`).then((res) => res.json()); diff --git a/frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+server.ts b/frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+server.ts similarity index 87% rename from frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+server.ts rename to frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+server.ts index d139db160..5615e2908 100644 --- a/frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/+server.ts +++ b/frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/+server.ts @@ -4,8 +4,7 @@ import { error, type NumericRange } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; export const GET: RequestHandler = async ({ fetch, url, params }) => { - const isLoaded = url.searchParams.has('loaded'); - const URLModel = isLoaded ? 'loaded-libraries' : 'stored-libraries'; + const URLModel = 'loaded-libraries'; const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/`; const contentEndpoint = `${BASE_API_URL}/${URLModel}/${params.id}/content/`; diff --git a/frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/tree/+server.ts b/frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/tree/+server.ts similarity index 85% rename from frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/tree/+server.ts rename to frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/tree/+server.ts index f2e2f9421..aa85de722 100644 --- a/frontend/src/routes/(app)/(internal)/libraries/[id=uuid]/tree/+server.ts +++ b/frontend/src/routes/(app)/(internal)/loaded-libraries/[id=uuid]/tree/+server.ts @@ -4,7 +4,7 @@ import { error, type NumericRange } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; export const GET: RequestHandler = async ({ fetch, params, url }) => { - const URLModel = url.searchParams.has('loaded') ? 'loaded-libraries' : 'stored-libraries'; + const URLModel = 'loaded-libraries'; const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/tree`; const res = await fetch(endpoint); diff --git a/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.server.ts b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.server.ts new file mode 100644 index 000000000..cf1351c19 --- /dev/null +++ b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.server.ts @@ -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 + ); + } +}; diff --git a/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.svelte b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.svelte new file mode 100644 index 000000000..7a6dc56ca --- /dev/null +++ b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.svelte @@ -0,0 +1,225 @@ + + +
+
+ +

{data.library.name}

+
+ {#if displayImportButton} + {#if loading.form} + + {:else} + { + 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} + + {/if} + + {/if} + {/if} +
+
+
+

+ {m.description()}: {data.library.description} +

+

+ {m.provider()}: {data.library.provider} +

+

+ {m.packager()}: {data.library.packager} +

+

+ {m.version()}: {data.library.version} +

+ {#if data.library.publication_date} +

+ {m.publicationDate()}: {formatDateOrDateTime( + data.library.publication_date, + languageTag() + )} +

+ {/if} + {#if data.library.dependencies} +

+ {m.dependencies()}: +

+
    + {#each data.library.dependencies as dependency} +
  • {dependency.name}
  • + {/each} +
+ {/if} + {#if data.library.copyright} +

+ {m.copyright()}: {data.library.copyright} +

+ {/if} +
+
+ + {#if riskMatrices.length > 0} + + + {#each riskMatricesPreview(riskMatrices) as riskMatrix} + + {/each} + + {/if} + + {#if referenceControls.length > 0} + + + + {/if} + + {#if threats.length > 0} + + + + {/if} + + {#if framework} +

{m.framework()}

+ {#await data.tree} + + {m.loading()}... + + {:then tree} + + {/await} + {/if} +
diff --git a/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.ts b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.ts new file mode 100644 index 000000000..9ac9b9738 --- /dev/null +++ b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+page.ts @@ -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 + }; +}; diff --git a/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+server.ts b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+server.ts new file mode 100644 index 000000000..ab1c06089 --- /dev/null +++ b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/+server.ts @@ -0,0 +1,25 @@ +import { BASE_API_URL } from '$lib/utils/constants'; + +import { error, type NumericRange } from '@sveltejs/kit'; +import type { RequestHandler } from './$types'; + +export const GET: RequestHandler = async ({ fetch, url, params }) => { + const URLModel = 'stored-libraries'; + const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/`; + const contentEndpoint = `${BASE_API_URL}/${URLModel}/${params.id}/content/`; + + const [res, contentRes] = await Promise.all([fetch(endpoint), fetch(contentEndpoint)]); + + if (!res.ok) error(res.status as NumericRange<400, 599>, await res.json()); + if (!contentRes.ok) error(contentRes.status as NumericRange<400, 599>, await contentRes.json()); + + const data = await res.json(); + const content = await contentRes.json(); + data.objects = content; + + return new Response(JSON.stringify(data), { + headers: { + 'Content-Type': 'application/json' + } + }); +}; diff --git a/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/tree/+server.ts b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/tree/+server.ts new file mode 100644 index 000000000..3dff2e0ba --- /dev/null +++ b/frontend/src/routes/(app)/(internal)/stored-libraries/[id=uuid]/tree/+server.ts @@ -0,0 +1,19 @@ +import { BASE_API_URL } from '$lib/utils/constants'; + +import { error, type NumericRange } from '@sveltejs/kit'; +import type { RequestHandler } from './$types'; + +export const GET: RequestHandler = async ({ fetch, params, url }) => { + const URLModel = 'stored-libraries'; + const endpoint = `${BASE_API_URL}/${URLModel}/${params.id}/tree`; + const res = await fetch(endpoint); + + if (!res.ok) error(res.status as NumericRange<400, 599>, await res.json()); + + const tree = await res.json(); + return new Response(JSON.stringify(tree), { + headers: { + 'Content-Type': 'application/json' + } + }); +};