mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 17:47:46 +01:00
add CVE-Whitelist
Signed-off-by: Shijun Sun (c) <sshijun@vmware.com>
This commit is contained in:
parent
b98ca7bf0b
commit
274ab7bcff
@ -96,7 +96,7 @@ describe('RegistryConfigComponent (inline template)', () => {
|
|||||||
|
|
||||||
it('should render configurations to the view', async(() => {
|
it('should render configurations to the view', async(() => {
|
||||||
expect(spy.calls.count()).toEqual(1);
|
expect(spy.calls.count()).toEqual(1);
|
||||||
expect(spySystemInfo.calls.count()).toEqual(1);
|
expect(spySystemInfo.calls.count()).toEqual(2);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
|
@ -4,23 +4,27 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="proCreation">{{'CONFIG.PRO_CREATION_RESTRICTION' | translate}}</label>
|
<label for="proCreation">{{'CONFIG.PRO_CREATION_RESTRICTION' | translate}}</label>
|
||||||
<div class="select">
|
<div class="select">
|
||||||
<select id="proCreation" name="proCreation" [(ngModel)]="systemSettings.project_creation_restriction.value"
|
<select id="proCreation" name="proCreation"
|
||||||
[disabled]="disabled(systemSettings.project_creation_restriction)">
|
[(ngModel)]="systemSettings.project_creation_restriction.value"
|
||||||
|
[disabled]="disabled(systemSettings.project_creation_restriction)">
|
||||||
<option value="everyone">{{'CONFIG.PRO_CREATION_EVERYONE' | translate }}</option>
|
<option value="everyone">{{'CONFIG.PRO_CREATION_EVERYONE' | translate }}</option>
|
||||||
<option value="adminonly">{{'CONFIG.PRO_CREATION_ADMIN' | translate }}</option>
|
<option value="adminonly">{{'CONFIG.PRO_CREATION_ADMIN' | translate }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-lg tooltip-top-right">
|
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true"
|
||||||
|
class="tooltip tooltip-lg tooltip-top-right">
|
||||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.PRO_CREATION_RESTRICTION' | translate}}</span>
|
<span class="tooltip-content">{{'CONFIG.TOOLTIP.PRO_CREATION_RESTRICTION' | translate}}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tokenExpiration" class="required">{{'CONFIG.TOKEN_EXPIRATION' | translate}}</label>
|
<label for="tokenExpiration" class="required">{{'CONFIG.TOKEN_EXPIRATION' | translate}}</label>
|
||||||
<label for="tokenExpiration" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-right"
|
<label for="tokenExpiration" aria-haspopup="true" role="tooltip"
|
||||||
[class.invalid]="tokenExpirationInput.invalid && (tokenExpirationInput.dirty || tokenExpirationInput.touched)">
|
class="tooltip tooltip-validation tooltip-md tooltip-top-right"
|
||||||
<input name="tokenExpiration" type="text" #tokenExpirationInput="ngModel" [(ngModel)]="systemSettings.token_expiration.value"
|
[class.invalid]="tokenExpirationInput.invalid && (tokenExpirationInput.dirty || tokenExpirationInput.touched)">
|
||||||
required pattern="^[1-9]{1}[0-9]*$" id="tokenExpiration" size="20" [disabled]="!editable">
|
<input name="tokenExpiration" type="text" #tokenExpirationInput="ngModel"
|
||||||
|
[(ngModel)]="systemSettings.token_expiration.value"
|
||||||
|
required pattern="^[1-9]{1}[0-9]*$" id="tokenExpiration" size="20" [disabled]="!editable">
|
||||||
<span class="tooltip-content">
|
<span class="tooltip-content">
|
||||||
{{'TOOLTIP.NUMBER_REQUIRED' | translate}}
|
{{'TOOLTIP.NUMBER_REQUIRED' | translate}}
|
||||||
</span>
|
</span>
|
||||||
@ -32,10 +36,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="robotTokenExpiration" class="required">{{'ROBOT_ACCOUNT.TOKEN_EXPIRATION' | translate}}</label>
|
<label for="robotTokenExpiration" class="required">{{'ROBOT_ACCOUNT.TOKEN_EXPIRATION' | translate}}</label>
|
||||||
<label for="robotTokenExpiration" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-right"
|
<label for="robotTokenExpiration" aria-haspopup="true" role="tooltip"
|
||||||
[class.invalid]="robotTokenExpirationInput.invalid && (robotTokenExpirationInput.dirty || robotTokenExpirationInput.touched)">
|
class="tooltip tooltip-validation tooltip-md tooltip-top-right"
|
||||||
<input name="robotTokenExpiration" type="text" #robotTokenExpirationInput="ngModel" (ngModelChange)="changeToken($event)" [(ngModel)]="robotTokenExpiration"
|
[class.invalid]="robotTokenExpirationInput.invalid && (robotTokenExpirationInput.dirty || robotTokenExpirationInput.touched)">
|
||||||
required pattern="^[1-9]{1}[0-9]*$" id="robotTokenExpiration" size="20" [disabled]="!robotExpirationEditable">
|
<input name="robotTokenExpiration" type="text" #robotTokenExpirationInput="ngModel"
|
||||||
|
(ngModelChange)="changeToken($event)" [(ngModel)]="robotTokenExpiration"
|
||||||
|
required pattern="^[1-9]{1}[0-9]*$" id="robotTokenExpiration" size="20"
|
||||||
|
[disabled]="!robotExpirationEditable">
|
||||||
<span class="tooltip-content">
|
<span class="tooltip-content">
|
||||||
{{'ROBOT_ACCOUNT.NUMBER_REQUIRED' | translate}}
|
{{'ROBOT_ACCOUNT.NUMBER_REQUIRED' | translate}}
|
||||||
</span>
|
</span>
|
||||||
@ -56,22 +63,94 @@
|
|||||||
<div *ngIf="!withAdmiral" class="form-group">
|
<div *ngIf="!withAdmiral" class="form-group">
|
||||||
<label for="repoReadOnly">{{'CONFIG.REPO_READ_ONLY' | translate}}</label>
|
<label for="repoReadOnly">{{'CONFIG.REPO_READ_ONLY' | translate}}</label>
|
||||||
<clr-checkbox-wrapper>
|
<clr-checkbox-wrapper>
|
||||||
<input type="checkbox" clrCheckbox name="repoReadOnly" id="repoReadOnly" [ngModel]="systemSettings.read_only.value"
|
<input type="checkbox" clrCheckbox name="repoReadOnly" id="repoReadOnly"
|
||||||
(ngModelChange)="setRepoReadOnlyValue($event)" />
|
[ngModel]="systemSettings.read_only.value"
|
||||||
|
(ngModelChange)="setRepoReadOnlyValue($event)"/>
|
||||||
<label>
|
<label>
|
||||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right read-tooltip">
|
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true"
|
||||||
|
class="tooltip tooltip-top-right read-tooltip">
|
||||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.REPO_TOOLTIP' | translate}}</span>
|
<span class="tooltip-content">{{'CONFIG.TOOLTIP.REPO_TOOLTIP' | translate}}</span>
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
</clr-checkbox-wrapper>
|
</clr-checkbox-wrapper>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" *ngIf="withClair">
|
||||||
|
<label for="systemWhitelist">{{'CVE_WHITELIST.DEPLOYMENT_SECURITY'|translate}}</label>
|
||||||
|
<div class="form-content w-100">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<span class="title">{{'CVE_WHITELIST.CVE_WHITELIST'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{'CVE_WHITELIST.SYS_WHITELIST_EXPLAIN'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{'CVE_WHITELIST.ADD_SYS'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="hasExpired">
|
||||||
|
<span class="label label-warning">{{'CVE_WHITELIST.WARNING_SYS'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clr-row width-70per">
|
||||||
|
<div class="clr-col position-relative">
|
||||||
|
<div>
|
||||||
|
<button (click)="showAddModal=!showAddModal"
|
||||||
|
class="btn btn-link">{{'CVE_WHITELIST.ADD'|translate}}</button>
|
||||||
|
</div>
|
||||||
|
<div class="add-modal" *ngIf="showAddModal">
|
||||||
|
<div>
|
||||||
|
<clr-textarea-container>
|
||||||
|
<label>{{'CVE_WHITELIST.ENTER'|translate}}</label>
|
||||||
|
<textarea class="w-100 font-italic" clrTextarea [(ngModel)]="cveIds"
|
||||||
|
name="cveIds"></textarea>
|
||||||
|
<clr-control-helper>{{'CVE_WHITELIST.HELP'|translate}}</clr-control-helper>
|
||||||
|
</clr-textarea-container>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button [disabled]="isDisabled()" (click)="addToSystemWhitelist()"
|
||||||
|
class="btn btn-link">{{'CVE_WHITELIST.ADD'|translate}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="whitelist-window">
|
||||||
|
<li *ngIf="systemWhitelist?.items?.length<1"
|
||||||
|
class="none">{{'CVE_WHITELIST.NONE'|translate}}</li>
|
||||||
|
<li *ngFor="let item of systemWhitelist?.items;let i = index;">{{item.cve_id}}
|
||||||
|
<clr-icon (click)="deleteItem(i)" class="float-lg-right margin-top-4"
|
||||||
|
shape="times-circle"></clr-icon>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="clr-col padding-top-8">
|
||||||
|
<div class="form-group padding-left-80">
|
||||||
|
<label for="expires">{{'CVE_WHITELIST.EXPIRES_AT'|translate}}</label>
|
||||||
|
<div class="underline">
|
||||||
|
<input #dateInput placeholder="{{'CVE_WHITELIST.NEVER_EXPIRES'|translate}}" readonly
|
||||||
|
type="date" [(clrDate)]="expiresDate" newFormLayout="true">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group padding-left-80">
|
||||||
|
<clr-checkbox-wrapper>
|
||||||
|
<input [checked]="neverExpires" [(ngModel)]="neverExpires" type="checkbox" clrCheckbox
|
||||||
|
name="neverExpires" id="neverExpires"/>
|
||||||
|
<label>
|
||||||
|
{{'CVE_WHITELIST.NEVER_EXPIRES'|translate}}
|
||||||
|
</label>
|
||||||
|
</clr-checkbox-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</form>
|
</form>
|
||||||
<div>
|
<div>
|
||||||
<button type="button" id="config_system_save" class="btn btn-primary" (click)="save()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.SAVE'
|
<button type="button" id="config_system_save" class="btn btn-primary" (click)="save()"
|
||||||
|
[disabled]="(!isValid() || !hasChanges()) && (!hasWhitelistChanged) || inProgress">{{'BUTTON.SAVE'
|
||||||
| translate}}</button>
|
| translate}}</button>
|
||||||
<button type="button" class="btn btn-outline" (click)="cancel()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.CANCEL'
|
<button type="button" class="btn btn-outline" (click)="cancel()"
|
||||||
|
[disabled]="(!isValid() || !hasChanges()) && (!hasWhitelistChanged) || inProgress">{{'BUTTON.CANCEL'
|
||||||
| translate}}</button>
|
| translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
<confirmation-dialog #cfgConfirmationDialog (confirmAction)="confirmCancel($event)"></confirmation-dialog>
|
<confirmation-dialog #cfgConfirmationDialog (confirmAction)="confirmCancel($event)"></confirmation-dialog>
|
@ -1,12 +1,75 @@
|
|||||||
.subtitle {
|
.subtitle {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-tooltip {
|
.create-tooltip {
|
||||||
top: -1;
|
top: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.read-tooltip {
|
.read-tooltip {
|
||||||
top: -7px;
|
top: -7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-top-4 {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.whitelist-window {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 12px;
|
||||||
|
height: 224px;
|
||||||
|
width: 222px;
|
||||||
|
color: #0079bb;
|
||||||
|
overflow-y: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
li {
|
||||||
|
height: 24px;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.width-70per {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.none {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline {
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-0079bb {
|
||||||
|
color: #0079bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-top-8 {
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-left-80 {
|
||||||
|
padding-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-modal {
|
||||||
|
position: absolute;
|
||||||
|
padding: 0 8px;
|
||||||
|
background-color: rgb(238, 238, 238);
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,20 +1,34 @@
|
|||||||
import { Component, Input, OnInit, Output, EventEmitter, ViewChild, Inject, OnChanges, SimpleChanges } from '@angular/core';
|
|
||||||
import { NgForm } from '@angular/forms';
|
|
||||||
import { Configuration, StringValueItem } from '../config';
|
|
||||||
import { SERVICE_CONFIG, IServiceConfig } from '../../service.config';
|
|
||||||
import { clone, isEmpty, getChanges } from '../../utils';
|
|
||||||
import { ErrorHandler } from '../../error-handler/index';
|
|
||||||
import { ConfirmationMessage } from '../../confirmation-dialog/confirmation-message';
|
|
||||||
import { ConfirmationDialogComponent } from '../../confirmation-dialog/confirmation-dialog.component';
|
|
||||||
import { ConfirmationState, ConfirmationTargets } from '../../shared/shared.const';
|
|
||||||
import { ConfirmationAcknowledgement } from '../../confirmation-dialog/confirmation-state-message';
|
|
||||||
import {
|
import {
|
||||||
ConfigurationService
|
Component,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
ViewChild,
|
||||||
|
Inject,
|
||||||
|
OnChanges,
|
||||||
|
SimpleChanges,
|
||||||
|
ElementRef
|
||||||
|
} from '@angular/core';
|
||||||
|
import {NgForm} from '@angular/forms';
|
||||||
|
import {Configuration, StringValueItem} from '../config';
|
||||||
|
import {SERVICE_CONFIG, IServiceConfig} from '../../service.config';
|
||||||
|
import {clone, isEmpty, getChanges, compareValue} from '../../utils';
|
||||||
|
import {ErrorHandler} from '../../error-handler/index';
|
||||||
|
import {ConfirmationMessage} from '../../confirmation-dialog/confirmation-message';
|
||||||
|
import {ConfirmationDialogComponent} from '../../confirmation-dialog/confirmation-dialog.component';
|
||||||
|
import {ConfirmationState, ConfirmationTargets} from '../../shared/shared.const';
|
||||||
|
import {ConfirmationAcknowledgement} from '../../confirmation-dialog/confirmation-state-message';
|
||||||
|
import {
|
||||||
|
ConfigurationService, SystemCVEWhitelist, SystemInfo, SystemInfoService, VulnerabilityItem
|
||||||
} from '../../service/index';
|
} from '../../service/index';
|
||||||
import { from } from 'rxjs';
|
import {forkJoin} from "rxjs";
|
||||||
|
|
||||||
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
|
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
|
||||||
const ONE_HOUR_MINUTES: number = 60;
|
const ONE_HOUR_MINUTES: number = 60;
|
||||||
const ONE_DAY_MINUTES: number = 24 * ONE_HOUR_MINUTES;
|
const ONE_DAY_MINUTES: number = 24 * ONE_HOUR_MINUTES;
|
||||||
|
const ONE_THOUSAND: number = 1000;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'system-settings',
|
selector: 'system-settings',
|
||||||
templateUrl: './system-settings.component.html',
|
templateUrl: './system-settings.component.html',
|
||||||
@ -26,6 +40,11 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
private originalConfig: Configuration;
|
private originalConfig: Configuration;
|
||||||
downloadLink: string;
|
downloadLink: string;
|
||||||
robotTokenExpiration: string;
|
robotTokenExpiration: string;
|
||||||
|
systemWhitelist: SystemCVEWhitelist;
|
||||||
|
systemWhitelistOrigin: SystemCVEWhitelist;
|
||||||
|
cveIds: string;
|
||||||
|
showAddModal: boolean = false;
|
||||||
|
systemInfo: SystemInfo;
|
||||||
@Output() configChange: EventEmitter<Configuration> = new EventEmitter<Configuration>();
|
@Output() configChange: EventEmitter<Configuration> = new EventEmitter<Configuration>();
|
||||||
@Output() readOnlyChange: EventEmitter<boolean> = new EventEmitter<boolean>();
|
@Output() readOnlyChange: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||||
@Output() reloadSystemConfig: EventEmitter<any> = new EventEmitter<any>();
|
@Output() reloadSystemConfig: EventEmitter<any> = new EventEmitter<any>();
|
||||||
@ -34,6 +53,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
get systemSettings(): Configuration {
|
get systemSettings(): Configuration {
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
set systemSettings(cfg: Configuration) {
|
set systemSettings(cfg: Configuration) {
|
||||||
this.config = cfg;
|
this.config = cfg;
|
||||||
this.configChange.emit(this.config);
|
this.configChange.emit(this.config);
|
||||||
@ -46,6 +66,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
|
|
||||||
@ViewChild("systemConfigFrom") systemSettingsForm: NgForm;
|
@ViewChild("systemConfigFrom") systemSettingsForm: NgForm;
|
||||||
@ViewChild("cfgConfirmationDialog") confirmationDlg: ConfirmationDialogComponent;
|
@ViewChild("cfgConfirmationDialog") confirmationDlg: ConfirmationDialogComponent;
|
||||||
|
@ViewChild('dateInput') dateInput: ElementRef;
|
||||||
|
|
||||||
get editable(): boolean {
|
get editable(): boolean {
|
||||||
return this.systemSettings &&
|
return this.systemSettings &&
|
||||||
@ -85,7 +106,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
let changes = {};
|
let changes = {};
|
||||||
for (let prop in allChanges) {
|
for (let prop in allChanges) {
|
||||||
if (prop === 'token_expiration' || prop === 'read_only' || prop === 'project_creation_restriction'
|
if (prop === 'token_expiration' || prop === 'read_only' || prop === 'project_creation_restriction'
|
||||||
|| prop === 'robot_token_duration') {
|
|| prop === 'robot_token_duration') {
|
||||||
changes[prop] = allChanges[prop];
|
changes[prop] = allChanges[prop];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,11 +133,18 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
*/
|
*/
|
||||||
public save(): void {
|
public save(): void {
|
||||||
let changes = this.getChanges();
|
let changes = this.getChanges();
|
||||||
if (!isEmpty(changes)) {
|
if (!isEmpty(changes) || !compareValue(this.systemWhitelistOrigin, this.systemWhitelist)) {
|
||||||
this.onGoing = true;
|
this.onGoing = true;
|
||||||
this.configService.saveConfigurations(changes)
|
let observables = [];
|
||||||
.subscribe(response => {
|
if (!isEmpty(changes)) {
|
||||||
this.onGoing = false;
|
observables.push(this.configService.saveConfigurations(changes));
|
||||||
|
}
|
||||||
|
if (!compareValue(this.systemWhitelistOrigin, this.systemWhitelist)) {
|
||||||
|
observables.push(this.systemInfoService.updateSystemWhitelist(this.systemWhitelist));
|
||||||
|
}
|
||||||
|
forkJoin(observables).subscribe(result => {
|
||||||
|
this.onGoing = false;
|
||||||
|
if (!isEmpty(changes)) {
|
||||||
// API should return the updated configurations here
|
// API should return the updated configurations here
|
||||||
// Unfortunately API does not do that
|
// Unfortunately API does not do that
|
||||||
// To refresh the view, we can clone the original data copy
|
// To refresh the view, we can clone the original data copy
|
||||||
@ -128,12 +156,15 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.reloadSystemConfig.emit();
|
this.reloadSystemConfig.emit();
|
||||||
this.errorHandler.info('CONFIG.SAVE_SUCCESS');
|
|
||||||
}
|
}
|
||||||
, error => {
|
if (!compareValue(this.systemWhitelistOrigin, this.systemWhitelist)) {
|
||||||
this.onGoing = false;
|
this.systemWhitelistOrigin = clone(this.systemWhitelist);
|
||||||
this.errorHandler.error(error);
|
}
|
||||||
});
|
this.errorHandler.info('CONFIG.SAVE_SUCCESS');
|
||||||
|
}, error => {
|
||||||
|
this.onGoing = false;
|
||||||
|
this.errorHandler.error(error);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Inprop situation, should not come here
|
// Inprop situation, should not come here
|
||||||
console.error('Save abort because nothing changed');
|
console.error('Save abort because nothing changed');
|
||||||
@ -175,6 +206,9 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
let changes = this.getChanges();
|
let changes = this.getChanges();
|
||||||
this.reset(changes);
|
this.reset(changes);
|
||||||
this.initRobotToken();
|
this.initRobotToken();
|
||||||
|
if (!compareValue(this.systemWhitelistOrigin, this.systemWhitelist)) {
|
||||||
|
this.systemWhitelist = clone(this.systemWhitelistOrigin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +225,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
*/
|
*/
|
||||||
public cancel(): void {
|
public cancel(): void {
|
||||||
let changes = this.getChanges();
|
let changes = this.getChanges();
|
||||||
if (!isEmpty(changes)) {
|
if (!isEmpty(changes) || !compareValue(this.systemWhitelistOrigin, this.systemWhitelist)) {
|
||||||
let msg = new ConfirmationMessage(
|
let msg = new ConfirmationMessage(
|
||||||
'CONFIG.CONFIRM_TITLE',
|
'CONFIG.CONFIRM_TITLE',
|
||||||
'CONFIG.CONFIRM_SUMMARY',
|
'CONFIG.CONFIRM_SUMMARY',
|
||||||
@ -207,23 +241,59 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(@Inject(SERVICE_CONFIG) private configInfo: IServiceConfig,
|
constructor(@Inject(SERVICE_CONFIG) private configInfo: IServiceConfig,
|
||||||
private configService: ConfigurationService,
|
private configService: ConfigurationService,
|
||||||
private errorHandler: ErrorHandler) {
|
private errorHandler: ErrorHandler,
|
||||||
|
private systemInfoService: SystemInfoService) {
|
||||||
if (this.configInfo && this.configInfo.systemInfoEndpoint) {
|
if (this.configInfo && this.configInfo.systemInfoEndpoint) {
|
||||||
this.downloadLink = this.configInfo.systemInfoEndpoint + "/getcert";
|
this.downloadLink = this.configInfo.systemInfoEndpoint + "/getcert";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.initRobotToken();
|
this.initRobotToken();
|
||||||
|
this.getSystemWhitelist();
|
||||||
|
this.getSystemInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initRobotToken (): void {
|
getSystemInfo() {
|
||||||
|
this.systemInfoService.getSystemInfo()
|
||||||
|
.subscribe(systemInfo => this.systemInfo = systemInfo
|
||||||
|
, error => this.errorHandler.error(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
get withClair(): boolean {
|
||||||
|
return this.systemInfo ? this.systemInfo.with_clair : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSystemWhitelist() {
|
||||||
|
this.onGoing = true;
|
||||||
|
this.systemInfoService.getSystemWhitelist()
|
||||||
|
.subscribe((systemWhitelist) => {
|
||||||
|
this.onGoing = false;
|
||||||
|
if (!systemWhitelist.items) {
|
||||||
|
systemWhitelist.items = [];
|
||||||
|
}
|
||||||
|
if (!systemWhitelist.expires_at) {
|
||||||
|
systemWhitelist.expires_at = null;
|
||||||
|
}
|
||||||
|
this.systemWhitelist = systemWhitelist;
|
||||||
|
this.systemWhitelistOrigin = clone(systemWhitelist);
|
||||||
|
}, error => {
|
||||||
|
this.onGoing = false;
|
||||||
|
console.error('An error occurred during getting systemWhitelist');
|
||||||
|
// this.errorHandler.error(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private initRobotToken(): void {
|
||||||
if (this.config &&
|
if (this.config &&
|
||||||
this.config.robot_token_duration ) {
|
this.config.robot_token_duration) {
|
||||||
let robotExpiration = this.config.robot_token_duration.value;
|
let robotExpiration = this.config.robot_token_duration.value;
|
||||||
this.robotTokenExpiration = Math.floor(robotExpiration / ONE_DAY_MINUTES) + '';
|
this.robotTokenExpiration = Math.floor(robotExpiration / ONE_DAY_MINUTES) + '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changeToken(v: string) {
|
changeToken(v: string) {
|
||||||
if (!v || v === "") {
|
if (!v || v === "") {
|
||||||
return;
|
return;
|
||||||
@ -235,5 +305,79 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
|
|||||||
this.config.robot_token_duration.value = +v * ONE_DAY_MINUTES;
|
this.config.robot_token_duration.value = +v * ONE_DAY_MINUTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteItem(index: number) {
|
||||||
|
this.systemWhitelist.items.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
addToSystemWhitelist() {
|
||||||
|
// remove duplication and add to systemWhitelist
|
||||||
|
let map = {};
|
||||||
|
this.systemWhitelist.items.forEach(item => {
|
||||||
|
map[item.cve_id] = true;
|
||||||
|
});
|
||||||
|
this.cveIds.split(/[\n,]+/).forEach(id => {
|
||||||
|
let cveObj: any = {};
|
||||||
|
cveObj.cve_id = id.trim();
|
||||||
|
if (!map[cveObj.cve_id]) {
|
||||||
|
map[cveObj.cve_id] = true;
|
||||||
|
this.systemWhitelist.items.push(cveObj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// clear modal and close modal
|
||||||
|
this.cveIds = null;
|
||||||
|
this.showAddModal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasWhitelistChanged(): boolean {
|
||||||
|
return !compareValue(this.systemWhitelistOrigin, this.systemWhitelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisabled(): boolean {
|
||||||
|
if (this.cveIds) {
|
||||||
|
let arr = this.cveIds.split(/[\n,]+/);
|
||||||
|
let flag = false;
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
let id = arr[i].trim();
|
||||||
|
if (!/^CVE-[\d]+-[\d]+$/.test(id)) {
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get expiresDate() {
|
||||||
|
if (this.systemWhitelist && this.systemWhitelist.expires_at) {
|
||||||
|
return new Date(this.systemWhitelist.expires_at * ONE_THOUSAND);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
set expiresDate(date) {
|
||||||
|
if (this.systemWhitelist && date) {
|
||||||
|
this.systemWhitelist.expires_at = Math.floor(date.getTime() / ONE_THOUSAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get neverExpires(): boolean {
|
||||||
|
return !(this.systemWhitelist && this.systemWhitelist.expires_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
set neverExpires(flag) {
|
||||||
|
if (flag) {
|
||||||
|
this.systemWhitelist.expires_at = null;
|
||||||
|
this.systemInfoService.resetDateInput(this.dateInput);
|
||||||
|
} else {
|
||||||
|
this.systemWhitelist.expires_at = Math.floor(new Date().getTime() / ONE_THOUSAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasExpired(): boolean {
|
||||||
|
if (this.systemWhitelistOrigin && this.systemWhitelistOrigin.expires_at) {
|
||||||
|
return new Date().getTime() > this.systemWhitelistOrigin.expires_at * ONE_THOUSAND;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,68 +1,174 @@
|
|||||||
<form #projectPolicyForm="ngForm">
|
<form #projectPolicyForm="ngForm">
|
||||||
<section class="form-block">
|
<section class="form-block">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.REGISTRY' | translate }}</label>
|
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.REGISTRY' | translate }}</label>
|
||||||
<div class="form-content" id="clr-wrapper-public">
|
<div class="form-content" id="clr-wrapper-public">
|
||||||
<clr-checkbox-wrapper>
|
<clr-checkbox-wrapper>
|
||||||
<input type="checkbox" id="clr-checkbox-wrapper-public" clrCheckbox [(ngModel)]="projectPolicy.Public" name="public"
|
<input type="checkbox" id="clr-checkbox-wrapper-public" clrCheckbox
|
||||||
[disabled]="!hasChangeConfigRole" />
|
[(ngModel)]="projectPolicy.Public" name="public"
|
||||||
<label for="clr-checkbox-wrapper-public">{{ 'PROJECT_CONFIG.PUBLIC_TOGGLE' | translate }}</label>
|
[disabled]="!hasChangeConfigRole"/>
|
||||||
</clr-checkbox-wrapper>
|
<label for="clr-checkbox-wrapper-public">{{ 'PROJECT_CONFIG.PUBLIC_TOGGLE' | translate }}</label>
|
||||||
|
</clr-checkbox-wrapper>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label> {{ 'PROJECT_CONFIG.PUBLIC_POLICY' | translate }} </label>
|
<label> {{ 'PROJECT_CONFIG.PUBLIC_POLICY' | translate }} </label>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" *ngIf="withNotary || withClair">
|
|
||||||
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SECURITY' | translate }}</label>
|
|
||||||
<div class="form-content">
|
|
||||||
<div *ngIf="withNotary">
|
|
||||||
<clr-checkbox-wrapper>
|
|
||||||
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.ContentTrust" name="content-trust" [disabled]="!hasChangeConfigRole" />
|
|
||||||
<label>{{ 'PROJECT_CONFIG.CONTENT_TRUST_TOGGLE' | translate }}</label>
|
|
||||||
</clr-checkbox-wrapper>
|
|
||||||
|
|
||||||
<div class="chk-explain"><label> {{ 'PROJECT_CONFIG.CONTENT_TRUST_POLCIY' | translate }} </label></div>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="withClair" id="prevent-vulenrability-image">
|
|
||||||
<clr-checkbox-wrapper>
|
|
||||||
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.PreventVulImg" name="prevent-vulenrability-image-input"
|
|
||||||
[disabled]="!hasChangeConfigRole" />
|
|
||||||
<label>{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_TOGGLE' | translate }}</label>
|
|
||||||
</clr-checkbox-wrapper>
|
|
||||||
|
|
||||||
<div class="chk-explain">
|
|
||||||
<label>
|
|
||||||
<div id="severity-blk">
|
|
||||||
<div>{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_1' | translate }}</div>
|
|
||||||
<div class="select">
|
|
||||||
<select id="severity" name="severity" [(ngModel)]="projectPolicy.PreventVulImgSeverity" [disabled]="!projectPolicy.PreventVulImg">
|
|
||||||
<option *ngFor='let s of severityOptions' [ngValue]="s.severity">{{ s.severityLevel | translate }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div> {{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_2' | translate }} </div>
|
</div>
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="form-group" *ngIf="withNotary || withClair">
|
||||||
</div>
|
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SECURITY' | translate }}</label>
|
||||||
<div class="form-group" *ngIf="withClair">
|
<div class="form-content">
|
||||||
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SCAN' | translate }}</label>
|
<div *ngIf="withNotary">
|
||||||
<div class="form-content">
|
<clr-checkbox-wrapper>
|
||||||
<clr-checkbox-wrapper id="scan-image-on-push-wrapper">
|
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.ContentTrust" name="content-trust"
|
||||||
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.ScanImgOnPush" [disabled]="!hasChangeConfigRole"
|
[disabled]="!hasChangeConfigRole"/>
|
||||||
name="scan-image-on-push" />
|
<label>{{ 'PROJECT_CONFIG.CONTENT_TRUST_TOGGLE' | translate }}</label>
|
||||||
<label>{{ 'PROJECT_CONFIG.AUTOSCAN_TOGGLE' | translate }}</label>
|
</clr-checkbox-wrapper>
|
||||||
</clr-checkbox-wrapper>
|
|
||||||
<div class="chk-explain"><label> {{ 'PROJECT_CONFIG.AUTOSCAN_POLICY' | translate }}</label></div>
|
<div class="chk-explain"><label> {{ 'PROJECT_CONFIG.CONTENT_TRUST_POLCIY' | translate }} </label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-primary" (click)="save()" [disabled]="!isValid() || !hasChanges() || !hasChangeConfigRole">{{'BUTTON.SAVE'
|
<div *ngIf="withClair" id="prevent-vulenrability-image">
|
||||||
| translate}}</button>
|
<clr-checkbox-wrapper>
|
||||||
<button type="button" class="btn btn-outline" (click)="cancel()" [disabled]="!isValid() || !hasChanges() || !hasChangeConfigRole">{{'BUTTON.CANCEL'
|
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.PreventVulImg"
|
||||||
| translate}}</button>
|
name="prevent-vulenrability-image-input"
|
||||||
<confirmation-dialog #cfgConfirmationDialog (confirmAction)="confirmCancel($event)"></confirmation-dialog>
|
[disabled]="!hasChangeConfigRole"/>
|
||||||
</section>
|
<label>{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_TOGGLE' | translate }}</label>
|
||||||
|
</clr-checkbox-wrapper>
|
||||||
|
|
||||||
|
<div class="chk-explain">
|
||||||
|
<label>
|
||||||
|
<div id="severity-blk">
|
||||||
|
<div>{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_1' | translate }}</div>
|
||||||
|
<div class="select">
|
||||||
|
<select id="severity" name="severity"
|
||||||
|
[(ngModel)]="projectPolicy.PreventVulImgSeverity"
|
||||||
|
[disabled]="!projectPolicy.PreventVulImg">
|
||||||
|
<option *ngFor='let s of severityOptions'
|
||||||
|
[ngValue]="s.severity">{{ s.severityLevel | translate }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div> {{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_2' | translate }} </div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" *ngIf="withClair">
|
||||||
|
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SCAN' | translate }}</label>
|
||||||
|
<div class="form-content">
|
||||||
|
<clr-checkbox-wrapper id="scan-image-on-push-wrapper">
|
||||||
|
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.ScanImgOnPush"
|
||||||
|
[disabled]="!hasChangeConfigRole"
|
||||||
|
name="scan-image-on-push"/>
|
||||||
|
<label>{{ 'PROJECT_CONFIG.AUTOSCAN_TOGGLE' | translate }}</label>
|
||||||
|
</clr-checkbox-wrapper>
|
||||||
|
<div class="chk-explain"><label> {{ 'PROJECT_CONFIG.AUTOSCAN_POLICY' | translate }}</label></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" *ngIf="withClair">
|
||||||
|
<label for="systemWhitelist">{{'CVE_WHITELIST.CVE_WHITELIST'|translate}}</label>
|
||||||
|
<div class="form-content w-100">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<span>{{'CVE_WHITELIST.PRO_WHITELIST_EXPLAIN'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{'CVE_WHITELIST.PRO_OR_SYS'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{'CVE_WHITELIST.MERGE_INTO'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="hasExpired">
|
||||||
|
<span *ngIf="isUseSystemWhitelist()"
|
||||||
|
class="label label-warning">{{'CVE_WHITELIST.WARNING_SYS'|translate}}</span>
|
||||||
|
<span *ngIf="!isUseSystemWhitelist()"
|
||||||
|
class="label label-warning">{{'CVE_WHITELIST.WARNING_PRO'|translate}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<clr-radio-container clrInline>
|
||||||
|
<clr-radio-wrapper>
|
||||||
|
<input type="radio" clrRadio name="systemWhitelistOrProjectWhitelist" required value="true"
|
||||||
|
[(ngModel)]="systemWhitelistOrProjectWhitelist"/>
|
||||||
|
<label>{{'CVE_WHITELIST.SYS_WHITELIST'|translate}}</label>
|
||||||
|
</clr-radio-wrapper>
|
||||||
|
<clr-radio-wrapper>
|
||||||
|
<input type="radio" clrRadio name="systemWhitelistOrProjectWhitelist" required value="false"
|
||||||
|
[(ngModel)]="systemWhitelistOrProjectWhitelist"/>
|
||||||
|
<label>{{'CVE_WHITELIST.PRO_WHITELIST'|translate}}</label>
|
||||||
|
</clr-radio-wrapper>
|
||||||
|
</clr-radio-container>
|
||||||
|
<div class="clr-row width-70per">
|
||||||
|
<div class="clr-col position-relative">
|
||||||
|
<div>
|
||||||
|
<button [disabled]="isUseSystemWhitelist()"
|
||||||
|
(click)="showAddModal=!showAddModal"
|
||||||
|
class="btn btn-link">{{'CVE_WHITELIST.ADD'|translate}}</button>
|
||||||
|
<button [disabled]="isUseSystemWhitelist()" (click)="addSystem()"
|
||||||
|
class="btn btn-link ml-1">{{'CVE_WHITELIST.ADD_SYSTEM'|translate}}</button>
|
||||||
|
</div>
|
||||||
|
<div class="add-modal" *ngIf="showAddModal && !isUseSystemWhitelist()">
|
||||||
|
<div>
|
||||||
|
<clr-textarea-container>
|
||||||
|
<label>{{'CVE_WHITELIST.ENTER'|translate}}</label>
|
||||||
|
<textarea class="w-100" clrTextarea [(ngModel)]="cveIds" name="cveIds"></textarea>
|
||||||
|
<clr-control-helper>{{'CVE_WHITELIST.HELP'|translate}}</clr-control-helper>
|
||||||
|
</clr-textarea-container>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button [disabled]="isDisabled()" (click)="addToProjectWhitelist()"
|
||||||
|
class="btn btn-link">{{'CVE_WHITELIST.ADD'|translate}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="whitelist-window" *ngIf="isUseSystemWhitelist()">
|
||||||
|
<li *ngIf="systemWhitelist?.items?.length<1"
|
||||||
|
class="none">{{'CVE_WHITELIST.NONE'|translate}}</li>
|
||||||
|
<li *ngFor="let item of systemWhitelist?.items">{{item.cve_id}}</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="whitelist-window" *ngIf="!isUseSystemWhitelist()">
|
||||||
|
<li class="none"
|
||||||
|
*ngIf="projectWhitelist?.items?.length<1">{{'CVE_WHITELIST.NONE'|translate}}</li>
|
||||||
|
<li *ngFor="let item of projectWhitelist?.items;let i = index;">{{item.cve_id}}
|
||||||
|
<clr-icon (click)="deleteItem(i)" class="float-lg-right margin-top-4"
|
||||||
|
shape="times-circle"></clr-icon>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="clr-col padding-top-8">
|
||||||
|
<div class="form-group padding-left-80">
|
||||||
|
<label for="expires">{{'CVE_WHITELIST.EXPIRES_AT'|translate}}</label>
|
||||||
|
<div class="underline">
|
||||||
|
<input #dateSystemInput readonly type="date" [(clrDate)]="systemExpiresDate">
|
||||||
|
<input *ngIf="!isUseSystemWhitelist()" #dateInput
|
||||||
|
placeholder="{{'CVE_WHITELIST.NEVER_EXPIRES'|translate}}" readonly type="date"
|
||||||
|
[(clrDate)]="expiresDate" newFormLayout="true">
|
||||||
|
<input *ngIf="isUseSystemWhitelist()"
|
||||||
|
placeholder="{{'CVE_WHITELIST.NEVER_EXPIRES'|translate}}" readonly type="text"
|
||||||
|
value="{{systemExpiresDateString}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group padding-left-80">
|
||||||
|
<clr-checkbox-wrapper>
|
||||||
|
<input [disabled]="isUseSystemWhitelist()" [checked]="neverExpires"
|
||||||
|
[(ngModel)]="neverExpires" type="checkbox" clrCheckbox name="neverExpires"
|
||||||
|
id="neverExpires"/>
|
||||||
|
<label>
|
||||||
|
{{'CVE_WHITELIST.NEVER_EXPIRES'|translate}}
|
||||||
|
</label>
|
||||||
|
</clr-checkbox-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-primary" (click)="save()"
|
||||||
|
[disabled]="(!isValid() || !hasChanges() || !hasChangeConfigRole) && !hasWhitelistChanged">{{'BUTTON.SAVE'
|
||||||
|
| translate}}</button>
|
||||||
|
<button type="button" class="btn btn-outline" (click)="cancel()"
|
||||||
|
[disabled]="(!isValid() || !hasChanges() || !hasChangeConfigRole) && !hasWhitelistChanged">{{'BUTTON.CANCEL'
|
||||||
|
| translate}}</button>
|
||||||
|
<confirmation-dialog #cfgConfirmationDialog (confirmAction)="confirmCancel($event)"></confirmation-dialog>
|
||||||
|
</section>
|
||||||
</form>
|
</form>
|
@ -1,8 +1,63 @@
|
|||||||
#severity-blk div
|
#severity-blk div {
|
||||||
{
|
display: inline-block;
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.select {
|
.select {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.whitelist-window {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 12px;
|
||||||
|
height: 224px;
|
||||||
|
width: 222px;
|
||||||
|
color: #0079bb;
|
||||||
|
overflow-y: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
li {
|
||||||
|
height: 24px;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.width-70per {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.none {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline {
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-0079bb {
|
||||||
|
color: #0079bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-top-8 {
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-left-80 {
|
||||||
|
padding-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-modal {
|
||||||
|
position: absolute;
|
||||||
|
padding: 0 8px;
|
||||||
|
background-color: rgb(238, 238, 238);
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,176 +1,370 @@
|
|||||||
import { Component, Input, OnInit, ViewChild } from '@angular/core';
|
import {Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core';
|
||||||
|
|
||||||
import { compareValue, clone } from '../utils';
|
import {compareValue, clone} from '../utils';
|
||||||
import { ProjectService } from '../service/project.service';
|
import {ProjectService} from '../service/project.service';
|
||||||
import { ErrorHandler } from '../error-handler/error-handler';
|
import {ErrorHandler} from '../error-handler/error-handler';
|
||||||
import { State } from '../service/interface';
|
import {State, SystemCVEWhitelist} from '../service/interface';
|
||||||
|
|
||||||
import { ConfirmationState, ConfirmationTargets } from '../shared/shared.const';
|
import {ConfirmationState, ConfirmationTargets} from '../shared/shared.const';
|
||||||
import { ConfirmationMessage } from '../confirmation-dialog/confirmation-message';
|
import {ConfirmationMessage} from '../confirmation-dialog/confirmation-message';
|
||||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
import {ConfirmationDialogComponent} from '../confirmation-dialog/confirmation-dialog.component';
|
||||||
import { ConfirmationAcknowledgement } from '../confirmation-dialog/confirmation-state-message';
|
import {ConfirmationAcknowledgement} from '../confirmation-dialog/confirmation-state-message';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import {TranslateService} from '@ngx-translate/core';
|
||||||
|
|
||||||
import { Project } from './project';
|
import {Project} from './project';
|
||||||
import {SystemInfo, SystemInfoService} from '../service/index';
|
import {SystemInfo, SystemInfoService} from '../service/index';
|
||||||
import { UserPermissionService } from '../service/permission.service';
|
import {UserPermissionService} from '../service/permission.service';
|
||||||
import { USERSTATICPERMISSION } from '../service/permission-static';
|
import {USERSTATICPERMISSION} from '../service/permission-static';
|
||||||
|
|
||||||
|
|
||||||
|
const ONE_THOUSAND: number = 1000;
|
||||||
|
const LOW: string = 'low';
|
||||||
|
|
||||||
export class ProjectPolicy {
|
export class ProjectPolicy {
|
||||||
Public: boolean;
|
Public: boolean;
|
||||||
ContentTrust: boolean;
|
ContentTrust: boolean;
|
||||||
PreventVulImg: boolean;
|
PreventVulImg: boolean;
|
||||||
PreventVulImgSeverity: string;
|
PreventVulImgSeverity: string;
|
||||||
ScanImgOnPush: boolean;
|
ScanImgOnPush: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.Public = false;
|
this.Public = false;
|
||||||
this.ContentTrust = false;
|
this.ContentTrust = false;
|
||||||
this.PreventVulImg = false;
|
this.PreventVulImg = false;
|
||||||
this.PreventVulImgSeverity = 'low';
|
this.PreventVulImgSeverity = LOW;
|
||||||
this.ScanImgOnPush = false;
|
this.ScanImgOnPush = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
initByProject(pro: Project) {
|
initByProject(pro: Project) {
|
||||||
this.Public = pro.metadata.public === 'true' ? true : false;
|
this.Public = pro.metadata.public === 'true' ? true : false;
|
||||||
this.ContentTrust = pro.metadata.enable_content_trust === 'true' ? true : false;
|
this.ContentTrust = pro.metadata.enable_content_trust === 'true' ? true : false;
|
||||||
this.PreventVulImg = pro.metadata.prevent_vul === 'true' ? true : false;
|
this.PreventVulImg = pro.metadata.prevent_vul === 'true' ? true : false;
|
||||||
if (pro.metadata.severity) { this.PreventVulImgSeverity = pro.metadata.severity; }
|
if (pro.metadata.severity) {
|
||||||
this.ScanImgOnPush = pro.metadata.auto_scan === 'true' ? true : false;
|
this.PreventVulImgSeverity = pro.metadata.severity;
|
||||||
}
|
}
|
||||||
|
this.ScanImgOnPush = pro.metadata.auto_scan === 'true' ? true : false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hbr-project-policy-config',
|
selector: 'hbr-project-policy-config',
|
||||||
templateUrl: './project-policy-config.component.html',
|
templateUrl: './project-policy-config.component.html',
|
||||||
styleUrls: ['./project-policy-config.component.scss']
|
styleUrls: ['./project-policy-config.component.scss']
|
||||||
})
|
})
|
||||||
export class ProjectPolicyConfigComponent implements OnInit {
|
export class ProjectPolicyConfigComponent implements OnInit {
|
||||||
onGoing = false;
|
onGoing = false;
|
||||||
@Input() projectId: number;
|
@Input() projectId: number;
|
||||||
@Input() projectName = 'unknown';
|
@Input() projectName = 'unknown';
|
||||||
|
|
||||||
@Input() hasSignedIn: boolean;
|
@Input() hasSignedIn: boolean;
|
||||||
@Input() hasProjectAdminRole: boolean;
|
@Input() hasProjectAdminRole: boolean;
|
||||||
|
|
||||||
@ViewChild('cfgConfirmationDialog') confirmationDlg: ConfirmationDialogComponent;
|
@ViewChild('cfgConfirmationDialog') confirmationDlg: ConfirmationDialogComponent;
|
||||||
|
@ViewChild('dateInput') dateInput: ElementRef;
|
||||||
|
@ViewChild('dateSystemInput') dateSystemInput: ElementRef;
|
||||||
|
|
||||||
systemInfo: SystemInfo;
|
systemInfo: SystemInfo;
|
||||||
orgProjectPolicy = new ProjectPolicy();
|
orgProjectPolicy = new ProjectPolicy();
|
||||||
projectPolicy = new ProjectPolicy();
|
projectPolicy = new ProjectPolicy();
|
||||||
hasChangeConfigRole: boolean;
|
hasChangeConfigRole: boolean;
|
||||||
severityOptions = [
|
severityOptions = [
|
||||||
{severity: 'high', severityLevel: 'VULNERABILITY.SEVERITY.HIGH'},
|
{severity: 'high', severityLevel: 'VULNERABILITY.SEVERITY.HIGH'},
|
||||||
{severity: 'medium', severityLevel: 'VULNERABILITY.SEVERITY.MEDIUM'},
|
{severity: 'medium', severityLevel: 'VULNERABILITY.SEVERITY.MEDIUM'},
|
||||||
{severity: 'low', severityLevel: 'VULNERABILITY.SEVERITY.LOW'},
|
{severity: 'low', severityLevel: 'VULNERABILITY.SEVERITY.LOW'},
|
||||||
{severity: 'negligible', severityLevel: 'VULNERABILITY.SEVERITY.NEGLIGIBLE'},
|
{severity: 'negligible', severityLevel: 'VULNERABILITY.SEVERITY.NEGLIGIBLE'},
|
||||||
];
|
];
|
||||||
|
userSystemWhitelist: boolean = true;
|
||||||
|
showAddModal: boolean = false;
|
||||||
|
systemWhitelist: SystemCVEWhitelist;
|
||||||
|
cveIds: string;
|
||||||
|
systemExpiresDate: Date;
|
||||||
|
systemExpiresDateString: string;
|
||||||
|
userProjectWhitelist = false;
|
||||||
|
systemWhitelistOrProjectWhitelist: string;
|
||||||
|
systemWhitelistOrProjectWhitelistOrigin: string;
|
||||||
|
projectWhitelist;
|
||||||
|
projectWhitelistOrigin;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private projectService: ProjectService,
|
private projectService: ProjectService,
|
||||||
private systemInfoService: SystemInfoService,
|
private systemInfoService: SystemInfoService,
|
||||||
private userPermission: UserPermissionService
|
private userPermission: UserPermissionService,
|
||||||
) {}
|
) {
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
// assert if project id exist
|
|
||||||
if (!this.projectId) {
|
|
||||||
this.errorHandler.error('Project ID cannot be unset.');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get system info
|
ngOnInit(): void {
|
||||||
this.systemInfoService.getSystemInfo()
|
// assert if project id exist
|
||||||
.subscribe(systemInfo => this.systemInfo = systemInfo
|
if (!this.projectId) {
|
||||||
, error => this.errorHandler.error(error));
|
this.errorHandler.error('Project ID cannot be unset.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// get system info
|
||||||
|
this.systemInfoService.getSystemInfo()
|
||||||
|
.subscribe(systemInfo => {
|
||||||
|
this.systemInfo = systemInfo;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.dateSystemInput.nativeElement.parentNode.setAttribute("hidden", "hidden");
|
||||||
|
}, 100);
|
||||||
|
} , error => this.errorHandler.error(error));
|
||||||
|
|
||||||
// retrive project level policy data
|
// retrive project level policy data
|
||||||
this.retrieve();
|
this.retrieve();
|
||||||
this.getPermission();
|
this.getPermission();
|
||||||
}
|
this.getSystemWhitelist();
|
||||||
private getPermission(): void {
|
|
||||||
this.userPermission.getPermission(this.projectId,
|
|
||||||
USERSTATICPERMISSION.CONFIGURATION.KEY, USERSTATICPERMISSION.CONFIGURATION.VALUE.UPDATE).subscribe(permissins => {
|
|
||||||
this.hasChangeConfigRole = permissins as boolean;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public get withNotary(): boolean {
|
|
||||||
return this.systemInfo ? this.systemInfo.with_notary : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get withClair(): boolean {
|
|
||||||
return this.systemInfo ? this.systemInfo.with_clair : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
retrieve(state?: State): any {
|
|
||||||
this.projectService.getProject(this.projectId)
|
|
||||||
.subscribe(
|
|
||||||
response => {
|
|
||||||
this.orgProjectPolicy.initByProject(response);
|
|
||||||
this.projectPolicy.initByProject(response);
|
|
||||||
}, error => this.errorHandler.error(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProjectPolicy(projectId: string|number, pp: ProjectPolicy) {
|
|
||||||
this.projectService.updateProjectPolicy(projectId, pp);
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.retrieve();
|
|
||||||
}
|
|
||||||
|
|
||||||
isValid() {
|
|
||||||
let flag = false;
|
|
||||||
if (!this.projectPolicy.PreventVulImg || this.severityOptions.some(x => x.severity === this.projectPolicy.PreventVulImgSeverity)) {
|
|
||||||
flag = true;
|
|
||||||
}
|
}
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasChanges() {
|
getSystemWhitelist() {
|
||||||
return !compareValue(this.orgProjectPolicy, this.projectPolicy);
|
this.systemInfoService.getSystemWhitelist()
|
||||||
}
|
.subscribe((systemWhitelist) => {
|
||||||
|
if (systemWhitelist) {
|
||||||
save() {
|
this.systemWhitelist = systemWhitelist;
|
||||||
if (!this.hasChanges()) {
|
if (this.systemWhitelist.expires_at) {
|
||||||
return;
|
this.systemExpiresDate = new Date(this.systemWhitelist.expires_at * ONE_THOUSAND);
|
||||||
|
setTimeout( () => {
|
||||||
|
this.systemExpiresDateString = this.dateSystemInput.nativeElement.value;
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, error => {
|
||||||
|
this.errorHandler.error(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this.onGoing = true;
|
|
||||||
this.projectService.updateProjectPolicy(this.projectId, this.projectPolicy)
|
|
||||||
.subscribe(() => {
|
|
||||||
this.onGoing = false;
|
|
||||||
|
|
||||||
this.translate.get('CONFIG.SAVE_SUCCESS').subscribe((res: string) => {
|
private getPermission(): void {
|
||||||
this.errorHandler.info(res);
|
this.userPermission.getPermission(this.projectId,
|
||||||
});
|
USERSTATICPERMISSION.CONFIGURATION.KEY, USERSTATICPERMISSION.CONFIGURATION.VALUE.UPDATE).subscribe(permissins => {
|
||||||
this.refresh();
|
this.hasChangeConfigRole = permissins as boolean;
|
||||||
}, error => {
|
});
|
||||||
this.onGoing = false;
|
}
|
||||||
this.errorHandler.error(error);
|
|
||||||
});
|
public get withNotary(): boolean {
|
||||||
}
|
return this.systemInfo ? this.systemInfo.with_notary : false;
|
||||||
|
}
|
||||||
cancel(): void {
|
|
||||||
let msg = new ConfirmationMessage(
|
public get withClair(): boolean {
|
||||||
'CONFIG.CONFIRM_TITLE',
|
return this.systemInfo ? this.systemInfo.with_clair : false;
|
||||||
'CONFIG.CONFIRM_SUMMARY',
|
}
|
||||||
'',
|
|
||||||
{},
|
retrieve(state?: State): any {
|
||||||
ConfirmationTargets.CONFIG
|
this.projectService.getProject(this.projectId)
|
||||||
);
|
.subscribe(
|
||||||
this.confirmationDlg.open(msg);
|
response => {
|
||||||
}
|
this.orgProjectPolicy.initByProject(response);
|
||||||
|
this.projectPolicy.initByProject(response);
|
||||||
reset(): void {
|
// get projectWhitelist
|
||||||
this.projectPolicy = clone(this.orgProjectPolicy);
|
if (!response.cve_whitelist) {
|
||||||
}
|
response.cve_whitelist = {
|
||||||
|
items: [],
|
||||||
confirmCancel(ack: ConfirmationAcknowledgement): void {
|
expires_at: null
|
||||||
if (ack && ack.source === ConfirmationTargets.CONFIG &&
|
};
|
||||||
ack.state === ConfirmationState.CONFIRMED) {
|
}
|
||||||
this.reset();
|
if (!response.cve_whitelist['items']) {
|
||||||
|
response.cve_whitelist['items'] = [];
|
||||||
|
}
|
||||||
|
if (!response.cve_whitelist['expires_at']) {
|
||||||
|
response.cve_whitelist['expires_at'] = null;
|
||||||
|
}
|
||||||
|
if (response && response.cve_whitelist) {
|
||||||
|
this.projectWhitelist = clone(response.cve_whitelist);
|
||||||
|
this.projectWhitelistOrigin = clone(response.cve_whitelist);
|
||||||
|
this.systemWhitelistOrProjectWhitelist = response.metadata.reuse_sys_cve_whitelist;
|
||||||
|
this.systemWhitelistOrProjectWhitelistOrigin = response.metadata.reuse_sys_cve_whitelist;
|
||||||
|
}
|
||||||
|
}, error => this.errorHandler.error(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this.retrieve();
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
let flag = false;
|
||||||
|
if (!this.projectPolicy.PreventVulImg || this.severityOptions.some(x => x.severity === this.projectPolicy.PreventVulImgSeverity)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasChanges() {
|
||||||
|
return !compareValue(this.orgProjectPolicy, this.projectPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
if (!this.hasChanges() && !this.hasWhitelistChanged) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.onGoing = true;
|
||||||
|
this.projectService.updateProjectPolicy(
|
||||||
|
this.projectId,
|
||||||
|
this.projectPolicy,
|
||||||
|
this.systemWhitelistOrProjectWhitelist,
|
||||||
|
this.projectWhitelist)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.onGoing = false;
|
||||||
|
this.translate.get('CONFIG.SAVE_SUCCESS').subscribe((res: string) => {
|
||||||
|
this.errorHandler.info(res);
|
||||||
|
});
|
||||||
|
this.refresh();
|
||||||
|
}, error => {
|
||||||
|
this.onGoing = false;
|
||||||
|
this.errorHandler.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel(): void {
|
||||||
|
let msg = new ConfirmationMessage(
|
||||||
|
'CONFIG.CONFIRM_TITLE',
|
||||||
|
'CONFIG.CONFIRM_SUMMARY',
|
||||||
|
'',
|
||||||
|
{},
|
||||||
|
ConfirmationTargets.CONFIG
|
||||||
|
);
|
||||||
|
this.confirmationDlg.open(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(): void {
|
||||||
|
this.projectPolicy = clone(this.orgProjectPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmCancel(ack: ConfirmationAcknowledgement): void {
|
||||||
|
if (ack && ack.source === ConfirmationTargets.CONFIG &&
|
||||||
|
ack.state === ConfirmationState.CONFIRMED) {
|
||||||
|
this.reset();
|
||||||
|
if (this.hasWhitelistChanged) {
|
||||||
|
this.projectWhitelist = clone(this.projectWhitelistOrigin);
|
||||||
|
this.systemWhitelistOrProjectWhitelist = this.systemWhitelistOrProjectWhitelistOrigin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isUseSystemWhitelist(): boolean {
|
||||||
|
return this.systemWhitelistOrProjectWhitelist === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteItem(index: number) {
|
||||||
|
this.projectWhitelist.items.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
addSystem() {
|
||||||
|
this.showAddModal = false;
|
||||||
|
if (!(this.systemWhitelist && this.systemWhitelist.items && this.systemWhitelist.items.length > 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.projectWhitelist && !this.projectWhitelist.items) {
|
||||||
|
this.projectWhitelist.items = [];
|
||||||
|
}
|
||||||
|
// remove duplication and add to projectWhitelist
|
||||||
|
let map = {};
|
||||||
|
this.projectWhitelist.items.forEach(item => {
|
||||||
|
map[item.cve_id] = true;
|
||||||
|
});
|
||||||
|
this.systemWhitelist.items.forEach(item => {
|
||||||
|
if (!map[item.cve_id]) {
|
||||||
|
map[item.cve_id] = true;
|
||||||
|
this.projectWhitelist.items.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addToProjectWhitelist() {
|
||||||
|
if (this.projectWhitelist && !this.projectWhitelist.items) {
|
||||||
|
this.projectWhitelist.items = [];
|
||||||
|
}
|
||||||
|
// remove duplication and add to projectWhitelist
|
||||||
|
let map = {};
|
||||||
|
this.projectWhitelist.items.forEach(item => {
|
||||||
|
map[item.cve_id] = true;
|
||||||
|
});
|
||||||
|
this.cveIds.split(/[\n,]+/).forEach(id => {
|
||||||
|
let cveObj: any = {};
|
||||||
|
cveObj.cve_id = id.trim();
|
||||||
|
if (!map[cveObj.cve_id]) {
|
||||||
|
map[cveObj.cve_id] = true;
|
||||||
|
this.projectWhitelist.items.push(cveObj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// clear modal and close modal
|
||||||
|
this.cveIds = null;
|
||||||
|
this.showAddModal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasWhitelistChanged(): boolean {
|
||||||
|
return !(compareValue(this.projectWhitelist, this.projectWhitelistOrigin)
|
||||||
|
&& this.systemWhitelistOrProjectWhitelistOrigin === this.systemWhitelistOrProjectWhitelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisabled(): boolean {
|
||||||
|
if (this.cveIds) {
|
||||||
|
let arr = this.cveIds.split(/[\n,]+/);
|
||||||
|
let flag = false;
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
let id = arr[i].trim();
|
||||||
|
if (!/^CVE-[\d]+-[\d]+$/.test(id)) {
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get expiresDate() {
|
||||||
|
if (this.systemWhitelistOrProjectWhitelist === 'true') {
|
||||||
|
if (this.systemWhitelist && this.systemWhitelist.expires_at) {
|
||||||
|
return new Date(this.systemWhitelist.expires_at * ONE_THOUSAND);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.projectWhitelist && this.projectWhitelist.expires_at) {
|
||||||
|
return new Date(this.projectWhitelist.expires_at * ONE_THOUSAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
set expiresDate(date) {
|
||||||
|
if (this.systemWhitelistOrProjectWhitelist === 'false') {
|
||||||
|
if (this.projectWhitelist && date) {
|
||||||
|
this.projectWhitelist.expires_at = Math.floor(date.getTime() / ONE_THOUSAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get neverExpires(): boolean {
|
||||||
|
if (this.systemWhitelistOrProjectWhitelist === 'true') {
|
||||||
|
if (this.systemWhitelist && this.systemWhitelist.expires_at) {
|
||||||
|
return !(this.systemWhitelist && this.systemWhitelist.expires_at);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.projectWhitelist && this.projectWhitelist.expires_at) {
|
||||||
|
return !(this.projectWhitelist && this.projectWhitelist.expires_at);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
set neverExpires(flag) {
|
||||||
|
if (flag) {
|
||||||
|
this.projectWhitelist.expires_at = null;
|
||||||
|
this.systemInfoService.resetDateInput(this.dateInput);
|
||||||
|
} else {
|
||||||
|
this.projectWhitelist.expires_at = Math.floor(new Date().getTime() / ONE_THOUSAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasExpired(): boolean {
|
||||||
|
if (this.systemWhitelistOrProjectWhitelist === 'true') {
|
||||||
|
if (this.systemWhitelist && this.systemWhitelist.expires_at) {
|
||||||
|
return new Date().getTime() > this.systemWhitelist.expires_at * ONE_THOUSAND;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.projectWhitelistOrigin && this.projectWhitelistOrigin.expires_at) {
|
||||||
|
return new Date().getTime() > this.projectWhitelistOrigin.expires_at * ONE_THOUSAND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ export class Project {
|
|||||||
prevent_vul: string | boolean;
|
prevent_vul: string | boolean;
|
||||||
severity: string;
|
severity: string;
|
||||||
auto_scan: string | boolean;
|
auto_scan: string | boolean;
|
||||||
|
reuse_sys_cve_whitelist?: string;
|
||||||
};
|
};
|
||||||
|
cve_whitelist?: object;
|
||||||
constructor () {
|
constructor () {
|
||||||
this.metadata.public = false;
|
this.metadata.public = false;
|
||||||
this.metadata.enable_content_trust = false;
|
this.metadata.enable_content_trust = false;
|
||||||
|
@ -434,8 +434,15 @@ export interface HttpOptionTextInterface {
|
|||||||
withCredentials?: boolean;
|
withCredentials?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface ProjectRootInterface {
|
export interface ProjectRootInterface {
|
||||||
NAME: string;
|
NAME: string;
|
||||||
VALUE: number;
|
VALUE: number;
|
||||||
LABEL: string;
|
LABEL: string;
|
||||||
}
|
}
|
||||||
|
export interface SystemCVEWhitelist {
|
||||||
|
id: number;
|
||||||
|
project_id: number;
|
||||||
|
expires_at: number;
|
||||||
|
items: Array<{ "cve_id": string; }>;
|
||||||
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
import {throwError as observableThrowError, Observable } from "rxjs";
|
import {throwError as observableThrowError, Observable } from "rxjs";
|
||||||
import { Injectable, Inject } from "@angular/core";
|
import {Injectable, Inject} from "@angular/core";
|
||||||
import { HttpClient, HttpParams, HttpResponse } from "@angular/common/http";
|
import { HttpClient, HttpParams, HttpResponse } from "@angular/common/http";
|
||||||
import { map , catchError } from "rxjs/operators";
|
import { catchError } from "rxjs/operators";
|
||||||
|
|
||||||
import { SERVICE_CONFIG, IServiceConfig } from "../service.config";
|
import { SERVICE_CONFIG, IServiceConfig } from "../service.config";
|
||||||
import { Project } from "../project-policy-config/project";
|
import { Project } from "../project-policy-config/project";
|
||||||
@ -12,7 +12,6 @@ import {
|
|||||||
HTTP_GET_OPTIONS,
|
HTTP_GET_OPTIONS,
|
||||||
buildHttpRequestOptionsWithObserveResponse
|
buildHttpRequestOptionsWithObserveResponse
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
import { RequestQueryParams } from "./RequestQueryParams";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the service methods to handle the Project related things.
|
* Define the service methods to handle the Project related things.
|
||||||
@ -47,7 +46,9 @@ export abstract class ProjectService {
|
|||||||
*/
|
*/
|
||||||
abstract updateProjectPolicy(
|
abstract updateProjectPolicy(
|
||||||
projectId: number | string,
|
projectId: number | string,
|
||||||
projectPolicy: ProjectPolicy
|
projectPolicy: ProjectPolicy,
|
||||||
|
reuseSysCVEVWhitelist: string,
|
||||||
|
projectWhitelist: object
|
||||||
): Observable<any>;
|
): Observable<any>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,7 +108,9 @@ export class ProjectDefaultService extends ProjectService {
|
|||||||
|
|
||||||
public updateProjectPolicy(
|
public updateProjectPolicy(
|
||||||
projectId: number | string,
|
projectId: number | string,
|
||||||
projectPolicy: ProjectPolicy
|
projectPolicy: ProjectPolicy,
|
||||||
|
reuseSysCVEVWhitelist: string,
|
||||||
|
projectWhitelist: object
|
||||||
): any {
|
): any {
|
||||||
let baseUrl: string = this.config.projectBaseEndpoint
|
let baseUrl: string = this.config.projectBaseEndpoint
|
||||||
? this.config.projectBaseEndpoint
|
? this.config.projectBaseEndpoint
|
||||||
@ -117,12 +120,14 @@ export class ProjectDefaultService extends ProjectService {
|
|||||||
`${baseUrl}/${projectId}`,
|
`${baseUrl}/${projectId}`,
|
||||||
{
|
{
|
||||||
metadata: {
|
metadata: {
|
||||||
public: projectPolicy.Public ? "true" : "false",
|
public: projectPolicy.Public ? "true" : "false",
|
||||||
enable_content_trust: projectPolicy.ContentTrust ? "true" : "false",
|
enable_content_trust: projectPolicy.ContentTrust ? "true" : "false",
|
||||||
prevent_vul: projectPolicy.PreventVulImg ? "true" : "false",
|
prevent_vul: projectPolicy.PreventVulImg ? "true" : "false",
|
||||||
severity: projectPolicy.PreventVulImgSeverity,
|
severity: projectPolicy.PreventVulImgSeverity,
|
||||||
auto_scan: projectPolicy.ScanImgOnPush ? "true" : "false"
|
auto_scan: projectPolicy.ScanImgOnPush ? "true" : "false",
|
||||||
}
|
reuse_sys_cve_whitelist: reuseSysCVEVWhitelist
|
||||||
|
},
|
||||||
|
cve_whitelist: projectWhitelist
|
||||||
},
|
},
|
||||||
HTTP_JSON_OPTIONS
|
HTTP_JSON_OPTIONS
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Inject, Injectable } from '@angular/core';
|
import {ElementRef, Inject, Injectable} from '@angular/core';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { map, catchError } from "rxjs/operators";
|
import { map, catchError } from "rxjs/operators";
|
||||||
import { Observable, throwError as observableThrowError } from "rxjs";
|
import { Observable, throwError as observableThrowError } from "rxjs";
|
||||||
import { SystemInfo } from './interface';
|
import {SystemCVEWhitelist, SystemInfo} from './interface';
|
||||||
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
||||||
import { HTTP_GET_OPTIONS } from "../utils";
|
import {HTTP_GET_OPTIONS, HTTP_JSON_OPTIONS} from "../utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get System information about current backend server.
|
* Get System information about current backend server.
|
||||||
@ -18,6 +18,20 @@ export abstract class SystemInfoService {
|
|||||||
* returns
|
* returns
|
||||||
*/
|
*/
|
||||||
abstract getSystemInfo(): Observable<SystemInfo>;
|
abstract getSystemInfo(): Observable<SystemInfo>;
|
||||||
|
/**
|
||||||
|
* get system CEVWhitelist
|
||||||
|
*/
|
||||||
|
abstract getSystemWhitelist(): Observable<SystemCVEWhitelist>;
|
||||||
|
/**
|
||||||
|
* update systemCVEWhitelist
|
||||||
|
* @param systemCVEWhitelist
|
||||||
|
*/
|
||||||
|
abstract updateSystemWhitelist(systemCVEWhitelist: SystemCVEWhitelist): Observable<any>;
|
||||||
|
/**
|
||||||
|
* set null to the date type input
|
||||||
|
* @param ref
|
||||||
|
*/
|
||||||
|
abstract resetDateInput(ref: ElementRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -33,5 +47,20 @@ export class SystemInfoDefaultService extends SystemInfoService {
|
|||||||
.pipe(map(systemInfo => systemInfo as SystemInfo)
|
.pipe(map(systemInfo => systemInfo as SystemInfo)
|
||||||
, catchError(error => observableThrowError(error)));
|
, catchError(error => observableThrowError(error)));
|
||||||
}
|
}
|
||||||
|
public getSystemWhitelist(): Observable<SystemCVEWhitelist> {
|
||||||
|
return this.http.get("/api/system/CVEWhitelist", HTTP_GET_OPTIONS)
|
||||||
|
.pipe(map(systemCVEWhitelist => systemCVEWhitelist as SystemCVEWhitelist)
|
||||||
|
, catchError(error => observableThrowError(error)));
|
||||||
|
}
|
||||||
|
public updateSystemWhitelist(systemCVEWhitelist: SystemCVEWhitelist): Observable<any> {
|
||||||
|
return this.http.put("/api/system/CVEWhitelist", JSON.stringify(systemCVEWhitelist), HTTP_JSON_OPTIONS)
|
||||||
|
.pipe(map(response => response)
|
||||||
|
, catchError(error => observableThrowError(error)));
|
||||||
|
}
|
||||||
|
public resetDateInput(ref: ElementRef) {
|
||||||
|
if (ref) {
|
||||||
|
ref.nativeElement.value = null ;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
171
src/portal/package-lock.json
generated
171
src/portal/package-lock.json
generated
@ -176,13 +176,15 @@
|
|||||||
"version": "1.40.0",
|
"version": "1.40.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
|
||||||
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
|
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.24",
|
"version": "2.1.24",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
|
||||||
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
|
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "1.40.0"
|
"mime-db": "1.40.0"
|
||||||
}
|
}
|
||||||
@ -3146,7 +3148,8 @@
|
|||||||
"acorn": {
|
"acorn": {
|
||||||
"version": "6.1.1",
|
"version": "6.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
|
||||||
"integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA=="
|
"integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"acorn-dynamic-import": {
|
"acorn-dynamic-import": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@ -6491,7 +6494,8 @@
|
|||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@ -6515,13 +6519,15 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -6538,19 +6544,22 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -6681,7 +6690,8 @@
|
|||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@ -6695,6 +6705,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -6711,6 +6722,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@ -6719,13 +6731,15 @@
|
|||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz",
|
||||||
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
|
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@ -6746,6 +6760,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@ -6834,7 +6849,8 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@ -6848,6 +6864,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -6943,7 +6960,8 @@
|
|||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
|
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -6985,6 +7003,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@ -7006,6 +7025,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -7054,13 +7074,15 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
|
||||||
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
|
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -10632,7 +10654,8 @@
|
|||||||
},
|
},
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@ -10650,11 +10673,13 @@
|
|||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -10667,15 +10692,18 @@
|
|||||||
},
|
},
|
||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -10778,7 +10806,8 @@
|
|||||||
},
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@ -10788,6 +10817,7 @@
|
|||||||
"is-fullwidth-code-point": {
|
"is-fullwidth-code-point": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -10800,17 +10830,20 @@
|
|||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@ -10827,6 +10860,7 @@
|
|||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@ -10899,7 +10933,8 @@
|
|||||||
},
|
},
|
||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@ -10909,6 +10944,7 @@
|
|||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -10984,7 +11020,8 @@
|
|||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -11014,6 +11051,7 @@
|
|||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@ -11031,6 +11069,7 @@
|
|||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -11069,11 +11108,13 @@
|
|||||||
},
|
},
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -17118,7 +17159,8 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@ -17139,12 +17181,14 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -17159,17 +17203,20 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -17286,7 +17333,8 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@ -17298,6 +17346,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -17312,6 +17361,7 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@ -17319,12 +17369,14 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@ -17343,6 +17395,7 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@ -17423,7 +17476,8 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@ -17435,6 +17489,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -17520,7 +17575,8 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -17556,6 +17612,7 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@ -17575,6 +17632,7 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -17618,12 +17676,14 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -18718,7 +18778,8 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@ -18739,12 +18800,14 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -18759,17 +18822,20 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -18886,7 +18952,8 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@ -18898,6 +18965,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -18912,6 +18980,7 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@ -18919,12 +18988,14 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@ -18943,6 +19014,7 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@ -19023,7 +19095,8 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@ -19035,6 +19108,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -19120,7 +19194,8 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -19156,6 +19231,7 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@ -19175,6 +19251,7 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -19218,12 +19295,14 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
<global-message [isAppLevel]="true"></global-message>
|
<global-message [isAppLevel]="true"></global-message>
|
||||||
<navigator (showAccountSettingsModal)="openModal($event)" (showPwdChangeModal)="openModal($event)"></navigator>
|
<navigator (showAccountSettingsModal)="openModal($event)" (showPwdChangeModal)="openModal($event)"></navigator>
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
<div class="content-area" [class.container-override]="showSearch" [class.content-area-override]="!shouldOverrideContent"
|
<div class="content-area" [class.container-override]="showSearch"
|
||||||
[class.start-content-padding]="shouldOverrideContent">
|
[class.content-area-override]="!shouldOverrideContent"
|
||||||
|
[class.start-content-padding]="shouldOverrideContent">
|
||||||
<global-message [isAppLevel]="false"></global-message>
|
<global-message [isAppLevel]="false"></global-message>
|
||||||
<!-- Only appear when searching -->
|
<!-- Only appear when searching -->
|
||||||
<search-result></search-result>
|
<search-result></search-result>
|
||||||
@ -11,56 +12,57 @@
|
|||||||
</div>
|
</div>
|
||||||
<clr-vertical-nav [clrVerticalNavCollapsible]="true" *ngIf="isUserExisting">
|
<clr-vertical-nav [clrVerticalNavCollapsible]="true" *ngIf="isUserExisting">
|
||||||
<div>
|
<div>
|
||||||
<a clrVerticalNavLink routerLinkActive="active" routerLink="/harbor/projects">
|
<a clrVerticalNavLink routerLinkActive="active" routerLink="/harbor/projects">
|
||||||
<clr-icon shape="organization" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="organization" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.PROJECTS' | translate}}
|
{{'SIDE_NAV.PROJECTS' | translate}}
|
||||||
</a>
|
</a>
|
||||||
<a clrVerticalNavLink routerLinkActive="active" routerLink="/harbor/logs">
|
<a clrVerticalNavLink routerLinkActive="active" routerLink="/harbor/logs">
|
||||||
<clr-icon shape="list" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="list" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.LOGS' | translate}}
|
{{'SIDE_NAV.LOGS' | translate}}
|
||||||
</a>
|
</a>
|
||||||
<clr-vertical-nav-group *ngIf="isSystemAdmin" routerLinkActive="active">
|
<clr-vertical-nav-group *ngIf="isSystemAdmin" routerLinkActive="active">
|
||||||
<clr-icon shape="administrator" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="administrator" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.NAME' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.NAME' | translate}}
|
||||||
<a routerLink="#" hidden aria-hidden="true"></a>
|
<a routerLink="#" hidden aria-hidden="true"></a>
|
||||||
<clr-vertical-nav-group-children *clrIfExpanded="true">
|
<clr-vertical-nav-group-children *clrIfExpanded="true">
|
||||||
<a clrVerticalNavLink routerLink="/harbor/users" routerLinkActive="active">
|
<a clrVerticalNavLink routerLink="/harbor/users" routerLinkActive="active">
|
||||||
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}
|
||||||
</a>
|
</a>
|
||||||
<a *ngIf='isLdapMode || isHttpAuthMode' clrVerticalNavLink routerLink="/harbor/groups" routerLinkActive="active">
|
<a *ngIf='isLdapMode' clrVerticalNavLink routerLink="/harbor/groups" routerLinkActive="active">
|
||||||
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.GROUP' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.GROUP' | translate}}
|
||||||
</a>
|
</a>
|
||||||
<a clrVerticalNavLink routerLink="/harbor/registries" routerLinkActive="active">
|
<a clrVerticalNavLink routerLink="/harbor/registries" routerLinkActive="active">
|
||||||
<clr-icon shape="block" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="block" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.REGISTRY' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.REGISTRY' | translate}}
|
||||||
</a>
|
</a>
|
||||||
<a clrVerticalNavLink routerLink="/harbor/replications" routerLinkActive="active">
|
<a clrVerticalNavLink routerLink="/harbor/replications" routerLinkActive="active">
|
||||||
<clr-icon shape="cloud-traffic" clrVerticalNavIcon></clr-icon>
|
<clr-icon shape="cloud-traffic" clrVerticalNavIcon></clr-icon>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.REPLICATION' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.REPLICATION' | translate}}
|
||||||
</a>
|
</a>
|
||||||
<a clrVerticalNavLink routerLink="/harbor/configs" routerLinkActive="active">
|
</clr-vertical-nav-group-children>
|
||||||
<clr-icon shape="cog" clrVerticalNavIcon></clr-icon>
|
</clr-vertical-nav-group>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.CONFIG' | translate}}
|
<clr-vertical-nav-group *ngIf="isSystemAdmin && (withClair || hasAdminRole)" routerLinkActive="active">
|
||||||
</a>
|
<clr-icon shape="event" clrVerticalNavIcon></clr-icon>
|
||||||
</clr-vertical-nav-group-children>
|
{{'SIDE_NAV.TASKS' | translate}}
|
||||||
</clr-vertical-nav-group>
|
<a routerLink="#" hidden aria-hidden="true"></a>
|
||||||
<clr-vertical-nav-group *ngIf="isSystemAdmin && (withClair || hasAdminRole)" routerLinkActive="active">
|
<clr-vertical-nav-group-children *clrIfExpanded="true">
|
||||||
<clr-icon shape="event" clrVerticalNavIcon></clr-icon>
|
<a clrVerticalNavLink *ngIf="withClair" routerLink="/harbor/vulnerability"
|
||||||
{{'SIDE_NAV.TASKS' | translate}}
|
routerLinkActive="active">
|
||||||
<a routerLink="#" hidden aria-hidden="true"></a>
|
{{'SIDE_NAV.SYSTEM_MGMT.VULNERABILITY' | translate}}
|
||||||
<clr-vertical-nav-group-children *clrIfExpanded="true">
|
</a>
|
||||||
<a clrVerticalNavLink *ngIf="withClair" routerLink="/harbor/vulnerability" routerLinkActive="active">
|
<a clrVerticalNavLink *ngIf="hasAdminRole" routerLink="/harbor/gc" routerLinkActive="active">
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.VULNERABILITY' | translate}}
|
{{'SIDE_NAV.SYSTEM_MGMT.GARBAGE_COLLECTION' | translate}}
|
||||||
</a>
|
</a>
|
||||||
<a clrVerticalNavLink *ngIf="hasAdminRole" routerLink="/harbor/gc" routerLinkActive="active">
|
</clr-vertical-nav-group-children>
|
||||||
{{'SIDE_NAV.SYSTEM_MGMT.GARBAGE_COLLECTION' | translate}}
|
</clr-vertical-nav-group>
|
||||||
</a>
|
<a *ngIf="isSystemAdmin" clrVerticalNavLink routerLinkActive="active" routerLink="/harbor/configs">
|
||||||
</clr-vertical-nav-group-children>
|
<clr-icon shape="cog" clrVerticalNavIcon></clr-icon>
|
||||||
</clr-vertical-nav-group>
|
{{'SIDE_NAV.SYSTEM_MGMT.CONFIG' | translate}}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="vertical-nav-footer">
|
<div class="vertical-nav-footer">
|
||||||
<a clrVerticalNavLink target="_blank" routerLink="/devcenter">
|
<a clrVerticalNavLink target="_blank" routerLink="/devcenter">
|
||||||
<button type="button" class="btn btn-sm api-button">
|
<button type="button" class="btn btn-sm api-button">
|
||||||
<span>{{'SIDE_NAV.API_EXPLORER' | translate }}</span>
|
<span>{{'SIDE_NAV.API_EXPLORER' | translate }}</span>
|
||||||
|
@ -1024,6 +1024,26 @@
|
|||||||
"MSG_SUCCESS": "Retag successfully",
|
"MSG_SUCCESS": "Retag successfully",
|
||||||
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
||||||
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
||||||
|
},
|
||||||
|
"CVE_WHITELIST": {
|
||||||
|
"DEPLOYMENT_SECURITY": "Deployment security",
|
||||||
|
"CVE_WHITELIST": "CVE whitelist",
|
||||||
|
"SYS_WHITELIST_EXPLAIN": "System whitelist allows vulnerabilities in this list to be ignored when calculating the vulnerability of an image.",
|
||||||
|
"ADD_SYS": "Add CVE IDs to the system whitelist",
|
||||||
|
"WARNING_SYS": "The system CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"WARNING_PRO": "The project CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"ADD": "ADD",
|
||||||
|
"ENTER": "Enter CVE ID(s)",
|
||||||
|
"HELP": "Separator: commas or newline characters",
|
||||||
|
"NONE": "None",
|
||||||
|
"EXPIRES_AT": "Expires at",
|
||||||
|
"NEVER_EXPIRES": "Never expires",
|
||||||
|
"PRO_WHITELIST_EXPLAIN": "Project whitelist allows vulnerabilities in this list to be ignored in this project when pushing and pulling images.",
|
||||||
|
"PRO_OR_SYS": "Use the system whitelist as is or select “Project whitelist” to create a new whitelist.",
|
||||||
|
"MERGE_INTO": "Merge the system whitelist into this project, add individual CVE IDs.",
|
||||||
|
"SYS_WHITELIST": "System whitelist",
|
||||||
|
"PRO_WHITELIST": "Project whitelist",
|
||||||
|
"ADD_SYSTEM": "ADD SYSTEM"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1022,6 +1022,26 @@
|
|||||||
"MSG_SUCCESS": "Retag successfully",
|
"MSG_SUCCESS": "Retag successfully",
|
||||||
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
||||||
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
||||||
|
},
|
||||||
|
"CVE_WHITELIST": {
|
||||||
|
"DEPLOYMENT_SECURITY": "Deployment security",
|
||||||
|
"CVE_WHITELIST": "CVE whitelist",
|
||||||
|
"SYS_WHITELIST_EXPLAIN": "System whitelist allows vulnerabilities in this list to be ignored when calculating the vulnerability of an image.",
|
||||||
|
"ADD_SYS": "Add CVE IDs to the system whitelist",
|
||||||
|
"WARNING_SYS": "The system CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"WARNING_PRO": "The project CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"ADD": "ADD",
|
||||||
|
"ENTER": "Enter CVE ID(s)",
|
||||||
|
"HELP": "Separator: commas or newline characters",
|
||||||
|
"NONE": "None",
|
||||||
|
"EXPIRES_AT": "Expires at",
|
||||||
|
"NEVER_EXPIRES": "Never expires",
|
||||||
|
"PRO_WHITELIST_EXPLAIN": "Project whitelist allows vulnerabilities in this list to be ignored in this project when pushing and pulling images.",
|
||||||
|
"PRO_OR_SYS": "Use the system whitelist as is or select “Project whitelist” to create a new whitelist.",
|
||||||
|
"MERGE_INTO": "Merge the system whitelist into this project, add individual CVE IDs.",
|
||||||
|
"SYS_WHITELIST": "System whitelist",
|
||||||
|
"PRO_WHITELIST": "Project whitelist",
|
||||||
|
"ADD_SYSTEM": "ADD SYSTEM"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -994,6 +994,26 @@
|
|||||||
"MSG_SUCCESS": "Retag successfully",
|
"MSG_SUCCESS": "Retag successfully",
|
||||||
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
||||||
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
||||||
|
},
|
||||||
|
"CVE_WHITELIST": {
|
||||||
|
"DEPLOYMENT_SECURITY": "Deployment security",
|
||||||
|
"CVE_WHITELIST": "CVE whitelist",
|
||||||
|
"SYS_WHITELIST_EXPLAIN": "System whitelist allows vulnerabilities in this list to be ignored when calculating the vulnerability of an image.",
|
||||||
|
"ADD_SYS": "Add CVE IDs to the system whitelist",
|
||||||
|
"WARNING_SYS": "The system CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"WARNING_PRO": "The project CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"ADD": "ADD",
|
||||||
|
"ENTER": "Enter CVE ID(s)",
|
||||||
|
"HELP": "Separator: commas or newline characters",
|
||||||
|
"NONE": "None",
|
||||||
|
"EXPIRES_AT": "Expires at",
|
||||||
|
"NEVER_EXPIRES": "Never expires",
|
||||||
|
"PRO_WHITELIST_EXPLAIN": "Project whitelist allows vulnerabilities in this list to be ignored in this project when pushing and pulling images.",
|
||||||
|
"PRO_OR_SYS": "Use the system whitelist as is or select “Project whitelist” to create a new whitelist.",
|
||||||
|
"MERGE_INTO": "Merge the system whitelist into this project, add individual CVE IDs.",
|
||||||
|
"SYS_WHITELIST": "System whitelist",
|
||||||
|
"PRO_WHITELIST": "Project whitelist",
|
||||||
|
"ADD_SYSTEM": "ADD SYSTEM"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1018,6 +1018,26 @@
|
|||||||
"MSG_SUCCESS": "Retag successfully",
|
"MSG_SUCCESS": "Retag successfully",
|
||||||
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
"TIP_REPO": "A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*.If a repository name has two or more path components, they must be separated by a forward slash ('/').The total length of a repository name, including slashes, must be less the 256 characters.",
|
||||||
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
"TIP_TAG": "A tag is a label applied to a Docker image in a repository. Tags are how various images in a repository are distinguished from each other.It need to match Regex: (`[\\w][\\w.-]{0,127}`)"
|
||||||
|
},
|
||||||
|
"CVE_WHITELIST": {
|
||||||
|
"DEPLOYMENT_SECURITY": "Deployment security",
|
||||||
|
"CVE_WHITELIST": "CVE whitelist",
|
||||||
|
"SYS_WHITELIST_EXPLAIN": "System whitelist allows vulnerabilities in this list to be ignored when calculating the vulnerability of an image.",
|
||||||
|
"ADD_SYS": "Add CVE IDs to the system whitelist",
|
||||||
|
"WARNING_SYS": "The system CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"WARNING_PRO": "The project CVE whitelist has expired. You can enable the whitelist by extending the expiration date.",
|
||||||
|
"ADD": "ADD",
|
||||||
|
"ENTER": "Enter CVE ID(s)",
|
||||||
|
"HELP": "Separator: commas or newline characters",
|
||||||
|
"NONE": "None",
|
||||||
|
"EXPIRES_AT": "Expires at",
|
||||||
|
"NEVER_EXPIRES": "Never expires",
|
||||||
|
"PRO_WHITELIST_EXPLAIN": "Project whitelist allows vulnerabilities in this list to be ignored in this project when pushing and pulling images.",
|
||||||
|
"PRO_OR_SYS": "Use the system whitelist as is or select “Project whitelist” to create a new whitelist.",
|
||||||
|
"MERGE_INTO": "Merge the system whitelist into this project, add individual CVE IDs.",
|
||||||
|
"SYS_WHITELIST": "System whitelist",
|
||||||
|
"PRO_WHITELIST": "Project whitelist",
|
||||||
|
"ADD_SYSTEM": "ADD SYSTEM"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1020,6 +1020,26 @@
|
|||||||
"MSG_SUCCESS": "同步成功",
|
"MSG_SUCCESS": "同步成功",
|
||||||
"TIP_REPO": "镜像仓库名被分解为路径组件。仓库名必须至少有一个小写字母、字母数字字符,可选句点、破折号或下划线分隔。严格意义上说,它必须匹配正则表达式[a-z0-9]+(?[.-][a-z0-9]+)*.如果仓库名有两个或多个路径组件,则它们必须用正斜杠('/')分隔。包括斜杠在内的仓库名的总长度必须小于256个字符。",
|
"TIP_REPO": "镜像仓库名被分解为路径组件。仓库名必须至少有一个小写字母、字母数字字符,可选句点、破折号或下划线分隔。严格意义上说,它必须匹配正则表达式[a-z0-9]+(?[.-][a-z0-9]+)*.如果仓库名有两个或多个路径组件,则它们必须用正斜杠('/')分隔。包括斜杠在内的仓库名的总长度必须小于256个字符。",
|
||||||
"TIP_TAG": "标签是应用于存储库中的Docker映像的一种标签,它用于区分多种镜像。它需要匹配Regex:([\\w][\\w.-]{0,127})"
|
"TIP_TAG": "标签是应用于存储库中的Docker映像的一种标签,它用于区分多种镜像。它需要匹配Regex:([\\w][\\w.-]{0,127})"
|
||||||
|
},
|
||||||
|
"CVE_WHITELIST": {
|
||||||
|
"DEPLOYMENT_SECURITY": "部署安全性",
|
||||||
|
"CVE_WHITELIST": "CVE白名单",
|
||||||
|
"SYS_WHITELIST_EXPLAIN": "在计算镜像的的安全性漏洞时,在系统的CVE白名单中的漏洞将会被忽略。",
|
||||||
|
"ADD_SYS": "可添加一条或多条CVE ID至系统的CVE白名单中",
|
||||||
|
"WARNING_SYS": "系统的CVE白名单已过期. 请延长有效期以使白名单生效",
|
||||||
|
"WARNING_PRO": "该项目的CVE白名单已过期. 请延长有效期以使白名单生效",
|
||||||
|
"ADD": "添加",
|
||||||
|
"ENTER": "输入一条或多条CVE ID",
|
||||||
|
"HELP": "CVE ID之间请用英文逗号隔开或者换行",
|
||||||
|
"NONE": "无",
|
||||||
|
"EXPIRES_AT": "有效期至",
|
||||||
|
"NEVER_EXPIRES": "永不过期",
|
||||||
|
"PRO_WHITELIST_EXPLAIN": "在推送和拉取镜像时,在项目的CVE白名单中的漏洞将会被忽略",
|
||||||
|
"PRO_OR_SYS": "您可以选择使用系统的CVE白名单作为该项目的白名单,也可勾选“启用项目白名单”项来建立该项目自己的CVE白名单,",
|
||||||
|
"MERGE_INTO": "您可以点击“添加系统白名单”项将系统白名单合并至该项目白名单中,并可为该项目白名单添加特有的CVE IDs",
|
||||||
|
"SYS_WHITELIST": "启用系统白名单",
|
||||||
|
"PRO_WHITELIST": "启用项目白名单",
|
||||||
|
"ADD_SYSTEM": "添加系统白名单"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user