mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 18:55:18 +01:00
Merge pull request #3567 from ninjadq/project_level_policy_ui_enhancement
enhancement the presentation of project level policy
This commit is contained in:
commit
ab7627e5c3
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "harbor-ui",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||
"scripts": {
|
||||
"start": "ng serve --host 0.0.0.0 --port 4500 --proxy-config proxy.config.json",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "harbor-ui",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.9",
|
||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||
"author": "VMware",
|
||||
"module": "index.js",
|
||||
|
@ -11,22 +11,22 @@ export const PROJECT_POLICY_CONFIG_TEMPLATE = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" *ngIf="withNotary || withClair">
|
||||
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SECURITY' | translate }}</label>
|
||||
<div class="form-content">
|
||||
<div>
|
||||
<div *ngIf="withNotary">
|
||||
<clr-checkbox [(ngModel)]="projectPolicy.ContentTrust" name="content-trust"
|
||||
[clrDisabled]="!hasProjectAdminRole">{{ 'PROJECT_CONFIG.CONTENT_TRUST_TOGGLE' | translate }}</clr-checkbox>
|
||||
<div class="chk-explain"><label> {{ 'PROJECT_CONFIG.CONTENT_TRUST_POLCIY' | translate }} </label></div>
|
||||
</div>
|
||||
<div>
|
||||
<div *ngIf="withClair">
|
||||
<clr-checkbox [(ngModel)]="projectPolicy.PreventVulImg" name="prevent-vulenrability-image" [clrDisabled]="!hasProjectAdminRole">{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_TOGGLE' | translate }}</clr-checkbox>
|
||||
<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.PreventVulImgServerity" [disabled]="!projectPolicy.PreventVulImg">
|
||||
<select id="severity" name="severity" [(ngModel)]="projectPolicy.PreventVulImgSeverity" [disabled]="!projectPolicy.PreventVulImg">
|
||||
<option *ngFor='let s of severityOptions' [ngValue]="s.severity">{{ s.severityLevel | translate | uppercase }}</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -37,7 +37,7 @@ export const PROJECT_POLICY_CONFIG_TEMPLATE = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" *ngIf="withClair">
|
||||
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SCAN' | translate }}</label>
|
||||
<div class="form-content">
|
||||
<clr-checkbox [(ngModel)]="projectPolicy.ScanImgOnPush" name="scan-image-on-push" [clrDisabled]="!hasProjectAdminRole">{{ 'PROJECT_CONFIG.AUTOSCAN_TOGGLE' | translate }}</clr-checkbox>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { SystemInfoService, SystemInfoDefaultService } from './../service/system-info.service';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ErrorHandler } from '../error-handler/error-handler';
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
@ -5,13 +6,88 @@ import { ProjectPolicyConfigComponent } from './project-policy-config.component'
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ProjectService, ProjectDefaultService} from '../service/project.service';
|
||||
import { SERVICE_CONFIG, IServiceConfig} from '../service.config';
|
||||
import { SystemInfo } from '../service/interface';
|
||||
import { Project } from './project';
|
||||
|
||||
describe('ProjectPolicyConfigComponent', () => {
|
||||
|
||||
let systemInfoService: SystemInfoService;
|
||||
let projectPolicyService: ProjectService;
|
||||
|
||||
let spySystemInfo: jasmine.Spy;
|
||||
let spyProjectPolicies: jasmine.Spy;
|
||||
|
||||
let mockSystemInfo: SystemInfo[] = [
|
||||
{
|
||||
'with_clair': true,
|
||||
'with_notary': true,
|
||||
'with_admiral': false,
|
||||
'admiral_endpoint': 'NA',
|
||||
'auth_mode': 'db_auth',
|
||||
'registry_url': '10.112.122.56',
|
||||
'project_creation_restriction': 'everyone',
|
||||
'self_registration': true,
|
||||
'has_ca_root': false,
|
||||
'harbor_version': 'v1.1.1-rc1-160-g565110d'
|
||||
},
|
||||
{
|
||||
'with_clair': false,
|
||||
'with_notary': false,
|
||||
'with_admiral': false,
|
||||
'admiral_endpoint': 'NA',
|
||||
'auth_mode': 'db_auth',
|
||||
'registry_url': '10.112.122.56',
|
||||
'project_creation_restriction': 'everyone',
|
||||
'self_registration': true,
|
||||
'has_ca_root': false,
|
||||
'harbor_version': 'v1.1.1-rc1-160-g565110d'
|
||||
}
|
||||
];
|
||||
|
||||
let mockPorjectPolicies: Project[] | any[] = [
|
||||
{
|
||||
'project_id': 1,
|
||||
'owner_id': 1,
|
||||
'name': 'library',
|
||||
'creation_time': '2017-11-03T02:37:24Z',
|
||||
'update_time': '2017-11-03T02:37:24Z',
|
||||
'deleted': 0,
|
||||
'owner_name': '',
|
||||
'togglable': false,
|
||||
'current_user_role_id': 0,
|
||||
'repo_count': 0,
|
||||
'metadata': {
|
||||
'public': 'true'
|
||||
}
|
||||
},
|
||||
{
|
||||
'project_id': 2,
|
||||
'owner_id': 1,
|
||||
'name': 'test',
|
||||
'creation_time': '2017-11-03T02:37:24Z',
|
||||
'update_time': '2017-11-03T02:37:24Z',
|
||||
'deleted': 0,
|
||||
'owner_name': '',
|
||||
'togglable': false,
|
||||
'current_user_role_id': 0,
|
||||
'repo_count': 0,
|
||||
'metadata': {
|
||||
'auto_scan': 'true',
|
||||
'enable_content_trust': 'true',
|
||||
'prevent_vul': 'true',
|
||||
'public': 'true',
|
||||
'severity': 'low'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
let component: ProjectPolicyConfigComponent;
|
||||
let fixture: ComponentFixture<ProjectPolicyConfigComponent>;
|
||||
|
||||
let config: IServiceConfig = {
|
||||
projectPolicyEndpoint: '/api/projects/testing/:id/'
|
||||
projectPolicyEndpoint: '/api/projects/testing',
|
||||
systemInfoEndpoint: '/api/systeminfo/testing',
|
||||
};
|
||||
|
||||
beforeEach(async(() => {
|
||||
@ -25,7 +101,8 @@ describe('ProjectPolicyConfigComponent', () => {
|
||||
providers: [
|
||||
ErrorHandler,
|
||||
{ provide: SERVICE_CONFIG, useValue: config },
|
||||
{ provide: ProjectService, useClass: ProjectDefaultService }
|
||||
{ provide: ProjectService, useClass: ProjectDefaultService },
|
||||
{ provide: SystemInfoService, useClass: SystemInfoDefaultService}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
@ -36,6 +113,13 @@ describe('ProjectPolicyConfigComponent', () => {
|
||||
component = fixture.componentInstance;
|
||||
component.projectId = 1;
|
||||
component.hasProjectAdminRole = true;
|
||||
|
||||
systemInfoService = fixture.debugElement.injector.get(SystemInfoService);
|
||||
projectPolicyService = fixture.debugElement.injector.get(ProjectService);
|
||||
|
||||
spySystemInfo = spyOn(systemInfoService, 'getSystemInfo').and.returnValues(Promise.resolve(mockSystemInfo[0]));
|
||||
spyProjectPolicies = spyOn(projectPolicyService, 'getProject').and.returnValues(Promise.resolve(mockPorjectPolicies[0]));
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -14,19 +14,20 @@ import { ConfirmationAcknowledgement } from '../confirmation-dialog/confirmation
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { Project } from './project';
|
||||
import {SystemInfo, SystemInfoService} from '../service/index';
|
||||
|
||||
export class ProjectPolicy {
|
||||
Public: boolean;
|
||||
ContentTrust: boolean;
|
||||
PreventVulImg: boolean;
|
||||
PreventVulImgServerity: string;
|
||||
PreventVulImgSeverity: string;
|
||||
ScanImgOnPush: boolean;
|
||||
|
||||
constructor() {
|
||||
this.Public = false;
|
||||
this.ContentTrust = false;
|
||||
this.PreventVulImg = false;
|
||||
this.PreventVulImgServerity = 'low';
|
||||
this.PreventVulImgSeverity = 'low';
|
||||
this.ScanImgOnPush = false;
|
||||
}
|
||||
|
||||
@ -34,7 +35,7 @@ export class ProjectPolicy {
|
||||
this.Public = pro.metadata.public === 'true' ? true : false;
|
||||
this.ContentTrust = pro.metadata.enable_content_trust === 'true' ? true : false;
|
||||
this.PreventVulImg = pro.metadata.prevent_vul === 'true' ? true : false;
|
||||
if (pro.metadata.severity) { this.PreventVulImgServerity = pro.metadata.severity; };
|
||||
if (pro.metadata.severity) { this.PreventVulImgSeverity = pro.metadata.severity; };
|
||||
this.ScanImgOnPush = pro.metadata.auto_scan === 'true' ? true : false;
|
||||
};
|
||||
}
|
||||
@ -42,7 +43,7 @@ export class ProjectPolicy {
|
||||
@Component({
|
||||
selector: 'hbr-project-policy-config',
|
||||
template: PROJECT_POLICY_CONFIG_TEMPLATE,
|
||||
styles: [PROJECT_POLICY_CONFIG_STYLE]
|
||||
styles: [PROJECT_POLICY_CONFIG_STYLE],
|
||||
})
|
||||
export class ProjectPolicyConfigComponent implements OnInit {
|
||||
onGoing = false;
|
||||
@ -54,6 +55,7 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
|
||||
@ViewChild('cfgConfirmationDialog') confirmationDlg: ConfirmationDialogComponent;
|
||||
|
||||
systemInfo: SystemInfo;
|
||||
orgProjectPolicy = new ProjectPolicy();
|
||||
projectPolicy = new ProjectPolicy();
|
||||
|
||||
@ -68,25 +70,41 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
private errorHandler: ErrorHandler,
|
||||
private translate: TranslateService,
|
||||
private projectService: ProjectService,
|
||||
private systemInfoService: SystemInfoService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
// assert if project id exist
|
||||
if (!this.projectId) {
|
||||
this.errorHandler.error('Project ID cannot be unset.');
|
||||
return;
|
||||
}
|
||||
|
||||
// get system info
|
||||
toPromise<SystemInfo>(this.systemInfoService.getSystemInfo())
|
||||
.then(systemInfo => this.systemInfo = systemInfo)
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
|
||||
// retrive project level policy data
|
||||
this.retrieve();
|
||||
}
|
||||
|
||||
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 {
|
||||
toPromise<Project>(this.projectService.
|
||||
getProject(this.projectId))
|
||||
.then(
|
||||
response => {
|
||||
this.orgProjectPolicy.initByProject(response);
|
||||
this.projectPolicy.initByProject(response);
|
||||
})
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
toPromise<Project>(this.projectService.getProject(this.projectId))
|
||||
.then(
|
||||
response => {
|
||||
this.orgProjectPolicy.initByProject(response);
|
||||
this.projectPolicy.initByProject(response);
|
||||
})
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
}
|
||||
|
||||
updateProjectPolicy(projectId: string|number, pp: ProjectPolicy) {
|
||||
@ -99,7 +117,7 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
|
||||
isValid() {
|
||||
let flag = false;
|
||||
if (!this.projectPolicy.PreventVulImg || this.severityOptions.some(x => x.severity === this.projectPolicy.PreventVulImgServerity)) {
|
||||
if (!this.projectPolicy.PreventVulImg || this.severityOptions.some(x => x.severity === this.projectPolicy.PreventVulImgSeverity)) {
|
||||
flag = true;
|
||||
}
|
||||
return flag;
|
||||
@ -115,18 +133,18 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
}
|
||||
this.onGoing = true;
|
||||
toPromise<any>(this.projectService.updateProjectPolicy(this.projectId, this.projectPolicy))
|
||||
.then(() => {
|
||||
this.onGoing = false;
|
||||
.then(() => {
|
||||
this.onGoing = false;
|
||||
|
||||
this.translate.get('CONFIG.SAVE_SUCCESS').subscribe((res: string) => {
|
||||
this.errorHandler.info(res);
|
||||
});
|
||||
this.refresh();
|
||||
})
|
||||
.catch(error => {
|
||||
this.onGoing = false;
|
||||
this.errorHandler.error(error);
|
||||
this.translate.get('CONFIG.SAVE_SUCCESS').subscribe((res: string) => {
|
||||
this.errorHandler.info(res);
|
||||
});
|
||||
this.refresh();
|
||||
})
|
||||
.catch(error => {
|
||||
this.onGoing = false;
|
||||
this.errorHandler.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
|
@ -2,12 +2,11 @@ export class Project {
|
||||
project_id: number;
|
||||
owner_id: number;
|
||||
name: string;
|
||||
creation_time: Date;
|
||||
creation_time_str: string;
|
||||
creation_time: Date | string;
|
||||
deleted: number;
|
||||
owner_name: string;
|
||||
togglable: boolean;
|
||||
update_time: Date;
|
||||
update_time: Date | string;
|
||||
current_user_role_id: number;
|
||||
repo_count: number;
|
||||
has_project_admin_role: boolean;
|
||||
|
@ -74,7 +74,7 @@ export class ProjectDefaultService extends ProjectService {
|
||||
'public': projectPolicy.Public ? 'true' : 'false',
|
||||
'enable_content_trust': projectPolicy.ContentTrust ? 'true' : 'false',
|
||||
'prevent_vul': projectPolicy.PreventVulImg ? 'true' : 'false',
|
||||
'severity': projectPolicy.PreventVulImgServerity,
|
||||
'severity': projectPolicy.PreventVulImgSeverity,
|
||||
'auto_scan': projectPolicy.ScanImgOnPush ? 'true' : 'false'
|
||||
} }, HTTP_JSON_OPTIONS)
|
||||
.map(response => response.status)
|
||||
|
@ -31,7 +31,7 @@
|
||||
"clarity-icons": "^0.9.8",
|
||||
"clarity-ui": "^0.9.8",
|
||||
"core-js": "^2.4.1",
|
||||
"harbor-ui": "0.5.8",
|
||||
"harbor-ui": "0.5.9",
|
||||
"intl": "^1.2.5",
|
||||
"mutationobserver-shim": "^0.3.2",
|
||||
"ngx-cookie": "^1.0.0",
|
||||
|
Loading…
Reference in New Issue
Block a user