refactor based on swagger yaml changes

Signed-off-by: xuelichao <xuel@vmware.com>
This commit is contained in:
xuelichao 2024-03-05 17:32:44 +08:00 committed by stonezdj(Daojun Zhang)
parent 7669e3d771
commit 71d4aecc13
19 changed files with 210 additions and 143 deletions

View File

@ -6776,6 +6776,10 @@ definitions:
type: object
description: 'The generate SBOM overview information'
properties:
report_id:
type: string
description: 'id of the native sbom report'
example: '5f62c830-f996-11e9-957f-0242c0a89008'
start_time:
type: string
format: date-time
@ -6801,10 +6805,6 @@ definitions:
format: int64
description: 'Time in seconds required to create the report'
example: 300
complete_percent:
type: integer
description: 'The complete percent of the scanning which value is between 0 and 100'
example: 100
scanner:
$ref: '#/definitions/Scanner'
NativeReportSummary:

View File

@ -1,11 +1,7 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import {
DEFAULT_SBOM_SUPPORTED_MIME_TYPES,
DEFAULT_SUPPORTED_MIME_TYPES,
} from '../../../../../shared/units/utils';
import { ScanTypes } from 'src/app/shared/entities/shared.const';
import { DEFAULT_SUPPORTED_MIME_TYPES } from '../../../../../shared/units/utils';
@Injectable({
providedIn: 'root',
@ -16,8 +12,7 @@ export class AdditionsService {
getDetailByLink(
link: string,
shouldSetHeader: boolean,
shouldReturnText: boolean,
scanType = ScanTypes.VULNERABILITY
shouldReturnText: boolean
): Observable<any> {
if (shouldReturnText) {
return this.http.get(link, {
@ -27,16 +22,9 @@ export class AdditionsService {
}
if (shouldSetHeader) {
return this.http.get(link, {
headers:
scanType === ScanTypes.SBOM
? {
'X-Accept-SBOMs':
DEFAULT_SBOM_SUPPORTED_MIME_TYPES,
}
: {
'X-Accept-Vulnerabilities':
DEFAULT_SUPPORTED_MIME_TYPES,
},
headers: {
'X-Accept-Vulnerabilities': DEFAULT_SUPPORTED_MIME_TYPES,
},
});
}
return this.http.get(link);

View File

@ -1,76 +1,105 @@
<ng-container *ngIf="additionLinks">
<h4 class="margin-bottom-025">{{ 'ARTIFACT.ADDITIONS' | translate }}</h4>
<div class="min-15">
<clr-tabs>
<clr-tabs #additionsTab>
<clr-tab *ngIf="getVulnerability()">
<button clrTabLink id="vulnerability">
<button
clrTabLink
id="vulnerability"
(click)="actionTab('vulnerability')">
{{ 'REPOSITORY.VULNERABILITY' | translate }}
</button>
<clr-tab-content id="vulnerability-content" *clrIfActive>
<hbr-artifact-vulnerabilities
[artifact]="artifact"
[projectName]="projectName"
[projectId]="projectId"
[repoName]="repoName"
[digest]="digest"
[vulnerabilitiesLink]="
getVulnerability()
"></hbr-artifact-vulnerabilities>
</clr-tab-content>
<ng-template
[clrIfActive]="currentTabLinkId === 'vulnerability'">
<clr-tab-content id="vulnerability-content">
<hbr-artifact-vulnerabilities
[artifact]="artifact"
[projectName]="projectName"
[projectId]="projectId"
[repoName]="repoName"
[digest]="digest"
[vulnerabilitiesLink]="
getVulnerability()
"></hbr-artifact-vulnerabilities>
</clr-tab-content>
</ng-template>
</clr-tab>
<clr-tab *ngIf="getSbom()">
<button clrTabLink id="sbom">
<button clrTabLink id="sbom" (click)="actionTab('sbom')">
{{ 'REPOSITORY.SBOM' | translate }}
</button>
<clr-tab-content id="sbom-content" *clrIfActive>
<hbr-artifact-sbom
[artifact]="artifact"
[projectName]="projectName"
[projectId]="projectId"
[repoName]="repoName"
[sbomDigest]="sbomDigest"
[sbomLink]="getSbom()"></hbr-artifact-sbom>
</clr-tab-content>
<ng-template [clrIfActive]="currentTabLinkId === 'sbom'">
<clr-tab-content id="sbom-content">
<hbr-artifact-sbom
[artifact]="artifact"
[projectName]="projectName"
[projectId]="projectId"
[repoName]="repoName"
[sbomDigest]="sbomDigest"></hbr-artifact-sbom>
</clr-tab-content>
</ng-template>
</clr-tab>
<clr-tab *ngIf="getBuildHistory()">
<button clrTabLink id="build-history">
<button
clrTabLink
id="build-history"
(click)="actionTab('build-history')">
{{ 'REPOSITORY.BUILD_HISTORY' | translate }}
</button>
<clr-tab-content *clrIfActive>
<hbr-artifact-build-history
[buildHistoryLink]="
getBuildHistory()
"></hbr-artifact-build-history>
</clr-tab-content>
<ng-template
[clrIfActive]="currentTabLinkId === 'build-history'">
<clr-tab-content>
<hbr-artifact-build-history
[buildHistoryLink]="
getBuildHistory()
"></hbr-artifact-build-history>
</clr-tab-content>
</ng-template>
</clr-tab>
<clr-tab *ngIf="getSummary()">
<button clrTabLink id="summary-link">
<button
clrTabLink
id="summary-link"
(click)="actionTab('summary-link')">
{{ 'ARTIFACT.SUMMARY' | translate }}
</button>
<clr-tab-content id="summary-content" *clrIfActive>
<hbr-artifact-summary
[summaryLink]="getSummary()"></hbr-artifact-summary>
</clr-tab-content>
<ng-template
[clrIfActive]="currentTabLinkId === 'summary-link'">
<clr-tab-content id="summary-content">
<hbr-artifact-summary
[summaryLink]="getSummary()"></hbr-artifact-summary>
</clr-tab-content>
</ng-template>
</clr-tab>
<clr-tab *ngIf="getDependencies()">
<button clrTabLink id="depend-link">
<button
clrTabLink
id="depend-link"
(click)="actionTab('depend-link')">
{{ 'ARTIFACT.DEPENDENCIES' | translate }}
</button>
<clr-tab-content id="depend-content" *clrIfActive>
<hbr-artifact-dependencies
[dependenciesLink]="
getDependencies()
"></hbr-artifact-dependencies>
</clr-tab-content>
<ng-template [clrIfActive]="currentTabLinkId === 'depend-link'">
<clr-tab-content id="depend-content">
<hbr-artifact-dependencies
[dependenciesLink]="
getDependencies()
"></hbr-artifact-dependencies>
</clr-tab-content>
</ng-template>
</clr-tab>
<clr-tab *ngIf="getValues()">
<button clrTabLink id="value-link">
<button
clrTabLink
id="value-link"
(click)="actionTab('value-link')">
{{ 'ARTIFACT.VALUES' | translate }}
</button>
<clr-tab-content id="value-content" *clrIfActive>
<hbr-artifact-values
[valuesLink]="getValues()"></hbr-artifact-values>
</clr-tab-content>
<ng-template [clrIfActive]="currentTabLinkId === 'value-link'">
<clr-tab-content id="value-content">
<hbr-artifact-values
[valuesLink]="getValues()"></hbr-artifact-values>
</clr-tab-content>
</ng-template>
</clr-tab>
</clr-tabs>
</div>

View File

@ -1,15 +1,23 @@
import { Component, Input } from '@angular/core';
import {
AfterViewChecked,
ChangeDetectorRef,
Component,
Input,
OnInit,
ViewChild,
} from '@angular/core';
import { ADDITIONS } from './models';
import { AdditionLinks } from '../../../../../../../ng-swagger-gen/models/addition-links';
import { AdditionLink } from '../../../../../../../ng-swagger-gen/models/addition-link';
import { Artifact } from '../../../../../../../ng-swagger-gen/models/artifact';
import { ClrTabs } from '@clr/angular';
@Component({
selector: 'artifact-additions',
templateUrl: './artifact-additions.component.html',
styleUrls: ['./artifact-additions.component.scss'],
})
export class ArtifactAdditionsComponent {
export class ArtifactAdditionsComponent implements AfterViewChecked, OnInit {
@Input() artifact: Artifact;
@Input() additionLinks: AdditionLinks;
@Input() projectName: string;
@ -21,7 +29,26 @@ export class ArtifactAdditionsComponent {
digest: string;
@Input()
sbomDigest: string;
constructor() {}
@Input()
tab: string;
@Input() currentTabLinkId: string = 'vulnerability';
activeTab: string = null;
@ViewChild('additionsTab') tabs: ClrTabs;
constructor(private ref: ChangeDetectorRef) {}
ngOnInit(): void {
this.activeTab = this.tab;
}
ngAfterViewChecked() {
if (this.activeTab) {
this.currentTabLinkId = this.activeTab;
this.activeTab = null;
}
this.ref.detectChanges();
}
getVulnerability(): AdditionLink {
if (
@ -62,4 +89,8 @@ export class ArtifactAdditionsComponent {
}
return null;
}
actionTab(tab: string): void {
this.currentTabLinkId = tab;
}
}

View File

@ -32,10 +32,10 @@
</div>
</div>
</clr-dg-action-bar>
<clr-dg-column [clrDgField]="'package'">{{
<clr-dg-column [clrDgField]="'package'" class="package-medium">{{
'SBOM.GRID.COLUMN_PACKAGE' | translate
}}</clr-dg-column>
<clr-dg-column [clrDgField]="'version'">{{
<clr-dg-column [clrDgField]="'version'" class="version-medium">{{
'SBOM.GRID.COLUMN_VERSION' | translate
}}</clr-dg-column>
<clr-dg-column>{{
@ -50,17 +50,25 @@
</ng-template>
</clr-dg-placeholder>
<clr-dg-row *clrDgItems="let res of artifactSbomPackages()">
<clr-dg-cell>{{ res.name ?? '' }}</clr-dg-cell>
<clr-dg-cell>{{ res.versionInfo ?? '' }}</clr-dg-cell>
<clr-dg-cell class="package-medium">{{
res.name ?? ''
}}</clr-dg-cell>
<clr-dg-cell class="version-medium">{{
res.versionInfo ?? ''
}}</clr-dg-cell>
<clr-dg-cell>{{ res.licenseConcluded ?? '' }}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>
<div class="report">
<i *ngIf="artifact?.scanner">{{
<i *ngIf="artifact?.sbom_overview">{{
'SBOM.REPORTED_BY'
| translate
: { scanner: getScannerInfo(artifact?.scanner) }
: {
scanner: getScannerInfo(
artifact?.sbom_overview?.scanner
)
}
}}</i>
</div>
<clr-dg-pagination

View File

@ -62,3 +62,13 @@
.label {
min-width: 3rem;
}
.package-medium {
max-width: 25rem;
text-overflow: ellipsis;
}
.version-medium {
min-width: 22rem;
text-overflow: ellipsis;
}

View File

@ -17,6 +17,7 @@ import { SessionUser } from '../../../../../../shared/entities/session-user';
import { AppConfigService } from 'src/app/services/app-config.service';
import { ArtifactSbomPackageItem } from '../../artifact';
import { ArtifactService } from 'ng-swagger-gen/services';
import { ArtifactListPageService } from '../../artifact-list-page/artifact-list-page.service';
describe('ArtifactSbomComponent', () => {
let component: ArtifactSbomComponent;
@ -97,13 +98,9 @@ describe('ArtifactSbomComponent', () => {
},
packages: artifactSbomPackages,
};
const mockedLink: AdditionLink = {
absolute: false,
href: '/test',
};
const fakedArtifactService = {
getSbomAddition() {
return of(artifactSbomJson);
getAddition() {
return of(JSON.stringify(artifactSbomJson));
},
};
const fakedUserPermissionService = {
@ -131,6 +128,12 @@ describe('ArtifactSbomComponent', () => {
};
const mockedSbomDigest =
'sha256:51a41cec9de9d62ee60e206f5a8a615a028a65653e45539990867417cb486285';
const mockedArtifactListPageService = {
hasScannerSupportSBOM(): boolean {
return true;
},
init() {},
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
@ -153,6 +156,10 @@ describe('ArtifactSbomComponent', () => {
useValue: fakedUserPermissionService,
},
{ provide: SessionService, useValue: fakedSessionService },
{
provide: ArtifactListPageService,
useValue: mockedArtifactListPageService,
},
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
@ -162,8 +169,7 @@ describe('ArtifactSbomComponent', () => {
fixture = TestBed.createComponent(ArtifactSbomComponent);
component = fixture.componentInstance;
component.hasSbomPermission = true;
component.hasEnabledSbom = true;
component.sbomLink = mockedLink;
component.hasScannerSupportSBOM = true;
component.sbomDigest = mockedSbomDigest;
component.ngOnInit();
fixture.detectChanges();

View File

@ -1,4 +1,10 @@
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import {
AfterViewInit,
Component,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { ClrDatagridStateInterface, ClrLoadingState } from '@clr/angular';
import { finalize } from 'rxjs/operators';
import { AdditionLink } from '../../../../../../../../ng-swagger-gen/models/addition-link';
@ -32,6 +38,8 @@ import {
getArtifactSbom,
} from '../../artifact';
import { ArtifactService } from 'ng-swagger-gen/services';
import { ScanTypes } from 'src/app/shared/entities/shared.const';
import { ArtifactListPageService } from '../../artifact-list-page/artifact-list-page.service';
@Component({
selector: 'hbr-artifact-sbom',
@ -39,8 +47,6 @@ import { ArtifactService } from 'ng-swagger-gen/services';
styleUrls: ['./artifact-sbom.component.scss'],
})
export class ArtifactSbomComponent implements OnInit, OnDestroy {
@Input()
sbomLink: AdditionLink;
@Input()
projectName: string;
@Input()
@ -53,7 +59,7 @@ export class ArtifactSbomComponent implements OnInit, OnDestroy {
artifactSbom: ArtifactSbom;
loading: boolean = false;
hasEnabledSbom: boolean = false;
hasScannerSupportSBOM: boolean = false;
downloadSbomBtnState: ClrLoadingState = ClrLoadingState.DEFAULT;
hasSbomPermission: boolean = false;
@ -69,15 +75,16 @@ export class ArtifactSbomComponent implements OnInit, OnDestroy {
private errorHandler: ErrorHandler,
private appConfigService: AppConfigService,
private artifactService: ArtifactService,
private artifactListPageService: ArtifactListPageService,
private userPermissionService: UserPermissionService,
private eventService: EventService,
private session: SessionService
) {}
ngOnInit() {
this.artifactListPageService.init(this.projectId);
this.getSbom();
this.getSbomPermission();
this.hasEnabledSbom = this.appConfigService.getConfig().sbom_enabled;
if (!this.sub) {
this.sub = this.eventService.subscribe(
HarborEvent.UPDATE_SBOM_INFO,
@ -109,23 +116,19 @@ export class ArtifactSbomComponent implements OnInit, OnDestroy {
}
getSbom() {
if (
this.sbomDigest &&
this.sbomLink &&
!this.sbomLink.absolute &&
this.sbomLink.href
) {
if (this.sbomDigest) {
if (!this.hasShowLoading) {
this.loading = true;
this.hasShowLoading = true;
}
const sbomAdditionParams = <ArtifactService.GetSbomAdditionParams>{
const sbomAdditionParams = <ArtifactService.GetAdditionParams>{
repositoryName: dbEncodeURIComponent(this.repoName),
reference: this.sbomDigest,
projectName: this.projectName,
addition: ScanTypes.SBOM,
};
this.artifactService
.getSbomAddition(sbomAdditionParams)
.getAddition(sbomAdditionParams)
.pipe(
finalize(() => {
this.loading = false;
@ -134,7 +137,14 @@ export class ArtifactSbomComponent implements OnInit, OnDestroy {
)
.subscribe(
res => {
this.artifactSbom = getArtifactSbom(res);
if (res) {
this.artifactSbom = getArtifactSbom(
JSON.parse(res)
);
} else {
this.loading = false;
this.hasShowLoading = false;
}
},
error => {
this.errorHandler.error(error);
@ -190,9 +200,9 @@ export class ArtifactSbomComponent implements OnInit, OnDestroy {
return (
this.hasViewInitWithDelay &&
this.artifact.sbom_overview &&
(this.artifact.sbom_overview.sbom_status ===
(this.artifact.sbom_overview.scan_status ===
SBOM_SCAN_STATUS.PENDING ||
this.artifact.sbom_overview.sbom_status ===
this.artifact.sbom_overview.scan_status ===
SBOM_SCAN_STATUS.RUNNING)
);
}
@ -200,7 +210,7 @@ export class ArtifactSbomComponent implements OnInit, OnDestroy {
downloadSbom() {
this.downloadSbomBtnState = ClrLoadingState.LOADING;
if (
this.artifact?.sbom_overview?.sbom_status ===
this.artifact?.sbom_overview?.scan_status ===
SBOM_SCAN_STATUS.SUCCESS
) {
downloadJson(
@ -212,9 +222,11 @@ export class ArtifactSbomComponent implements OnInit, OnDestroy {
}
canDownloadSbom(): boolean {
this.hasScannerSupportSBOM =
this.artifactListPageService.hasScannerSupportSBOM();
return (
this.hasEnabledSbom &&
this.hasSbomPermission &&
this.hasScannerSupportSBOM &&
//this.hasSbomPermission &&
this.sbomDigest &&
this.downloadSbomBtnState !== ClrLoadingState.LOADING &&
this.artifactSbom !== undefined

View File

@ -170,6 +170,8 @@ export class ArtifactListPageService {
this._hasDeleteImagePermission = results[2];
this._hasScanImagePermission = results[3];
this._hasSbomPermission = results?.[4] ?? false;
// TODO need to remove the static code
this._hasSbomPermission = true;
},
error => this.errorHandlerService.error(error)
);

View File

@ -53,9 +53,9 @@
!(
canGenerateSbomNow() &&
selectedRowHasSbom() &&
hasEnabledSbom &&
hasScannerSupportSBOM &&
hasSbomPermission
hasEnabledScanner &&
hasSbomPermission &&
hasScannerSupportSBOM
)
"
(click)="generateSbom()">

View File

@ -46,7 +46,6 @@ import {
ConfirmationButtons,
ConfirmationState,
ConfirmationTargets,
ScanTypes,
} from '../../../../../../../shared/entities/shared.const';
import {
operateChanges,
@ -102,7 +101,6 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
projectName: string;
repoName: string;
registryUrl: string;
sbomEnabled: boolean;
artifactList: ArtifactFront[] = [];
availableTime = AVAILABLE_TIME;
inprogress: boolean;
@ -240,7 +238,6 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
ngOnInit() {
const appConfig = this.appConfigService.getConfig();
this.registryUrl = appConfig.registry_url;
this.sbomEnabled = appConfig.sbom_enabled;
this.initRouterData();
if (!this.updateArtifactSub) {
this.updateArtifactSub = this.eventService.subscribe(
@ -753,11 +750,15 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
if (this.activatedRoute.snapshot.queryParams[UN_LOGGED_PARAM] === YES) {
this.router.navigate(relativeRouterLink, {
relativeTo: this.activatedRoute,
queryParams: { [UN_LOGGED_PARAM]: YES },
queryParams: {
[UN_LOGGED_PARAM]: YES,
sbomDigest: artifact.sbomDigest ?? '',
},
});
} else {
this.router.navigate(relativeRouterLink, {
relativeTo: this.activatedRoute,
queryParams: { sbomDigest: artifact.sbomDigest ?? '' },
});
}
}
@ -981,6 +982,10 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
}
}
}
// when finished, remove it from selectedRow
sbomFinished(artifact: Artifact) {
this.scanFinished(artifact);
}
// when finished, remove it from selectedRow
sbomFinished(artifact: Artifact) {
@ -1127,7 +1132,7 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
if (this.selectedRow && this.selectedRow.length) {
let flag: boolean = true;
this.selectedRow.forEach(item => {
const st: string = this.scanStatus(item);
const st: string = this.sbomStatus(item);
if (!this.isRunningState(st)) {
flag = false;
}

View File

@ -60,6 +60,7 @@
[repoName]="repositoryName"
[digest]="artifactDigest"
[sbomDigest]="sbomDigest"
[tab]="activeTab"
[additionLinks]="artifact?.addition_links"></artifact-additions>
</ng-container>
<div *ngIf="loading" class="clr-row mt-3 center">

View File

@ -22,6 +22,7 @@ export class ArtifactSummaryComponent implements OnInit {
tagId: string;
artifactDigest: string;
sbomDigest?: string;
activeTab?: string;
repositoryName: string;
projectId: string | number;
referArtifactNameArray: string[] = [];
@ -96,6 +97,7 @@ export class ArtifactSummaryComponent implements OnInit {
this.artifactDigest = this.route.snapshot.params['digest'];
this.projectId = this.route.snapshot.parent.params['id'];
this.sbomDigest = this.route.snapshot.queryParams['sbomDigest'];
this.activeTab = this.route.snapshot.queryParams['tab'];
if (this.repositoryName && this.artifactDigest) {
const resolverData = this.route.snapshot.data;
if (resolverData) {

View File

@ -216,10 +216,7 @@ export const ArtifactSbomFieldMapper = {
* else return false.
*/
export function isSpdxSbom(sbomJson?: Object): boolean {
return sbomJson[ArtifactSbomFieldMapper.sbomVersion] ||
sbomJson[ArtifactSbomFieldMapper.sbomId]
? true
: false;
return Object.keys(sbomJson ?? {}).includes(ArtifactSbomFieldMapper.sbomId);
}
/**
@ -343,7 +340,6 @@ export function readDataFromArtifactSbomJson(
*/
export function getArtifactSbom(sbomJson?: Object): ArtifactSbom {
if (sbomJson) {
// only support to parse spdx json
if (isSpdxSbom(sbomJson)) {
const artifactSbom = <ArtifactSbom>{};
artifactSbom.sbomJsonRaw = sbomJson;

View File

@ -10,7 +10,6 @@ import { SbomTipHistogramComponent } from './sbom-tip-histogram/sbom-tip-histogr
import { SBOMOverview } from './sbom-overview';
import { of, timer } from 'rxjs';
import { ArtifactService, ScanService } from 'ng-swagger-gen/services';
import { Artifact } from 'ng-swagger-gen/models';
describe('ResultSbomComponent (inline template)', () => {
let component: ResultSbomComponent;

View File

@ -219,7 +219,7 @@ export class ResultSbomComponent implements OnInit, OnDestroy {
projectName: this.projectName,
repositoryName: dbEncodeURIComponent(this.repoName),
reference: this.artifactDigest,
withScanOverview: true,
withSbomOverview: true,
XAcceptVulnerabilities: DEFAULT_SUPPORTED_MIME_TYPES,
})
.subscribe(

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ScannerVo, SbomSummary } from '../../../../../../shared/services';
@ -20,9 +20,8 @@ const SUCCESS_PCT: number = 100;
templateUrl: './sbom-tip-histogram.component.html',
styleUrls: ['./sbom-tip-histogram.component.scss'],
})
export class SbomTipHistogramComponent implements OnInit {
export class SbomTipHistogramComponent {
@Input() scanner: ScannerVo;
_sbomPackages: number = 0;
@Input() sbomSummary: SbomSummary = {
scan_status: SBOM_SCAN_STATUS.NOT_GENERATED_SBOM,
};
@ -34,22 +33,6 @@ export class SbomTipHistogramComponent implements OnInit {
private router: Router
) {}
ngOnInit(): void {
this._sbomPackages = this.sbomSummary?.summary?.total ?? 0;
}
get sbomPackages(): number {
return this._sbomPackages;
}
get sevSummary(): { [key: string]: number } {
if (this.sbomSummary && this.sbomSummary.summary) {
return this.sbomSummary.summary.summary;
}
return null;
}
duration(): string {
if (this.sbomSummary && this.sbomSummary.duration) {
let str = '';

View File

@ -29,7 +29,6 @@ export class AppConfig {
registry_storage_provider_name: string;
read_only: boolean;
show_popular_repo: boolean;
sbom_enabled: boolean;
banner_message: string;
current_time: string;
oidc_provider_name: string;
@ -44,7 +43,6 @@ export class AppConfig {
this.project_creation_restriction = 'everyone';
this.self_registration = true;
this.has_ca_root = false;
this.sbom_enabled = false;
this.harbor_version = 'unknown';
this.clair_vulnerability_status = {
overall_last_update: 0,

View File

@ -213,12 +213,9 @@ export interface VulnerabilitySummary {
}
export interface SbomSummary {
report_id?: string;
mime_type?: string;
sbom_digest?: string;
scan_status?: string;
severity?: string;
duration?: number;
summary?: SeveritySummary;
start_time?: Date;
end_time?: Date;
scanner?: ScannerVo;