diff --git a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html index d9102ef01..2dd2e71c1 100644 --- a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html +++ b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.html @@ -28,7 +28,7 @@ {{'VULNERABILITY.GRID.COLUMN_PACKAGE' | translate}} {{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}} {{'VULNERABILITY.GRID.COLUMN_FIXED' | translate}} - + {{'VULNERABILITY.GRID.IN_ALLOW_LIST' | translate}} {{'VULNERABILITY.STATE.OTHER_STATUS' | translate}} @@ -67,6 +67,9 @@ {{res.fix_version}} + + {{(isInAllowList(res.id)?"TAG_RETENTION.YES":"TAG_RETENTION.NO") | translate}} + {{'VULNERABILITY.GRID.COLUMN_DESCRIPTION' | translate}}: {{res.description}} diff --git a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts index c25009e81..eac55394b 100644 --- a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts +++ b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.spec.ts @@ -6,11 +6,20 @@ import { AdditionsService } from "../additions.service"; import { of } from "rxjs"; import { TranslateFakeLoader, TranslateLoader, TranslateModule } from "@ngx-translate/core"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { ScanningResultService, UserPermissionService, VulnerabilityItem } from "../../../../../../lib/services"; +import { + ProjectService, + ScanningResultService, + SystemInfoService, + UserPermissionService, + VulnerabilityItem +} from "../../../../../../lib/services"; import { AdditionLink } from "../../../../../../../ng-swagger-gen/models/addition-link"; import { ErrorHandler } from "../../../../../../lib/utils/error-handler"; import { ChannelService } from "../../../../../../lib/services/channel.service"; import { DEFAULT_SUPPORTED_MIME_TYPE } from "../../../../../../lib/utils/utils"; +import {SessionService} from "../../../../../shared/session.service"; +import {SessionUser} from "../../../../../shared/session-user"; +import {delay} from "rxjs/operators"; describe('ArtifactVulnerabilitiesComponent', () => { @@ -65,6 +74,34 @@ describe('ArtifactVulnerabilitiesComponent', () => { } } }; + const mockedUser: SessionUser = { + user_id: 1, + username: 'admin', + email: 'harbor@vmware.com', + realname: 'admin', + has_admin_role: true, + comment: 'no comment' + }; + const fakedSessionService = { + getCurrentUser() { + return mockedUser; + } + }; + const fakedProjectService = { + getProject() { + return of({ + name: 'test', + metadata: { + reuse_sys_cve_allowlist: "false" + }, + cve_allowlist: { + items: [ + {cve_id: "123"} + ] + } + }).pipe(delay(0)); + } + }; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -80,10 +117,13 @@ describe('ArtifactVulnerabilitiesComponent', () => { declarations: [ArtifactVulnerabilitiesComponent], providers: [ ErrorHandler, + SystemInfoService, {provide: AdditionsService, useValue: fakedAdditionsService}, {provide: UserPermissionService, useValue: fakedUserPermissionService}, {provide: ScanningResultService, useValue: fakedScanningResultService}, {provide: ChannelService, useValue: fakedChannelService}, + {provide: SessionService, useValue: fakedSessionService}, + {provide: ProjectService, useValue: fakedProjectService}, ], schemas: [ NO_ERRORS_SCHEMA @@ -111,4 +151,14 @@ describe('ArtifactVulnerabilitiesComponent', () => { const rows = fixture.nativeElement.getElementsByTagName('clr-dg-row'); expect(rows.length).toEqual(2); }); + it("should show column 'Listed In CVE Allowlist'", async () => { + fixture.autoDetectChanges(true); + await fixture.whenStable(); + const cols = fixture.nativeElement.querySelectorAll("clr-dg-column"); + expect(cols).toBeTruthy(); + expect(cols.length).toEqual(6); + const firstRow = fixture.nativeElement.querySelector("clr-dg-row"); + const cells = firstRow.querySelectorAll("clr-dg-cell"); + expect(cells[cells.length - 1].innerText).toEqual("TAG_RETENTION.YES"); + }); }); diff --git a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts index 5edbb3561..7e5ba4df2 100644 --- a/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts +++ b/src/portal/src/app/project/repository/artifact/artifact-additions/artifact-vulnerabilities/artifact-vulnerabilities.component.ts @@ -4,8 +4,9 @@ import { ClrDatagridComparatorInterface, ClrLoadingState } from "@clr/angular"; import { finalize } from "rxjs/operators"; import { AdditionLink } from "../../../../../../../ng-swagger-gen/models/addition-link"; import { + ProjectService, ScannerVo, - ScanningResultService, + ScanningResultService, SystemInfoService, UserPermissionService, USERSTATICPERMISSION, VulnerabilityItem @@ -20,6 +21,7 @@ import { ChannelService } from "../../../../../../lib/services/channel.service"; import { ResultBarChartComponent } from "../../../vulnerability-scanning/result-bar-chart.component"; import { Subscription } from "rxjs"; import { Artifact } from "../../../../../../../ng-swagger-gen/models/artifact"; +import {SessionService} from "../../../../../shared/session.service"; @Component({ selector: 'hbr-artifact-vulnerabilities', @@ -53,12 +55,16 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy { resultBarChartComponent: ResultBarChartComponent; sub: Subscription; hasViewInitWithDelay: boolean = false; + currentCVEList: Array<{ "cve_id": string; }> = []; constructor( private errorHandler: ErrorHandler, private additionsService: AdditionsService, private userPermissionService: UserPermissionService, private scanningService: ScanningResultService, private channel: ChannelService, + private session: SessionService, + private projectService: ProjectService, + private systemInfoService: SystemInfoService, ) { const that = this; this.severitySort = { @@ -80,6 +86,10 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy { setTimeout(() => { this.hasViewInitWithDelay = true; }, 0); + if (this.isSystemAdmin()) { + // get system and project CVE allow list + this.getCurrentCVEAllowList(); + } } ngOnDestroy() { if (this.sub) { @@ -194,4 +204,37 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy { } return null; } + isSystemAdmin(): boolean { + const account = this.session.getCurrentUser(); + return account && account.has_admin_role; + } + getCurrentCVEAllowList() { + this.projectService.getProject(this.projectId).subscribe( + projectRes => { + if (projectRes && projectRes.cve_allowlist + && projectRes.metadata && projectRes.metadata.reuse_sys_cve_allowlist !== "true" + ) { // use project CVE allow list + this.currentCVEList = projectRes.cve_allowlist['items']; + } else { // use system CVE allow list + this.systemInfoService.getSystemAllowlist().subscribe( + systemRes => { + if (systemRes && systemRes.items && systemRes.items.length) { + this.currentCVEList = systemRes.items; + } + } + ); + } + } + ); + } + isInAllowList(CVEId: string): boolean { + if (this.currentCVEList && this.currentCVEList.length) { + for (let i = 0; i < this.currentCVEList.length; i++) { + if (CVEId === this.currentCVEList[i].cve_id) { + return true; + } + } + } + return false; + } } diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index aba6a278c..6ac9b6d6f 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -1016,7 +1016,8 @@ "COLUMN_FIXED": "Fixed in version", "COLUMN_DESCRIPTION": "Description", "FOOT_ITEMS": "Items", - "FOOT_OF": "of" + "FOOT_OF": "of", + "IN_ALLOW_LIST": "Listed In CVE Allowlist" }, "CHART": { "SCANNING_TIME": "Scan completed time:", diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index 68740fdd9..cc7607829 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -1016,7 +1016,8 @@ "COLUMN_FIXED": "Fixed in version", "COLUMN_DESCRIPTION": "Description", "FOOT_ITEMS": "Items", - "FOOT_OF": "of" + "FOOT_OF": "of", + "IN_ALLOW_LIST": "Listed In CVE Allowlist" }, "CHART": { "SCANNING_TIME": "Scan completed time:", diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index 0b46878c6..790522503 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -989,7 +989,8 @@ "COLUMN_FIXED": "Fixé dans le version", "COLUMN_DESCRIPTION": "Description", "FOOT_ITEMS": "Items", - "FOOT_OF": "de" + "FOOT_OF": "de", + "IN_ALLOW_LIST": "Listed In CVE Allowlist" }, "CHART": { "SCANNING_TIME": "Temps d'analyse complète :", diff --git a/src/portal/src/i18n/lang/pt-br-lang.json b/src/portal/src/i18n/lang/pt-br-lang.json index cc174b33a..0d9f5c44c 100644 --- a/src/portal/src/i18n/lang/pt-br-lang.json +++ b/src/portal/src/i18n/lang/pt-br-lang.json @@ -1012,7 +1012,8 @@ "COLUMN_FIXED": "Corrigido na versão", "COLUMN_DESCRIPTION": "Descrição", "FOOT_ITEMS": "Itens", - "FOOT_OF": "de" + "FOOT_OF": "de", + "IN_ALLOW_LIST": "Listed In CVE Allowlist" }, "CHART": { "SCANNING_TIME": "Tempo de conclusão da análise:", diff --git a/src/portal/src/i18n/lang/tr-tr-lang.json b/src/portal/src/i18n/lang/tr-tr-lang.json index adb2f6211..96dccacb3 100644 --- a/src/portal/src/i18n/lang/tr-tr-lang.json +++ b/src/portal/src/i18n/lang/tr-tr-lang.json @@ -1016,7 +1016,8 @@ "COLUMN_FIXED": "Sürümde düzeltildi", "COLUMN_DESCRIPTION": "Açıklama", "FOOT_ITEMS": "Öğeler", - "FOOT_OF": "of" + "FOOT_OF": "of", + "IN_ALLOW_LIST": "Listed In CVE Allowlist" }, "CHART": { "SCANNING_TIME": "Tarama tamamlanma zamanı:", diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index c8e70483b..60076cc86 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -1016,7 +1016,8 @@ "COLUMN_FIXED": "修复版本", "COLUMN_DESCRIPTION": "简介", "FOOT_ITEMS": "项目", - "FOOT_OF": "总共" + "FOOT_OF": "总共", + "IN_ALLOW_LIST": "已入特赦名单" }, "CHART": { "SCANNING_TIME": "扫描完成时间:", diff --git a/src/portal/src/i18n/lang/zh-tw-lang.json b/src/portal/src/i18n/lang/zh-tw-lang.json index 03e1dd475..efd9e959d 100644 --- a/src/portal/src/i18n/lang/zh-tw-lang.json +++ b/src/portal/src/i18n/lang/zh-tw-lang.json @@ -1011,7 +1011,8 @@ "COLUMN_FIXED": "修復版本", "COLUMN_DESCRIPTION": "簡介", "FOOT_ITEMS": "項目", - "FOOT_OF": "總共" + "FOOT_OF": "總共", + "IN_ALLOW_LIST": "Listed In CVE Allowlist" }, "CHART":{ "SCANNING_TIME": "掃描完成時間:",