mirror of
https://github.com/goharbor/harbor
synced 2024-09-21 06:45:37 +00:00
Merge pull request #13347 from AllForNothing/vul-list
Improve vilnerability list UI
This commit is contained in:
commit
ec790d0afd
|
@ -28,7 +28,7 @@
|
||||||
<clr-dg-column [clrDgField]="'package'">{{'VULNERABILITY.GRID.COLUMN_PACKAGE' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'package'">{{'VULNERABILITY.GRID.COLUMN_PACKAGE' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'version'">{{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'version'">{{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'fix_version'">{{'VULNERABILITY.GRID.COLUMN_FIXED' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'fix_version'">{{'VULNERABILITY.GRID.COLUMN_FIXED' | translate}}</clr-dg-column>
|
||||||
|
<clr-dg-column *ngIf="isSystemAdmin()">{{'VULNERABILITY.GRID.IN_ALLOW_LIST' | translate}}</clr-dg-column>
|
||||||
<clr-dg-placeholder>
|
<clr-dg-placeholder>
|
||||||
<span *ngIf="hasScanned();else elseBlock">{{'VULNERABILITY.STATE.OTHER_STATUS' | translate}}</span>
|
<span *ngIf="hasScanned();else elseBlock">{{'VULNERABILITY.STATE.OTHER_STATUS' | translate}}</span>
|
||||||
<ng-template #elseBlock>
|
<ng-template #elseBlock>
|
||||||
|
@ -67,6 +67,9 @@
|
||||||
</div>
|
</div>
|
||||||
<ng-template #elseBlock>{{res.fix_version}}</ng-template>
|
<ng-template #elseBlock>{{res.fix_version}}</ng-template>
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
|
<clr-dg-cell *ngIf="isSystemAdmin()">
|
||||||
|
{{(isInAllowList(res.id)?"TAG_RETENTION.YES":"TAG_RETENTION.NO") | translate}}
|
||||||
|
</clr-dg-cell>
|
||||||
<clr-dg-row-detail *clrIfExpanded>
|
<clr-dg-row-detail *clrIfExpanded>
|
||||||
{{'VULNERABILITY.GRID.COLUMN_DESCRIPTION' | translate}}: {{res.description}}
|
{{'VULNERABILITY.GRID.COLUMN_DESCRIPTION' | translate}}: {{res.description}}
|
||||||
</clr-dg-row-detail>
|
</clr-dg-row-detail>
|
||||||
|
|
|
@ -6,11 +6,20 @@ import { AdditionsService } from "../additions.service";
|
||||||
import { of } from "rxjs";
|
import { of } from "rxjs";
|
||||||
import { TranslateFakeLoader, TranslateLoader, TranslateModule } from "@ngx-translate/core";
|
import { TranslateFakeLoader, TranslateLoader, TranslateModule } from "@ngx-translate/core";
|
||||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
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 { AdditionLink } from "../../../../../../../ng-swagger-gen/models/addition-link";
|
||||||
import { ErrorHandler } from "../../../../../../lib/utils/error-handler";
|
import { ErrorHandler } from "../../../../../../lib/utils/error-handler";
|
||||||
import { ChannelService } from "../../../../../../lib/services/channel.service";
|
import { ChannelService } from "../../../../../../lib/services/channel.service";
|
||||||
import { DEFAULT_SUPPORTED_MIME_TYPE } from "../../../../../../lib/utils/utils";
|
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', () => {
|
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(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -80,10 +117,13 @@ describe('ArtifactVulnerabilitiesComponent', () => {
|
||||||
declarations: [ArtifactVulnerabilitiesComponent],
|
declarations: [ArtifactVulnerabilitiesComponent],
|
||||||
providers: [
|
providers: [
|
||||||
ErrorHandler,
|
ErrorHandler,
|
||||||
|
SystemInfoService,
|
||||||
{provide: AdditionsService, useValue: fakedAdditionsService},
|
{provide: AdditionsService, useValue: fakedAdditionsService},
|
||||||
{provide: UserPermissionService, useValue: fakedUserPermissionService},
|
{provide: UserPermissionService, useValue: fakedUserPermissionService},
|
||||||
{provide: ScanningResultService, useValue: fakedScanningResultService},
|
{provide: ScanningResultService, useValue: fakedScanningResultService},
|
||||||
{provide: ChannelService, useValue: fakedChannelService},
|
{provide: ChannelService, useValue: fakedChannelService},
|
||||||
|
{provide: SessionService, useValue: fakedSessionService},
|
||||||
|
{provide: ProjectService, useValue: fakedProjectService},
|
||||||
],
|
],
|
||||||
schemas: [
|
schemas: [
|
||||||
NO_ERRORS_SCHEMA
|
NO_ERRORS_SCHEMA
|
||||||
|
@ -111,4 +151,14 @@ describe('ArtifactVulnerabilitiesComponent', () => {
|
||||||
const rows = fixture.nativeElement.getElementsByTagName('clr-dg-row');
|
const rows = fixture.nativeElement.getElementsByTagName('clr-dg-row');
|
||||||
expect(rows.length).toEqual(2);
|
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");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,8 +4,9 @@ import { ClrDatagridComparatorInterface, ClrLoadingState } from "@clr/angular";
|
||||||
import { finalize } from "rxjs/operators";
|
import { finalize } from "rxjs/operators";
|
||||||
import { AdditionLink } from "../../../../../../../ng-swagger-gen/models/addition-link";
|
import { AdditionLink } from "../../../../../../../ng-swagger-gen/models/addition-link";
|
||||||
import {
|
import {
|
||||||
|
ProjectService,
|
||||||
ScannerVo,
|
ScannerVo,
|
||||||
ScanningResultService,
|
ScanningResultService, SystemInfoService,
|
||||||
UserPermissionService,
|
UserPermissionService,
|
||||||
USERSTATICPERMISSION,
|
USERSTATICPERMISSION,
|
||||||
VulnerabilityItem
|
VulnerabilityItem
|
||||||
|
@ -20,6 +21,7 @@ import { ChannelService } from "../../../../../../lib/services/channel.service";
|
||||||
import { ResultBarChartComponent } from "../../../vulnerability-scanning/result-bar-chart.component";
|
import { ResultBarChartComponent } from "../../../vulnerability-scanning/result-bar-chart.component";
|
||||||
import { Subscription } from "rxjs";
|
import { Subscription } from "rxjs";
|
||||||
import { Artifact } from "../../../../../../../ng-swagger-gen/models/artifact";
|
import { Artifact } from "../../../../../../../ng-swagger-gen/models/artifact";
|
||||||
|
import {SessionService} from "../../../../../shared/session.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hbr-artifact-vulnerabilities',
|
selector: 'hbr-artifact-vulnerabilities',
|
||||||
|
@ -53,12 +55,16 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy {
|
||||||
resultBarChartComponent: ResultBarChartComponent;
|
resultBarChartComponent: ResultBarChartComponent;
|
||||||
sub: Subscription;
|
sub: Subscription;
|
||||||
hasViewInitWithDelay: boolean = false;
|
hasViewInitWithDelay: boolean = false;
|
||||||
|
currentCVEList: Array<{ "cve_id": string; }> = [];
|
||||||
constructor(
|
constructor(
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private additionsService: AdditionsService,
|
private additionsService: AdditionsService,
|
||||||
private userPermissionService: UserPermissionService,
|
private userPermissionService: UserPermissionService,
|
||||||
private scanningService: ScanningResultService,
|
private scanningService: ScanningResultService,
|
||||||
private channel: ChannelService,
|
private channel: ChannelService,
|
||||||
|
private session: SessionService,
|
||||||
|
private projectService: ProjectService,
|
||||||
|
private systemInfoService: SystemInfoService,
|
||||||
) {
|
) {
|
||||||
const that = this;
|
const that = this;
|
||||||
this.severitySort = {
|
this.severitySort = {
|
||||||
|
@ -80,6 +86,10 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.hasViewInitWithDelay = true;
|
this.hasViewInitWithDelay = true;
|
||||||
}, 0);
|
}, 0);
|
||||||
|
if (this.isSystemAdmin()) {
|
||||||
|
// get system and project CVE allow list
|
||||||
|
this.getCurrentCVEAllowList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
if (this.sub) {
|
if (this.sub) {
|
||||||
|
@ -194,4 +204,37 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1016,7 +1016,8 @@
|
||||||
"COLUMN_FIXED": "Fixed in version",
|
"COLUMN_FIXED": "Fixed in version",
|
||||||
"COLUMN_DESCRIPTION": "Description",
|
"COLUMN_DESCRIPTION": "Description",
|
||||||
"FOOT_ITEMS": "Items",
|
"FOOT_ITEMS": "Items",
|
||||||
"FOOT_OF": "of"
|
"FOOT_OF": "of",
|
||||||
|
"IN_ALLOW_LIST": "Listed In CVE Allowlist"
|
||||||
},
|
},
|
||||||
"CHART": {
|
"CHART": {
|
||||||
"SCANNING_TIME": "Scan completed time:",
|
"SCANNING_TIME": "Scan completed time:",
|
||||||
|
|
|
@ -1016,7 +1016,8 @@
|
||||||
"COLUMN_FIXED": "Fixed in version",
|
"COLUMN_FIXED": "Fixed in version",
|
||||||
"COLUMN_DESCRIPTION": "Description",
|
"COLUMN_DESCRIPTION": "Description",
|
||||||
"FOOT_ITEMS": "Items",
|
"FOOT_ITEMS": "Items",
|
||||||
"FOOT_OF": "of"
|
"FOOT_OF": "of",
|
||||||
|
"IN_ALLOW_LIST": "Listed In CVE Allowlist"
|
||||||
},
|
},
|
||||||
"CHART": {
|
"CHART": {
|
||||||
"SCANNING_TIME": "Scan completed time:",
|
"SCANNING_TIME": "Scan completed time:",
|
||||||
|
|
|
@ -989,7 +989,8 @@
|
||||||
"COLUMN_FIXED": "Fixé dans le version",
|
"COLUMN_FIXED": "Fixé dans le version",
|
||||||
"COLUMN_DESCRIPTION": "Description",
|
"COLUMN_DESCRIPTION": "Description",
|
||||||
"FOOT_ITEMS": "Items",
|
"FOOT_ITEMS": "Items",
|
||||||
"FOOT_OF": "de"
|
"FOOT_OF": "de",
|
||||||
|
"IN_ALLOW_LIST": "Listed In CVE Allowlist"
|
||||||
},
|
},
|
||||||
"CHART": {
|
"CHART": {
|
||||||
"SCANNING_TIME": "Temps d'analyse complète :",
|
"SCANNING_TIME": "Temps d'analyse complète :",
|
||||||
|
|
|
@ -1012,7 +1012,8 @@
|
||||||
"COLUMN_FIXED": "Corrigido na versão",
|
"COLUMN_FIXED": "Corrigido na versão",
|
||||||
"COLUMN_DESCRIPTION": "Descrição",
|
"COLUMN_DESCRIPTION": "Descrição",
|
||||||
"FOOT_ITEMS": "Itens",
|
"FOOT_ITEMS": "Itens",
|
||||||
"FOOT_OF": "de"
|
"FOOT_OF": "de",
|
||||||
|
"IN_ALLOW_LIST": "Listed In CVE Allowlist"
|
||||||
},
|
},
|
||||||
"CHART": {
|
"CHART": {
|
||||||
"SCANNING_TIME": "Tempo de conclusão da análise:",
|
"SCANNING_TIME": "Tempo de conclusão da análise:",
|
||||||
|
|
|
@ -1016,7 +1016,8 @@
|
||||||
"COLUMN_FIXED": "Sürümde düzeltildi",
|
"COLUMN_FIXED": "Sürümde düzeltildi",
|
||||||
"COLUMN_DESCRIPTION": "Açıklama",
|
"COLUMN_DESCRIPTION": "Açıklama",
|
||||||
"FOOT_ITEMS": "Öğeler",
|
"FOOT_ITEMS": "Öğeler",
|
||||||
"FOOT_OF": "of"
|
"FOOT_OF": "of",
|
||||||
|
"IN_ALLOW_LIST": "Listed In CVE Allowlist"
|
||||||
},
|
},
|
||||||
"CHART": {
|
"CHART": {
|
||||||
"SCANNING_TIME": "Tarama tamamlanma zamanı:",
|
"SCANNING_TIME": "Tarama tamamlanma zamanı:",
|
||||||
|
|
|
@ -1016,7 +1016,8 @@
|
||||||
"COLUMN_FIXED": "修复版本",
|
"COLUMN_FIXED": "修复版本",
|
||||||
"COLUMN_DESCRIPTION": "简介",
|
"COLUMN_DESCRIPTION": "简介",
|
||||||
"FOOT_ITEMS": "项目",
|
"FOOT_ITEMS": "项目",
|
||||||
"FOOT_OF": "总共"
|
"FOOT_OF": "总共",
|
||||||
|
"IN_ALLOW_LIST": "已入特赦名单"
|
||||||
},
|
},
|
||||||
"CHART": {
|
"CHART": {
|
||||||
"SCANNING_TIME": "扫描完成时间:",
|
"SCANNING_TIME": "扫描完成时间:",
|
||||||
|
|
|
@ -1011,7 +1011,8 @@
|
||||||
"COLUMN_FIXED": "修復版本",
|
"COLUMN_FIXED": "修復版本",
|
||||||
"COLUMN_DESCRIPTION": "簡介",
|
"COLUMN_DESCRIPTION": "簡介",
|
||||||
"FOOT_ITEMS": "項目",
|
"FOOT_ITEMS": "項目",
|
||||||
"FOOT_OF": "總共"
|
"FOOT_OF": "總共",
|
||||||
|
"IN_ALLOW_LIST": "Listed In CVE Allowlist"
|
||||||
},
|
},
|
||||||
"CHART":{
|
"CHART":{
|
||||||
"SCANNING_TIME": "掃描完成時間:",
|
"SCANNING_TIME": "掃描完成時間:",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user