diff --git a/src/locales/de-DE/messages.po b/src/locales/de-DE/messages.po index 9fec499b..8cb06a2c 100644 --- a/src/locales/de-DE/messages.po +++ b/src/locales/de-DE/messages.po @@ -429,7 +429,7 @@ msgstr "Produktstufe ändern" msgid "Change Type" msgstr "" -#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:42 +#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:69 msgid "Changes" msgstr "Änderungen" @@ -789,7 +789,7 @@ msgstr "Externe Verzeichnisse" msgid "External Id" msgstr "External Id" -#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:52 +#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:79 msgid "Failed to retrieve changelog" msgstr "Das Änderungsprotokoll konnte nicht abgerufen werden" @@ -825,7 +825,7 @@ msgstr "Findet Snapshots von Festplatten, die nicht mehr verwendet werden und m msgid "Fix scans your infrastructure and resource configurations by using read-only API access. No agents required." msgstr "Fix scannt Ihre Infrastruktur- und Ressourcenkonfigurationen mithilfe des schreibgeschützten API-Zugriffs. Keine Agenten erforderlich." -#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:48 +#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:46 msgid "Fixed issues" msgstr "Behobene Probleme" @@ -1126,7 +1126,7 @@ msgstr "Nachbarschaftsansicht" msgid "new improved resources in the past {since}" msgstr "neue verbesserte Ressourcen in der Vergangenheit {since}" -#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:65 +#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:63 msgid "New issues" msgstr "Neue Ausgaben" diff --git a/src/locales/en-US/messages.po b/src/locales/en-US/messages.po index e5eadcb9..14f221d8 100644 --- a/src/locales/en-US/messages.po +++ b/src/locales/en-US/messages.po @@ -429,7 +429,7 @@ msgstr "Change Product Tier" msgid "Change Type" msgstr "Change Type" -#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:42 +#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:69 msgid "Changes" msgstr "Changes" @@ -789,7 +789,7 @@ msgstr "External Directories" msgid "External Id" msgstr "External Id" -#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:52 +#: src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx:79 msgid "Failed to retrieve changelog" msgstr "Failed to retrieve changelog" @@ -825,7 +825,7 @@ msgstr "Finds snapshots of disks that are no longer in use, which potentially co msgid "Fix scans your infrastructure and resource configurations by using read-only API access. No agents required." msgstr "Fix scans your infrastructure and resource configurations by using read-only API access. No agents required." -#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:48 +#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:46 msgid "Fixed issues" msgstr "Fixed issues" @@ -1126,7 +1126,7 @@ msgstr "Neighborhood View" msgid "new improved resources in the past {since}" msgstr "new improved resources in the past {since}" -#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:65 +#: src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx:63 msgid "New issues" msgstr "New issues" diff --git a/src/pages/panel/inventory/resource-detail/ResourceDetail.tsx b/src/pages/panel/inventory/resource-detail/ResourceDetail.tsx index 9562a0e3..ee486fba 100644 --- a/src/pages/panel/inventory/resource-detail/ResourceDetail.tsx +++ b/src/pages/panel/inventory/resource-detail/ResourceDetail.tsx @@ -343,7 +343,9 @@ export const ResourceDetail = () => { nodeSecurityIssues={data.resource.security?.issues ?? []} /> ) : null} - {resourceDetailId && (!error || nodeNotFound) ? : null} + {resourceDetailId && (!error || nodeNotFound) ? ( + + ) : null} diff --git a/src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx b/src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx index 24d18f64..baad613a 100644 --- a/src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx +++ b/src/pages/panel/inventory/resource-detail/ResourceDetailChangeLog.tsx @@ -2,20 +2,21 @@ import { Trans } from '@lingui/macro' import { Timeline } from '@mui/lab' import { Accordion, AccordionDetails, Divider, Stack, Typography } from '@mui/material' import { useQuery } from '@tanstack/react-query' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useParams } from 'react-router-dom' import { useUserProfile } from 'src/core/auth' import { getWorkspaceInventoryNodeHistoryQuery } from 'src/pages/panel/shared/queries' import { Spinner } from 'src/shared/loading' import { StickyAccordionSummaryWithIcon } from 'src/shared/sticky-accordion-summary' -import { WorkspaceInventoryNodeHistory } from 'src/shared/types/server' +import { WorkspaceInventoryNode, WorkspaceInventoryNodeHistory } from 'src/shared/types/server' import { ResourceDetailChangeLogHistory, ResourceDetailChangeLogSelectedHistory } from './utils' interface ResourceDetailChangeLogProps { notFound?: boolean + defaultResource?: WorkspaceInventoryNode['resource'] } const severities = ['critical', 'high', 'medium', 'low', 'info'] -export const ResourceDetailChangeLog = ({ notFound }: ResourceDetailChangeLogProps) => { +export const ResourceDetailChangeLog = ({ notFound, defaultResource }: ResourceDetailChangeLogProps) => { const [expanded, setExpanded] = useState(false) const [[historyAnchorEl, selectedHistory], setHistory] = useState<[HTMLElement | null, WorkspaceInventoryNodeHistory | undefined]>([ null, @@ -23,19 +24,45 @@ export const ResourceDetailChangeLog = ({ notFound }: ResourceDetailChangeLogPro ]) const { selectedWorkspace } = useUserProfile() const { resourceDetailId } = useParams() - const { data, isLoading, error } = useQuery({ + const { + data: orgData, + isLoading, + isFetched, + error, + } = useQuery({ queryKey: ['workspace-inventory-node-history', selectedWorkspace?.id, resourceDetailId, undefined, undefined, undefined, undefined], queryFn: getWorkspaceInventoryNodeHistoryQuery, throwOnError: false, enabled: !!resourceDetailId && expanded, }) + const data = useMemo(() => { + if (isFetched && defaultResource) { + return orgData && orgData[orgData.length - 1]?.change === 'node_created' + ? orgData + : [ + ...(orgData ?? []), + { + change: 'node_created', + changed_at: defaultResource.reported.ctime, + created: defaultResource.reported.ctime, + id: Math.random().toString(), + metadata: defaultResource.metadata, + reported: defaultResource.reported, + revision: defaultResource.revision, + type: 'node', + updated: defaultResource.reported.ctime, + ancestors: defaultResource.ancestors, + } as WorkspaceInventoryNodeHistory, + ] + } + }, [isFetched, defaultResource, orgData]) useEffect(() => { if (notFound) { setExpanded(true) } }, [notFound]) const onClosePopup = () => setHistory((prev) => [null, prev[1]]) - return data?.length || isLoading || error || !expanded ? ( + return ( <> setExpanded(value)}> @@ -85,5 +112,5 @@ export const ResourceDetailChangeLog = ({ notFound }: ResourceDetailChangeLogPro selectedHistory={selectedHistory} /> - ) : null + ) } diff --git a/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistory.tsx b/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistory.tsx index eaeef489..019030df 100644 --- a/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistory.tsx +++ b/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistory.tsx @@ -77,14 +77,14 @@ export const ResourceDetailChangeLogSelectedHistory = ({ )) - ) : selectedHistory.change === 'node_created' || selectedHistory.change === 'node_deleted' ? ( + ) : selectedHistory.change === 'node_compliant' || selectedHistory.change === 'node_vulnerable' ? ( + + ) : ( {stringify(selectedHistory.reported, null, ' ')} - ) : ( - )} diff --git a/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx b/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx index b1642b5d..00fade19 100644 --- a/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx +++ b/src/pages/panel/inventory/resource-detail/utils/ResourceDetailChangeLogSelectedHistoryDiff.tsx @@ -5,15 +5,13 @@ import { useMemo } from 'react' import { useUserProfile } from 'src/core/auth' import { getWorkspaceInventoryReportChecksQuery } from 'src/pages/panel/shared/queries' import { useGetBenchmarks } from 'src/pages/panel/shared/utils' -import { FailedCheck, WorkspaceInventoryNodeHistory } from 'src/shared/types/server' +import { FailedCheck, WorkspaceInventoryNodeSecurityHistory } from 'src/shared/types/server' import { ResourceDetailChangeLogSelectedHistoryAccordion } from './ResourceDetailChangeLogSelectedHistoryAccordion' -type ResourceDetailChangeLogSelectedHistoryDiffProps = WorkspaceInventoryNodeHistory<'node_vulnerable'>['diff'] - export const ResourceDetailChangeLogSelectedHistoryDiff = ({ node_compliant = [], node_vulnerable = [], -}: ResourceDetailChangeLogSelectedHistoryDiffProps) => { +}: WorkspaceInventoryNodeSecurityHistory['diff']) => { const { selectedWorkspace } = useUserProfile() const { checkIds, benchmarksIds } = useMemo( () => ({ diff --git a/src/shared/types/server/responses/GetWorkspaceInventoryNodeHistory.ts b/src/shared/types/server/responses/GetWorkspaceInventoryNodeHistory.ts index 866e2e12..f21d6c3f 100644 --- a/src/shared/types/server/responses/GetWorkspaceInventoryNodeHistory.ts +++ b/src/shared/types/server/responses/GetWorkspaceInventoryNodeHistory.ts @@ -9,25 +9,40 @@ export type WorkspaceInventoryNodeHistoryDiff = { benchmarks: string[] } -export interface WorkspaceInventoryNodeHistory { +type WorkspaceInventoryNodeHistoryBase = { id: string type: 'node' revision: string reported: NodeReported - before: NodeChange extends 'node_updated' ? NodeReported : never - security: NodeChange extends 'node_vulnerable' | 'node_compliant' ? NodeSecurity : never metadata: NodeMetadata - diff: NodeChange extends 'node_vulnerable' | 'node_compliant' - ? { - node_compliant?: WorkspaceInventoryNodeHistoryDiff[] - node_vulnerable?: WorkspaceInventoryNodeHistoryDiff[] - } - : never ancestors?: NodeAncestors - change: NodeChange + change: WorkspaceInventoryNodeHistoryChanges changed_at: string created: string updated: string } +interface WorkspaceInventoryNodeExistedHistory extends WorkspaceInventoryNodeHistoryBase { + change: 'node_created' | 'node_deleted' +} + +interface WorkspaceInventoryNodeUpdatedHistory extends WorkspaceInventoryNodeHistoryBase { + change: 'node_updated' + before: NodeReported +} + +export interface WorkspaceInventoryNodeSecurityHistory extends WorkspaceInventoryNodeHistoryBase { + change: 'node_vulnerable' | 'node_compliant' + security: NodeSecurity + diff: { + node_compliant?: WorkspaceInventoryNodeHistoryDiff[] + node_vulnerable?: WorkspaceInventoryNodeHistoryDiff[] + } +} + +export type WorkspaceInventoryNodeHistory = + | WorkspaceInventoryNodeExistedHistory + | WorkspaceInventoryNodeUpdatedHistory + | WorkspaceInventoryNodeSecurityHistory + export type GetWorkspaceInventoryNodeHistoryResponse = WorkspaceInventoryNodeHistory[] diff --git a/src/shared/types/server/responses/index.ts b/src/shared/types/server/responses/index.ts index 808ea8b9..43166b4d 100644 --- a/src/shared/types/server/responses/index.ts +++ b/src/shared/types/server/responses/index.ts @@ -18,6 +18,7 @@ export type { WorkspaceInventoryNodeHistory, WorkspaceInventoryNodeHistoryChanges, WorkspaceInventoryNodeHistoryDiff, + WorkspaceInventoryNodeSecurityHistory, } from './GetWorkspaceInventoryNodeHistory' export type { GetWorkspaceInventoryNodeNeighborhoodResponse,