Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@codemirror/view": "^6.9.6",
"@harnessio/design-system": "^2.1.1",
"@harnessio/icons": "^2.1.18",
"@harnessio/react-har-service-client": "0.49.0",
"@harnessio/react-har-service-client": "0.50.0",
"@harnessio/react-ng-manager-client": "^1.40.0",
"@harnessio/react-ssca-manager-client": "^0.65.0",
"@harnessio/uicore": "^4.3.4",
Expand Down
4 changes: 4 additions & 0 deletions web/src/ar/MFEAppTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import type React from 'react'
import type { PermissionIdentifier, ResourceType } from '@ar/common/permissionTypes'
import type RbacButton from '@ar/__mocks__/components/RbacButton'
import type RbacMenuItem from '@ar/__mocks__/components/RbacMenuItem'
import type OssOverviewView from '@ar/__mocks__/components/OssOverviewView'
import type NGBreadcrumbs from '@ar/__mocks__/components/NGBreadcrumbs'
import type PageNotPublic from '@ar/__mocks__/components/PageNotPublic'
import type DependencyView from '@ar/__mocks__/components/DependencyView'
import type SecretFormInput from '@ar/__mocks__/components/SecretFormInput'
import type VulnerabilityView from '@ar/__mocks__/components/VulnerabilityView'
import type OssVulnerabilitiesView from '@ar/__mocks__/components/OssVulnerabilitiesView'
import type PolicySetFixedTypeSelector from '@ar/__mocks__/components/PolicySetFixedTypeSelector'
import type {
ModalProvider,
Expand Down Expand Up @@ -106,6 +108,8 @@ export interface CustomComponents {
SecretFormInput: typeof SecretFormInput
VulnerabilityView: typeof VulnerabilityView
DependencyView: typeof DependencyView
OssOverviewView: typeof OssOverviewView
OssVulnerabilitiesView: typeof OssVulnerabilitiesView
PolicySetFixedTypeSelector: typeof PolicySetFixedTypeSelector
PageNotPublic: typeof PageNotPublic
}
Expand Down
26 changes: 26 additions & 0 deletions web/src/ar/__mocks__/components/OssOverviewView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React from 'react'

interface OssSbomOverviewViewProps {
purl: string
onViewVulnerabilities: () => void
}

export default function OssOverviewView(_props: OssSbomOverviewViewProps) {
return <>Mock Oss Overview View</>
}
25 changes: 25 additions & 0 deletions web/src/ar/__mocks__/components/OssVulnerabilitiesView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React from 'react'

interface OssSbomVulnerabilitiesViewProps {
purl: string
}

export default function OssVulnerabilitiesView(_props: OssSbomVulnerabilitiesViewProps) {
return <>Mock Oss Vulnerabilities View</>
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderConte
import VersionTreeNode from '../components/VersionTreeNode/VersionTreeNode'
import VersionDetailsTabs from '../components/VersionDetailsTabs/VersionDetailsTabs'
import DartVersionOverviewPage from './pages/overview/ComposerVersionOverviewPage'
import ScanDetailsPage from '../components/ScanDetailsPage/ScanDetailsPage'

export class ComposerVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.COMPOSER
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
VersionDetailsTab.EVALUATION_DETAILS,
VersionDetailsTab.CODE
]

Expand Down Expand Up @@ -109,6 +111,8 @@ export class ComposerVersionType extends VersionStep<ArtifactVersionSummary> {
<DartVersionArtifactDetailsPage />
</VersionOverviewProvider>
)
case VersionDetailsTab.EVALUATION_DETAILS:
return <ScanDetailsPage />
case VersionDetailsTab.OSS:
return (
<VersionOverviewProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ export const mockDockerVersionSummary: ArtifactVersionSummaryResponseResponse =
stoPipelineId: 'HARNESS_ARTIFACT_SCAN_PIPELINE',
version: '1.0.0',
uuid: 'uuid',
registryUUID: 'uuid'
registryUUID: 'uuid',
purl: 'test'
},
status: 'SUCCESS'
}
Expand All @@ -98,7 +99,8 @@ export const mockDockerVersionSummaryWithoutSscaAndStoData: ArtifactVersionSumma
packageType: 'DOCKER',
version: '1.0.0',
uuid: 'uuid',
registryUUID: 'uuid'
registryUUID: 'uuid',
purl: 'test'
},
status: 'SUCCESS'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export const mockGenericVersionSummary: ArtifactVersionSummaryResponseResponse =
packageType: 'GENERIC',
version: '1.0.0',
uuid: 'uuid',
registryUUID: 'uuid'
registryUUID: 'uuid',
purl: 'test'
},
status: 'SUCCESS'
}
Expand Down
4 changes: 4 additions & 0 deletions web/src/ar/pages/version-details/GoVersion/GoVersionType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ import GoVersionArtifactDetailsPage from './pages/artifact-dertails/GoVersionArt
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionTreeNode from '../components/VersionTreeNode/VersionTreeNode'
import VersionDetailsTabs from '../components/VersionDetailsTabs/VersionDetailsTabs'
import ScanDetailsPage from '../components/ScanDetailsPage/ScanDetailsPage'

export class GoVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.GO
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
VersionDetailsTab.EVALUATION_DETAILS,
VersionDetailsTab.CODE
]

Expand Down Expand Up @@ -109,6 +111,8 @@ export class GoVersionType extends VersionStep<ArtifactVersionSummary> {
<GoVersionArtifactDetailsPage />
</VersionOverviewProvider>
)
case VersionDetailsTab.EVALUATION_DETAILS:
return <ScanDetailsPage />
case VersionDetailsTab.OSS:
return (
<VersionOverviewProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export const mockHelmVersionSummary: ArtifactVersionSummaryResponseResponse = {
packageType: 'HELM',
version: '1.0.0',
uuid: 'uuid',
registryUUID: 'uuid'
registryUUID: 'uuid',
purl: 'test'
},
status: 'SUCCESS'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFi
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionActions from '../components/VersionActions/VersionActions'
import { VersionAction } from '../components/VersionActions/types'
import ScanDetailsPage from '../components/ScanDetailsPage/ScanDetailsPage'

export class MavenVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.MAVEN
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
VersionDetailsTab.EVALUATION_DETAILS,
VersionDetailsTab.CODE
]

Expand Down Expand Up @@ -100,6 +102,8 @@ export class MavenVersionType extends VersionStep<ArtifactVersionSummary> {
<ArtifactFilesContent />
</VersionFilesProvider>
)
case VersionDetailsTab.EVALUATION_DETAILS:
return <ScanDetailsPage />
case VersionDetailsTab.OSS:
return <OSSContentPage />
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export const mockMavenVersionSummary: ArtifactVersionSummaryResponseResponse = {
packageType: 'MAVEN',
version: '1.0.0',
uuid: 'uuid',
registryUUID: 'uuid'
registryUUID: 'uuid',
purl: 'test'
},
status: 'SUCCESS'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderConte
import VersionFilesProvider from '../context/VersionFilesProvider'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import { VersionAction } from '../components/VersionActions/types'
import ScanDetailsPage from '../components/ScanDetailsPage/ScanDetailsPage'

export class NpmVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.NPM
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
VersionDetailsTab.EVALUATION_DETAILS,
VersionDetailsTab.CODE
]

Expand Down Expand Up @@ -100,6 +102,8 @@ export class NpmVersionType extends VersionStep<ArtifactVersionSummary> {
return <NpmVersionOverviewPage />
case VersionDetailsTab.ARTIFACT_DETAILS:
return <NpmVersionArtifactDetailsPage />
case VersionDetailsTab.EVALUATION_DETAILS:
return <ScanDetailsPage />
case VersionDetailsTab.OSS:
return (
<Layout.Vertical spacing="xlarge">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ import VersionFilesProvider from '../context/VersionFilesProvider'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import { VersionAction } from '../components/VersionActions/types'
import VersionOverviewProvider from '../context/VersionOverviewProvider'
import ScanDetailsPage from '../components/ScanDetailsPage/ScanDetailsPage'

export class NuGetVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.NUGET
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
VersionDetailsTab.EVALUATION_DETAILS,
VersionDetailsTab.CODE
]

Expand Down Expand Up @@ -109,6 +111,8 @@ export class NuGetVersionType extends VersionStep<ArtifactVersionSummary> {
<NuGetVersionArtifactDetailsPage />
</VersionOverviewProvider>
)
case VersionDetailsTab.EVALUATION_DETAILS:
return <ScanDetailsPage />
case VersionDetailsTab.OSS:
return (
<VersionOverviewProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderConte
import VersionFilesProvider from '../context/VersionFilesProvider'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import { VersionAction } from '../components/VersionActions/types'
import ScanDetailsPage from '../components/ScanDetailsPage/ScanDetailsPage'

export class PythonVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.PYTHON
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
VersionDetailsTab.EVALUATION_DETAILS,
VersionDetailsTab.CODE
]

Expand Down Expand Up @@ -101,6 +103,8 @@ export class PythonVersionType extends VersionStep<ArtifactVersionSummary> {
return <PythonVersionOverviewPage />
case VersionDetailsTab.ARTIFACT_DETAILS:
return <PythonVersionArtifactDetailsPage />
case VersionDetailsTab.EVALUATION_DETAILS:
return <ScanDetailsPage />
case VersionDetailsTab.OSS:
return (
<Layout.Vertical spacing="xlarge">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ import RPMVersionArtifactDetailsPage from './pages/artifact-dertails/RPMVersionA
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionTreeNode from '../components/VersionTreeNode/VersionTreeNode'
import VersionDetailsTabs from '../components/VersionDetailsTabs/VersionDetailsTabs'
import ScanDetailsPage from '../components/ScanDetailsPage/ScanDetailsPage'

export class RPMVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.RPM
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
VersionDetailsTab.EVALUATION_DETAILS,
VersionDetailsTab.CODE
]

Expand Down Expand Up @@ -109,6 +111,8 @@ export class RPMVersionType extends VersionStep<ArtifactVersionSummary> {
<RPMVersionArtifactDetailsPage />
</VersionOverviewProvider>
)
case VersionDetailsTab.EVALUATION_DETAILS:
return <ScanDetailsPage />
case VersionDetailsTab.OSS:
return (
<VersionOverviewProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React, { useContext, useState } from 'react'
import { Container, Layout } from '@harnessio/uicore'

import { useParentComponents } from '@ar/hooks'
import { useStrings } from '@ar/frameworks/strings'
import { ButtonTab, ButtonTabs } from '@ar/components/ButtonTabs/ButtonTabs'
import { VersionProviderContext } from '@ar/pages/version-details/context/VersionProvider'

import { ScanStatusDetailsTabEnum } from './types'

function ScanDetailsPage() {
const [selectedTab, setSelectedTab] = useState<ScanStatusDetailsTabEnum>(ScanStatusDetailsTabEnum.Overview)
const { data } = useContext(VersionProviderContext)
const { purl = '' } = data || {}
const { OssOverviewView, OssVulnerabilitiesView } = useParentComponents()
Comment on lines +29 to +31

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against rendering child views when purl is empty/undefined.

data || {} + purl = '' means that when context data hasn't populated yet (or has no purl), both OssOverviewView and OssVulnerabilitiesView receive an empty string. This may trigger API calls with an invalid key inside the injected MFE components before the data is ready.

🛡️ Suggested guard
  const { data } = useContext(VersionProviderContext)
- const { purl = '' } = data || {}
+ const { purl } = data || {}
  const { OssOverviewView, OssVulnerabilitiesView } = useParentComponents()
  const { getString } = useStrings()
+ if (!purl) return null  // or a spinner/loading state
  return (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@web/src/ar/pages/version-details/components/ScanDetailsPage/ScanDetailsPage.tsx`
around lines 29 - 31, The child MFE views (OssOverviewView,
OssVulnerabilitiesView) are being rendered/passed a purl when
VersionProviderContext.data may be missing or purl is an empty string; update
ScanDetailsPage to guard rendering by checking the resolved purl (from data via
VersionProviderContext) and only render or pass props to OssOverviewView and
OssVulnerabilitiesView when purl is a non-empty string (e.g., conditional render
or early return when !purl), ensuring you do not pass the empty default '' into
those components and preventing premature API calls inside the injected MFEs.

const { getString } = useStrings()
return (
<Layout.Vertical padding="large" spacing="large">
<ButtonTabs small bold selectedTabId={selectedTab} onChange={setSelectedTab}>
<ButtonTab
id={ScanStatusDetailsTabEnum.Overview}
icon="document"
iconProps={{ size: 12 }}
Comment on lines +38 to +39

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Both tabs use the same "document" icon — likely a placeholder.

Overview and Vulnerabilities tabs share icon="document". Distinct icons (e.g., "eye-open" for Overview, "warning-sign" for Vulnerabilities) would better communicate tab intent.

Also applies to: 56-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@web/src/ar/pages/version-details/components/ScanDetailsPage/ScanDetailsPage.tsx`
around lines 38 - 39, Tabs in ScanDetailsPage.tsx both use the same placeholder
icon ("document"); update the tab icon props to use distinct, meaningful icons:
change the Overview tab's icon prop from "document" to "eye-open" and change the
Vulnerabilities tab's icon prop from "document" to "warning-sign" (ensure
iconProps remains unchanged); make the same replacements for the repeated tab
definition later in the file where icon="document" appears.

panel={
<Container>
{OssOverviewView ? (
<OssOverviewView
purl={purl}
onViewVulnerabilities={() => setSelectedTab(ScanStatusDetailsTabEnum.Vulnerabilities)}
/>
) : (
getString('tabNotFound')
)}
</Container>
}
title={getString('versionDetails.securityTests.tabs.overview')}
/>
<ButtonTab
id={ScanStatusDetailsTabEnum.Vulnerabilities}
icon="document"
iconProps={{ size: 12 }}
panel={
<Container>
{OssVulnerabilitiesView ? <OssVulnerabilitiesView purl={purl} /> : getString('tabNotFound')}
</Container>
}
title={getString('versionDetails.securityTests.tabs.vulnerabilities')}
/>
</ButtonTabs>
</Layout.Vertical>
)
}

export default ScanDetailsPage
Loading