Update security hub ui (#19062)

1. Fixes #19010
2. Fixes #19011
3. Fixes #19012
4. Fixes #19015
5. Fixes #19025
6. Fixes #19026
7. Fixes #19034
8. Fixes #19037

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Shijun Sun 2023-07-31 20:25:05 +08:00 committed by GitHub
parent d93f24a4dc
commit 854e0295d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 87 additions and 44 deletions

View File

@ -29,7 +29,7 @@
'VULNERABILITY.GRID.COLUMN_SEVERITY' | translate
}}</clr-dg-column>
<clr-dg-column class="min-width">{{
'VULNERABILITY.PACKAGE' | translate
'VULNERABILITY.GRID.COLUMN_PACKAGE' | translate
}}</clr-dg-column>
<clr-dg-column>{{
'VULNERABILITY.GRID.COLUMN_VERSION' | translate
@ -42,12 +42,17 @@
</clr-dg-placeholder>
<clr-dg-row *ngFor="let c of vul" [clrDgItem]="c">
<clr-dg-cell class="min-width">
<span *ngIf="!c?.links || c?.links?.length === 0">{{
c.cve_id
}}</span>
<span
*ngIf="
!c?.links ||
c?.links?.length === 0 ||
(c?.links?.length === 1 && !c?.links[0])
"
>{{ c.cve_id }}</span
>
<a
rel="noopener noreferrer"
*ngIf="c?.links && c?.links.length === 1"
*ngIf="c?.links && c?.links.length === 1 && c?.links[0]"
href="{{ c?.links[0] }}"
target="_blank"
>{{ c.cve_id }}</a

View File

@ -10,12 +10,12 @@ import {
import { finalize } from 'rxjs/operators';
import { VulnerabilityItem } from '../../../../../../ng-swagger-gen/models/vulnerability-item';
import {
getDigestLink,
getRepoLink,
OptionType,
SearchEventData,
severityText,
VUL_ID,
getDigestLink,
getRepoLink,
} from './security-hub.interface';
import { ProjectService } from '../../../../../../ng-swagger-gen/services/project.service';
import { VulnerabilityFilterComponent } from './vulnerability-filter/vulnerability-filter.component';
@ -96,14 +96,17 @@ export class SecurityHubComponent {
search(res: SearchEventData) {
if (res?.projectId) {
this.projectService
.getProject({
projectNameOrId: res.projectId,
.listProjects({
name: res.projectId,
page: 1,
pageSize: 1,
withDetail: false,
})
.subscribe({
next: project => {
if (project?.project_id) {
next: projects => {
if (projects?.length) {
res.normal.push(
`${OptionType.PROJECT_ID}=${project?.project_id}`
`${OptionType.PROJECT_ID}=${projects[0]?.project_id}`
);
this.clrDgRefresh(this.state, res?.normal);
} else {
@ -112,7 +115,8 @@ export class SecurityHubComponent {
}
},
error: err => {
this.messageHandler.error(err);
res.normal.push(`${OptionType.PROJECT_ID}=0`);
this.clrDgRefresh(this.state, res?.normal);
},
});
} else {
@ -157,12 +161,30 @@ export class SecurityHubComponent {
searchCVE(cveId: string) {
this.vulnerabilityFilterComponent.selectedOptions = [OptionType.CVE_ID];
this.vulnerabilityFilterComponent.candidates = [
OptionType.SEVERITY,
OptionType.CVSS3,
OptionType.PROJECT_ID,
OptionType.REPO,
OptionType.PACKAGE,
OptionType.TAG,
];
this.vulnerabilityFilterComponent.valueMap = {};
this.vulnerabilityFilterComponent.valueMap[OptionType.CVE_ID] = cveId;
this.currentPage = 1;
this.clrDgRefresh(this.state, [`${OptionType.CVE_ID}=${cveId}`]);
}
searchRepo(repoName: string) {
this.vulnerabilityFilterComponent.selectedOptions = [OptionType.REPO];
this.vulnerabilityFilterComponent.candidates = [
OptionType.CVE_ID,
OptionType.SEVERITY,
OptionType.CVSS3,
OptionType.PROJECT_ID,
OptionType.PACKAGE,
OptionType.TAG,
];
this.vulnerabilityFilterComponent.valueMap = {};
this.vulnerabilityFilterComponent.valueMap[OptionType.REPO] = repoName;
this.currentPage = 1;
this.clrDgRefresh(this.state, [`${OptionType.REPO}=${repoName}`]);

View File

@ -29,7 +29,7 @@ export const OptionType_I18n_Map = {
[OptionType.SEVERITY]: 'VULNERABILITY.GRID.COLUMN_SEVERITY',
[OptionType.CVSS3]: 'VULNERABILITY.GRID.CVSS3',
[OptionType.REPO]: 'SECURITY_HUB.REPO_NAME',
[OptionType.PACKAGE]: 'VULNERABILITY.PACKAGE',
[OptionType.PACKAGE]: 'VULNERABILITY.GRID.COLUMN_PACKAGE',
[OptionType.TAG]: 'REPLICATION.TAG',
[OptionType.PROJECT_ID]: 'SECURITY_HUB.OPTION_PROJECT_ID_NAME',
};

View File

@ -56,7 +56,7 @@ export class SingleBarComponent implements OnChanges {
enabled: true,
distance: -8,
style: {
fontSize: 8,
fontSize: '8px',
fontWeight: 1,
},
pointFormat: '{point.y}',

View File

@ -97,7 +97,7 @@ export class VulnerabilityFilterComponent {
item === OptionType.PROJECT_ID &&
this.valueMap[OptionType.PROJECT_ID]
) {
result.projectId = this.valueMap[OptionType.PROJECT_ID];
result.projectId = this.valueMap[OptionType.PROJECT_ID]?.trim();
} else if (item === OptionType.SEVERITY) {
if (this.severity) {
result.normal.push(
@ -108,12 +108,12 @@ export class VulnerabilityFilterComponent {
if (this.startScore || this.endScore) {
result.normal.push(
`${OptionType.CVSS3}=[${
this.startScore ? this.startScore : '0.0'
}~${this.endScore ? this.endScore : '10.0'}]`
this.startScore ? this.startScore?.trim() : '0.0'
}~${this.endScore ? this.endScore?.trim() : '10.0'}]`
);
}
} else if (this.valueMap[item]) {
result.normal.push(`${item}=${this.valueMap[item]}`);
result.normal.push(`${item}=${this.valueMap[item]?.trim()}`);
}
});
this.search.emit(result);

View File

@ -116,16 +116,18 @@
<div
class="clr-row row"
*ngFor="let item of securitySummary?.dangerous_artifacts">
<div class="clr-col ellipsis">
<div class="clr-col">
<a
class="search"
href="javascript:void(0)"
appScrollAnchor="{{ vulId }}"
(click)="searchRepoClick(item?.repository_name)"
title="{{ item.repository_name }}"
><clr-icon shape="search"></clr-icon
>{{ item.repository_name }}</a
>
title="{{ item.repository_name }}">
<span class="ellipsis">
<clr-icon shape="search"></clr-icon
>{{ item.repository_name }}
</span>
</a>
</div>
<div class="clr-col" title="{{ item?.digest }}">
<a
@ -137,8 +139,10 @@
item.digest
)
"
>{{ item?.digest?.slice(0, 15) }}</a
>
><span class="ellipsis">{{
item?.digest?.slice(0, 15)
}}</span>
</a>
</div>
<div class="clr-col">
<div class="single-bar-container">
@ -163,7 +167,7 @@
{{ 'VULNERABILITY.GRID.CVSS3' | translate }}
</div>
<div class="clr-col-4 column">
{{ 'VULNERABILITY.PACKAGE' | translate }}
{{ 'VULNERABILITY.GRID.COLUMN_PACKAGE' | translate }}
</div>
</div>
</div>
@ -171,16 +175,18 @@
<div
class="clr-row row"
*ngFor="let item of securitySummary?.dangerous_cves">
<div class="clr-col-4 ellipsis">
<div class="clr-col-4">
<a
class="search"
href="javascript:void(0)"
appScrollAnchor="{{ vulId }}"
(click)="searchCVEClick(item?.cve_id)"
title="{{ item.cve_id }}"
><clr-icon shape="search"></clr-icon
>{{ item.cve_id }}</a
>
title="{{ item.cve_id }}">
<span class="ellipsis">
<clr-icon shape="search"></clr-icon
>{{ item.cve_id }}
</span>
</a>
</div>
<div class="clr-col-2">
<ng-container [ngSwitch]="item.severity">

View File

@ -113,6 +113,7 @@ export class VulnerabilitySummaryComponent implements OnInit, OnDestroy {
enabled: false,
},
showInLegend: true,
borderWidth: 0,
},
},
legend: {

View File

@ -1,7 +1,7 @@
import { throwError as observableThrowError, Observable, of } from 'rxjs';
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { catchError, share } from 'rxjs/operators';
import { Project } from '../../base/project/project-config/project-policy-config/project';
import { ProjectPolicy } from '../../base/project/project-config/project-policy-config/project-policy-config.component';
import {
@ -10,6 +10,7 @@ import {
buildHttpRequestOptionsWithObserveResponse,
CURRENT_BASE_HREF,
} from '../units/utils';
import { CacheObservable } from '../units/cache-util';
/**
* Define the service methods to handle the Project related things.
@ -87,18 +88,26 @@ export abstract class ProjectService {
*/
@Injectable()
export class ProjectDefaultService extends ProjectService {
// to avoid multiple requests for one navigating action
private _sharedProjectObservableMap: {
[key: number | string]: Observable<Project>;
} = {};
constructor(private http: HttpClient) {
super();
}
@CacheObservable({ maxAge: 1000 * 60 })
public getProject(projectId: number | string): Observable<Project> {
if (!projectId) {
return observableThrowError('Bad argument');
}
let baseUrl: string = CURRENT_BASE_HREF + '/projects';
return this.http
if (this._sharedProjectObservableMap[projectId]) {
return this._sharedProjectObservableMap[projectId];
}
this._sharedProjectObservableMap[projectId] = this.http
.get<Project>(`${baseUrl}/${projectId}`, HTTP_GET_OPTIONS)
.pipe(catchError(error => observableThrowError(error)));
.pipe(share());
return this._sharedProjectObservableMap[projectId];
}
public updateProjectPolicy(

View File

@ -1886,7 +1886,7 @@
"CVE": "CVEs",
"FILTER_BY": "Filter by",
"OPTION_ALL": "All",
"OPTION_PROJECT_ID_NAME": "Project id or name",
"OPTION_PROJECT_ID_NAME": "Project Name",
"SEARCH": "SEARCH",
"REPO_NAME": "Repository Name",
"TOOLTIP": "All filters except CVSS3 only support exact matches",

View File

@ -1887,7 +1887,7 @@
"CVE": "CVEs",
"FILTER_BY": "Filter by",
"OPTION_ALL": "All",
"OPTION_PROJECT_ID_NAME": "Project Id or Name",
"OPTION_PROJECT_ID_NAME": "Project Name",
"SEARCH": "SEARCH",
"REPO_NAME": "Repository Name",
"TOOLTIP": "All filters except CVSS3 only support exact matches",

View File

@ -1883,7 +1883,7 @@
"CVE": "CVEs",
"FILTER_BY": "Filter by",
"OPTION_ALL": "All",
"OPTION_PROJECT_ID_NAME": "Project id or name",
"OPTION_PROJECT_ID_NAME": "Project Name",
"SEARCH": "SEARCH",
"REPO_NAME": "Repository Name",
"TOOLTIP": "All filters except CVSS3 only support exact matches",

View File

@ -1853,7 +1853,7 @@
"CVE": "CVEs",
"FILTER_BY": "Filter by",
"OPTION_ALL": "All",
"OPTION_PROJECT_ID_NAME": "Project id or name",
"OPTION_PROJECT_ID_NAME": "Project Name",
"SEARCH": "SEARCH",
"REPO_NAME": "Repository Name",
"TOOLTIP": "All filters except CVSS3 only support exact matches",

View File

@ -1883,7 +1883,7 @@
"CVE": "CVEs",
"FILTER_BY": "Filter by",
"OPTION_ALL": "All",
"OPTION_PROJECT_ID_NAME": "Project id or name",
"OPTION_PROJECT_ID_NAME": "Project Name",
"SEARCH": "SEARCH",
"REPO_NAME": "Repository Name",
"TOOLTIP": "All filters except CVSS3 only support exact matches",

View File

@ -1886,7 +1886,7 @@
"CVE": "CVEs",
"FILTER_BY": "Filter by",
"OPTION_ALL": "All",
"OPTION_PROJECT_ID_NAME": "Project id or name",
"OPTION_PROJECT_ID_NAME": "Project Name",
"SEARCH": "SEARCH",
"REPO_NAME": "Repository Name",
"TOOLTIP": "All filters except CVSS3 only support exact matches",

View File

@ -1883,7 +1883,7 @@
"CVE": "CVEs",
"FILTER_BY": "过滤条件",
"OPTION_ALL": "全部",
"OPTION_PROJECT_ID_NAME": "项目 ID 或 名称",
"OPTION_PROJECT_ID_NAME": "项目名称",
"SEARCH": "搜索",
"REPO_NAME": "仓库名称",
"TOOLTIP": "CVSS3 除外的所有过滤项只支持精确匹配",

View File

@ -1875,7 +1875,7 @@
"CVE": "CVEs",
"FILTER_BY": "Filter by",
"OPTION_ALL": "All",
"OPTION_PROJECT_ID_NAME": "Project id or name",
"OPTION_PROJECT_ID_NAME": "Project Name",
"SEARCH": "SEARCH",
"REPO_NAME": "Repository Name",
"TOOLTIP": "All filters except CVSS3 only support exact matches",