From 69ffd7117cc270639eb61ee267858c6994647954 Mon Sep 17 00:00:00 2001 From: "Deng, Qian" Date: Tue, 24 Oct 2017 12:56:23 +0800 Subject: [PATCH] add ui for project level policy --- src/ui/router.go | 1 + src/ui_ng/lib/src/harbor-library.module.ts | 19 ++- src/ui_ng/lib/src/index.ts | 3 +- .../lib/src/project-policy-config/index.ts | 8 + .../project-policy-config.component.css.ts | 9 + .../project-policy-config.component.html.ts | 51 ++++++ .../project-policy-config.component.spec.ts | 45 +++++ .../project-policy-config.component.ts | 155 ++++++++++++++++++ .../lib/src/project-policy-config/project.ts | 30 ++++ src/ui_ng/lib/src/service.config.ts | 8 + src/ui_ng/lib/src/service/index.ts | 3 +- src/ui_ng/lib/src/service/interface.ts | 2 +- src/ui_ng/lib/src/service/project.service.ts | 85 ++++++++++ src/ui_ng/package.json | 2 +- src/ui_ng/src/app/app.module.ts | 10 +- src/ui_ng/src/app/harbor-routing.module.ts | 5 + .../project-config.component.css | 0 .../project-config.component.html | 5 + .../project-config.component.spec.ts | 25 +++ .../project-config.component.ts | 49 ++++++ .../project-detail.component.html | 3 + .../project-detail.component.ts | 6 +- src/ui_ng/src/i18n/lang/en-us-lang.json | 17 +- src/ui_ng/src/i18n/lang/es-es-lang.json | 17 +- src/ui_ng/src/i18n/lang/zh-cn-lang.json | 17 +- 25 files changed, 557 insertions(+), 18 deletions(-) create mode 100644 src/ui_ng/lib/src/project-policy-config/index.ts create mode 100644 src/ui_ng/lib/src/project-policy-config/project-policy-config.component.css.ts create mode 100644 src/ui_ng/lib/src/project-policy-config/project-policy-config.component.html.ts create mode 100644 src/ui_ng/lib/src/project-policy-config/project-policy-config.component.spec.ts create mode 100644 src/ui_ng/lib/src/project-policy-config/project-policy-config.component.ts create mode 100644 src/ui_ng/lib/src/project-policy-config/project.ts create mode 100644 src/ui_ng/lib/src/service/project.service.ts create mode 100644 src/ui_ng/src/app/project/project-config/project-config.component.css create mode 100644 src/ui_ng/src/app/project/project-config/project-config.component.html create mode 100644 src/ui_ng/src/app/project/project-config/project-config.component.spec.ts create mode 100644 src/ui_ng/src/app/project/project-config/project-config.component.ts diff --git a/src/ui/router.go b/src/ui/router.go index 51eca5438e..5074de88f9 100644 --- a/src/ui/router.go +++ b/src/ui/router.go @@ -47,6 +47,7 @@ func initRouters() { beego.Router("/harbor/projects/:id/replications", &controllers.IndexController{}) beego.Router("/harbor/projects/:id/members", &controllers.IndexController{}) beego.Router("/harbor/projects/:id/logs", &controllers.IndexController{}) + beego.Router("/harbor/projects/:id/configs", &controllers.IndexController{}) beego.Router("/harbor/tags/:id/*", &controllers.IndexController{}) beego.Router("/harbor/users", &controllers.IndexController{}) diff --git a/src/ui_ng/lib/src/harbor-library.module.ts b/src/ui_ng/lib/src/harbor-library.module.ts index 4b08acc0f8..6582726436 100644 --- a/src/ui_ng/lib/src/harbor-library.module.ts +++ b/src/ui_ng/lib/src/harbor-library.module.ts @@ -24,6 +24,7 @@ import { VULNERABILITY_DIRECTIVES } from './vulnerability-scanning/index'; import { PUSH_IMAGE_BUTTON_DIRECTIVES } from './push-image/index'; import { CONFIGURATION_DIRECTIVES } from './config/index'; import { JOB_LOG_VIEWER_DIRECTIVES } from './job-log-viewer/index'; +import { PROJECT_POLICY_CONFIG_DIRECTIVES } from './project-policy-config/index'; import { SystemInfoService, @@ -43,7 +44,9 @@ import { ConfigurationService, ConfigurationDefaultService, JobLogService, - JobLogDefaultService + JobLogDefaultService, + ProjectService, + ProjectDefaultService, } from './service/index'; import { ErrorHandler, @@ -68,6 +71,7 @@ export const DefaultServiceConfig: IServiceConfig = { replicationRuleEndpoint: "/api/policies/replication", replicationJobEndpoint: "/api/jobs/replication", vulnerabilityScanningBaseEndpoint: "/api/repositories", + projectPolicyEndpoint: "/api/projects/configs", enablei18Support: false, defaultLang: DEFAULT_LANG, langCookieKey: DEFAULT_LANG_COOKIE_KEY, @@ -118,7 +122,10 @@ export interface HarborModuleConfig { configService?: Provider, //Service implementation for job log - jobLogService?: Provider + jobLogService?: Provider, + + //Service implementation for project policy + projectPolicyService?: Provider, } /** @@ -162,7 +169,8 @@ export function initConfig(translateInitializer: TranslateServiceInitializer, co VULNERABILITY_DIRECTIVES, PUSH_IMAGE_BUTTON_DIRECTIVES, CONFIGURATION_DIRECTIVES, - JOB_LOG_VIEWER_DIRECTIVES + JOB_LOG_VIEWER_DIRECTIVES, + PROJECT_POLICY_CONFIG_DIRECTIVES ], exports: [ LOG_DIRECTIVES, @@ -183,7 +191,8 @@ export function initConfig(translateInitializer: TranslateServiceInitializer, co PUSH_IMAGE_BUTTON_DIRECTIVES, CONFIGURATION_DIRECTIVES, JOB_LOG_VIEWER_DIRECTIVES, - TranslateModule + TranslateModule, + PROJECT_POLICY_CONFIG_DIRECTIVES ], providers: [] }) @@ -204,6 +213,7 @@ export class HarborLibraryModule { config.scanningService || { provide: ScanningResultService, useClass: ScanningResultDefaultService }, config.configService || { provide: ConfigurationService, useClass: ConfigurationDefaultService }, config.jobLogService || { provide: JobLogService, useClass: JobLogDefaultService }, + config.projectPolicyService || { provide: ProjectService, useClass: ProjectDefaultService }, //Do initializing TranslateServiceInitializer, { @@ -232,6 +242,7 @@ export class HarborLibraryModule { config.scanningService || { provide: ScanningResultService, useClass: ScanningResultDefaultService }, config.configService || { provide: ConfigurationService, useClass: ConfigurationDefaultService }, config.jobLogService || { provide: JobLogService, useClass: JobLogDefaultService }, + config.projectPolicyService || { provide: ProjectService, useClass: ProjectDefaultService }, ChannelService ] }; diff --git a/src/ui_ng/lib/src/index.ts b/src/ui_ng/lib/src/index.ts index 1366610507..586a56c5fe 100644 --- a/src/ui_ng/lib/src/index.ts +++ b/src/ui_ng/lib/src/index.ts @@ -17,4 +17,5 @@ export * from './push-image/index'; export * from './third-party/index'; export * from './config/index'; export * from './job-log-viewer/index'; -export * from './channel/index'; \ No newline at end of file +export * from './channel/index'; +export * from './project-policy-config/index'; diff --git a/src/ui_ng/lib/src/project-policy-config/index.ts b/src/ui_ng/lib/src/project-policy-config/index.ts new file mode 100644 index 0000000000..93745c1bf4 --- /dev/null +++ b/src/ui_ng/lib/src/project-policy-config/index.ts @@ -0,0 +1,8 @@ +import { Type } from '@angular/core'; +import { ProjectPolicyConfigComponent } from './project-policy-config.component'; + +export * from './project-policy-config.component' + +export const PROJECT_POLICY_CONFIG_DIRECTIVES: Type[] = [ + ProjectPolicyConfigComponent +]; diff --git a/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.css.ts b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.css.ts new file mode 100644 index 0000000000..b48779761b --- /dev/null +++ b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.css.ts @@ -0,0 +1,9 @@ +export const PROJECT_POLICY_CONFIG_STYLE = `#severity-blk div +{ + display: inline-block; +} + +.select { + width: 120px; +} +`; diff --git a/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.html.ts b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.html.ts new file mode 100644 index 0000000000..5037c9c374 --- /dev/null +++ b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.html.ts @@ -0,0 +1,51 @@ +export const PROJECT_POLICY_CONFIG_TEMPLATE = ` +
+
+
+ +
+ {{ 'PROJECT_CONFIG.PUBLIC_TOGGLE' | translate }} +
+ +
+
+
+
+ +
+
+ {{ 'PROJECT_CONFIG.CONTENT_TRUST_TOGGLE' | translate }} +
+
+
+ {{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_TOGGLE' | translate }} +
+ +
+
+
+
+
+ +
+ {{ 'PROJECT_CONFIG.AUTOSCAN_TOGGLE' | translate }} +
+
+
+ + + +
+
`; diff --git a/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.spec.ts b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.spec.ts new file mode 100644 index 0000000000..c98e7af8f7 --- /dev/null +++ b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.spec.ts @@ -0,0 +1,45 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ErrorHandler } from '../error-handler/error-handler'; +import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component'; +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'; + +describe('ProjectPolicyConfigComponent', () => { + let component: ProjectPolicyConfigComponent; + let fixture: ComponentFixture; + + let config: IServiceConfig = { + projectPolicyEndpoint: '/api/projects/testing/:id/' + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [SharedModule], + declarations: [ + ProjectPolicyConfigComponent, + ConfirmationDialogComponent, + ConfirmationDialogComponent, + ], + providers: [ + ErrorHandler, + { provide: SERVICE_CONFIG, useValue: config }, + { provide: ProjectService, useClass: ProjectDefaultService } + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ProjectPolicyConfigComponent); + component = fixture.componentInstance; + component.projectId = 1; + component.hasProjectAdminRole = true; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.ts b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.ts new file mode 100644 index 0000000000..1dfc4768bc --- /dev/null +++ b/src/ui_ng/lib/src/project-policy-config/project-policy-config.component.ts @@ -0,0 +1,155 @@ +import { Component, Input, OnInit, ViewChild } from '@angular/core'; + +import { PROJECT_POLICY_CONFIG_TEMPLATE } from './project-policy-config.component.html'; +import { PROJECT_POLICY_CONFIG_STYLE } from './project-policy-config.component.css'; +import { toPromise, compareValue, clone } from '../utils'; +import { ProjectService } from '../service/project.service'; +import { ErrorHandler } from '../error-handler/error-handler'; +import { State } from 'clarity-angular'; + +import { ConfirmationState, ConfirmationTargets, ConfirmationButtons } from '../shared/shared.const'; +import { ConfirmationMessage } from '../confirmation-dialog/confirmation-message'; +import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component'; +import { ConfirmationAcknowledgement } from '../confirmation-dialog/confirmation-state-message'; +import { TranslateService } from '@ngx-translate/core'; + +import { Project } from './project'; + +export class ProjectPolicy { + Public: boolean; + ContentTrust: boolean; + PreventVulImg: boolean; + PreventVulImgServerity: string; + ScanImgOnPush: boolean; + + constructor() { + this.Public = false; + this.ContentTrust = false; + this.PreventVulImg = false; + this.PreventVulImgServerity = 'low'; + this.ScanImgOnPush = false; + } + + initByProject(pro: Project) { + 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; }; + this.ScanImgOnPush = pro.metadata.auto_scan === 'true' ? true : false; + }; +} + +@Component({ + selector: 'hbr-project-policy-config', + template: PROJECT_POLICY_CONFIG_TEMPLATE, + styles: [PROJECT_POLICY_CONFIG_STYLE] +}) +export class ProjectPolicyConfigComponent implements OnInit { + onGoing = false; + @Input() projectId: number; + @Input() projectName = 'unknown'; + + @Input() hasSignedIn: boolean; + @Input() hasProjectAdminRole: boolean; + + @ViewChild('cfgConfirmationDialog') confirmationDlg: ConfirmationDialogComponent; + + orgProjectPolicy = new ProjectPolicy(); + projectPolicy = new ProjectPolicy(); + + severityOptions = [ + {severity: 'high', severityLevel: 'VULNERABILITY.SEVERITY.HIGH'}, + {severity: 'medium', severityLevel: 'VULNERABILITY.SEVERITY.MEDIUM'}, + {severity: 'low', severityLevel: 'VULNERABILITY.SEVERITY.LOW'}, + {severity: 'negligible', severityLevel: 'VULNERABILITY.SEVERITY.NEGLIGIBLE'}, + ]; + + constructor( + private errorHandler: ErrorHandler, + private translate: TranslateService, + private projectService: ProjectService, + ) {} + + ngOnInit(): void { + if (!this.projectId) { + this.errorHandler.error('Project ID cannot be unset.'); + return; + } + this.retrieve(); + } + + retrieve(state?: State): any { + toPromise(this.projectService. + getProject(this.projectId)) + .then( + 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.PreventVulImgServerity)) { + flag = true; + } + return flag; + } + + hasChanges() { + return compareValue(this.orgProjectPolicy, this.projectPolicy) + } + + save() { + if (!this.hasChanges()) { + return; + } + this.onGoing = true; + toPromise(this.projectService.updateProjectPolicy(this.projectId, this.projectPolicy)) + .then(() => { + this.onGoing = false; + + this.translate.get('CONFIG.SAVE_SUCCESS').subscribe((res: string) => { + this.errorHandler.info(res); + }); + this.refresh(); + }) + .catch(error => { + console.log(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(); + } + } +} diff --git a/src/ui_ng/lib/src/project-policy-config/project.ts b/src/ui_ng/lib/src/project-policy-config/project.ts new file mode 100644 index 0000000000..bf00419bd0 --- /dev/null +++ b/src/ui_ng/lib/src/project-policy-config/project.ts @@ -0,0 +1,30 @@ +export class Project { + project_id: number; + owner_id: number; + name: string; + creation_time: Date; + creation_time_str: string; + deleted: number; + owner_name: string; + togglable: boolean; + update_time: Date; + current_user_role_id: number; + repo_count: number; + has_project_admin_role: boolean; + is_member: boolean; + role_name: string; + metadata: { + public: string | boolean; + enable_content_trust: string | boolean; + prevent_vul: string | boolean; + severity: string; + auto_scan: string | boolean; + }; + constructor () { + this.metadata.public = false; + this.metadata.enable_content_trust = false; + this.metadata.prevent_vul = false; + this.metadata.severity = 'low'; + this.metadata.auto_scan = false; + } +} diff --git a/src/ui_ng/lib/src/service.config.ts b/src/ui_ng/lib/src/service.config.ts index 268f466486..1943319edf 100644 --- a/src/ui_ng/lib/src/service.config.ts +++ b/src/ui_ng/lib/src/service.config.ts @@ -80,6 +80,14 @@ export interface IServiceConfig { */ vulnerabilityScanningBaseEndpoint?: string; + /** + * The base endpoint of the service used to handle project policy. + * + * @type {string} + * @memberOf IServiceConfig + */ + projectPolicyEndpoint?: string; + /** * To determine whether or not to enable the i18 multiple languages supporting. * diff --git a/src/ui_ng/lib/src/service/index.ts b/src/ui_ng/lib/src/service/index.ts index 98bf0cb063..df69f23a08 100644 --- a/src/ui_ng/lib/src/service/index.ts +++ b/src/ui_ng/lib/src/service/index.ts @@ -8,4 +8,5 @@ export * from './tag.service'; export * from './RequestQueryParams'; export * from './scanning.service'; export * from './configuration.service'; -export * from './job-log.service'; \ No newline at end of file +export * from './job-log.service'; +export * from './project.service'; diff --git a/src/ui_ng/lib/src/service/interface.ts b/src/ui_ng/lib/src/service/interface.ts index 85af94fcb9..96fc2383d3 100644 --- a/src/ui_ng/lib/src/service/interface.ts +++ b/src/ui_ng/lib/src/service/interface.ts @@ -242,4 +242,4 @@ export interface TagClickEvent { project_id: string | number; repository_name: string; tag_name: string; -} \ No newline at end of file +} diff --git a/src/ui_ng/lib/src/service/project.service.ts b/src/ui_ng/lib/src/service/project.service.ts new file mode 100644 index 0000000000..5675462051 --- /dev/null +++ b/src/ui_ng/lib/src/service/project.service.ts @@ -0,0 +1,85 @@ +import { Observable } from 'rxjs/Observable'; +import { Injectable, Inject } from '@angular/core'; +import 'rxjs/add/observable/of'; +import { Http, Headers, RequestOptions } from '@angular/http'; +import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; + +import { Project } from '../project-policy-config/project'; +import { ProjectPolicy } from '../project-policy-config/project-policy-config.component'; + +/** + * Define the service methods to handle the Prject related things. + * + * @export + * @abstract + * @class ProjectService + */ +export abstract class ProjectService { + /** + * Get Infomations of a specific Project. + * + * @abstract + * @param {string|number} [projectId] + * @returns {(Observable | Promise | Project)} + * + * @memberOf ProjectService + */ + abstract getProject(projectId: number | string): Observable | Promise | Project; + + /** + * Update the specified project. + * + * @abstract + * @param {(number | string)} projectId + * @param {ProjectPolicy} projectPolicy + * @returns {(Observable | Promise | any)} + * + * @memberOf EndpointService + */ + abstract updateProjectPolicy(projectId: number | string, projectPolicy: ProjectPolicy): Observable | Promise | any; +} + +/** + * Implement default service for project. + * + * @export + * @class ProjectDefaultService + * @extends {ProjectService} + */ +@Injectable() +export class ProjectDefaultService extends ProjectService { + + headers = new Headers({'Content-type': 'application/json'}); + options = new RequestOptions({'headers': this.headers}); + + constructor( + private http: Http, + @Inject(SERVICE_CONFIG) private config: IServiceConfig + ) { + super(); + } + + public getProject(projectId: number | string): Observable | Promise | Project { + if (!projectId) { + return Promise.reject('Bad argument'); + } + + return this.http + .get(`/api/projects/${projectId}`) + .map(response => response.json()) + .catch(error => Observable.throw(error)); + } + + public updateProjectPolicy(projectId: number | string, projectPolicy: ProjectPolicy): any { + return this.http + .put(`/api/projects/${projectId}`, { 'metadata': { + 'public': projectPolicy.Public ? 'true' : 'false', + 'enable_content_trust': projectPolicy.ContentTrust ? 'true' : 'false', + 'prevent_vul': projectPolicy.PreventVulImg ? 'true' : 'false', + 'severity': projectPolicy.PreventVulImgServerity, + 'auto_scan': projectPolicy.ScanImgOnPush ? 'true' : 'false' + } }, this.options) + .map(response => response.status) + .catch(error => Observable.throw(error)); + } +} diff --git a/src/ui_ng/package.json b/src/ui_ng/package.json index f607f68910..f8f2b596ac 100644 --- a/src/ui_ng/package.json +++ b/src/ui_ng/package.json @@ -31,7 +31,7 @@ "clarity-icons": "^0.9.8", "clarity-ui": "^0.9.8", "core-js": "^2.4.1", - "harbor-ui": "0.4.85", + "harbor-ui": "0.4.91", "intl": "^1.2.5", "mutationobserver-shim": "^0.3.2", "ngx-cookie": "^1.0.0", diff --git a/src/ui_ng/src/app/app.module.ts b/src/ui_ng/src/app/app.module.ts index 3bca44a375..9b54cb9745 100644 --- a/src/ui_ng/src/app/app.module.ts +++ b/src/ui_ng/src/app/app.module.ts @@ -24,6 +24,7 @@ import { ConfigurationModule } from './config/config.module'; import { TranslateService } from "@ngx-translate/core"; import { AppConfigService } from './app-config.service'; import {SkinableConfig} from "./skinable-config.service"; +import { ProjectConfigComponent } from './project/project-config/project-config.component'; export function initConfig(configService: AppConfigService, skinableService: SkinableConfig) { return () => { @@ -39,6 +40,7 @@ export function getCurrentLanguage(translateService: TranslateService) { @NgModule({ declarations: [ AppComponent, + ProjectConfigComponent, ], imports: [ SharedModule, @@ -49,10 +51,10 @@ export function getCurrentLanguage(translateService: TranslateService) { ], providers: [ AppConfigService, - SkinableConfig, - { - provide: APP_INITIALIZER, - useFactory: initConfig, + SkinableConfig, + { + provide: APP_INITIALIZER, + useFactory: initConfig, deps: [ AppConfigService, SkinableConfig], multi: true }, diff --git a/src/ui_ng/src/app/harbor-routing.module.ts b/src/ui_ng/src/app/harbor-routing.module.ts index 750b2b6e2b..ed9f876ba2 100644 --- a/src/ui_ng/src/app/harbor-routing.module.ts +++ b/src/ui_ng/src/app/harbor-routing.module.ts @@ -31,6 +31,7 @@ import { TagRepositoryComponent } from './repository/tag-repository/tag-reposito import { ReplicationPageComponent } from './replication/replication-page.component'; import { MemberComponent } from './project/member/member.component'; import { AuditLogComponent } from './log/audit-log.component'; +import { ProjectConfigComponent } from './project/project-config/project-config.component' import { ProjectRoutingResolver } from './project/project-routing-resolver.service'; import { SystemAdminGuard } from './shared/route/system-admin-activate.service'; @@ -133,6 +134,10 @@ const harborRoutes: Routes = [ { path: 'logs', component: AuditLogComponent + }, + { + path: 'configs', + component: ProjectConfigComponent } ] }, diff --git a/src/ui_ng/src/app/project/project-config/project-config.component.css b/src/ui_ng/src/app/project/project-config/project-config.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ui_ng/src/app/project/project-config/project-config.component.html b/src/ui_ng/src/app/project/project-config/project-config.component.html new file mode 100644 index 0000000000..22db9c4522 --- /dev/null +++ b/src/ui_ng/src/app/project/project-config/project-config.component.html @@ -0,0 +1,5 @@ +
+
+ +
+
\ No newline at end of file diff --git a/src/ui_ng/src/app/project/project-config/project-config.component.spec.ts b/src/ui_ng/src/app/project/project-config/project-config.component.spec.ts new file mode 100644 index 0000000000..84bc4f4557 --- /dev/null +++ b/src/ui_ng/src/app/project/project-config/project-config.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProjectConfigComponent } from './project-config.component'; + +describe('ProjectConfigPageComponent', () => { + let component: ProjectConfigComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ProjectConfigComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ProjectConfigComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/ui_ng/src/app/project/project-config/project-config.component.ts b/src/ui_ng/src/app/project/project-config/project-config.component.ts new file mode 100644 index 0000000000..a62b220b63 --- /dev/null +++ b/src/ui_ng/src/app/project/project-config/project-config.component.ts @@ -0,0 +1,49 @@ +// Copyright (c) 2017 VMware, Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { SessionService } from '../../shared/session.service'; +import { SessionUser } from '../../shared/session-user'; +import { Project } from '../project'; + +@Component({ + selector: 'app-project-config', + templateUrl: './project-config.component.html', + styleUrls: ['./project-config.component.css'] +}) +export class ProjectConfigComponent implements OnInit { + + projectId: number; + projectName: string; + currentUser: SessionUser; + hasSignedIn: boolean; + hasProjectAdminRole: boolean; + + constructor( + private route: ActivatedRoute, + private router: Router, + private session: SessionService) {} + + ngOnInit() { + this.projectId = +this.route.snapshot.parent.params['id']; + this.currentUser = this.session.getCurrentUser(); + this.hasSignedIn = this.session.getCurrentUser() !== null; + let resolverData = this.route.snapshot.parent.data; + if (resolverData) { + let pro: Project = resolverData['projectResolver']; + this.hasProjectAdminRole = pro.has_project_admin_role; + this.projectName = pro.name; + } + } +} diff --git a/src/ui_ng/src/app/project/project-detail/project-detail.component.html b/src/ui_ng/src/app/project/project-detail/project-detail.component.html index 6f7f3717c1..317f03b8a4 100644 --- a/src/ui_ng/src/app/project/project-detail/project-detail.component.html +++ b/src/ui_ng/src/app/project/project-detail/project-detail.component.html @@ -16,6 +16,9 @@ + \ No newline at end of file diff --git a/src/ui_ng/src/app/project/project-detail/project-detail.component.ts b/src/ui_ng/src/app/project/project-detail/project-detail.component.ts index 2e2bfd03c2..942aedcb03 100644 --- a/src/ui_ng/src/app/project/project-detail/project-detail.component.ts +++ b/src/ui_ng/src/app/project/project-detail/project-detail.component.ts @@ -23,14 +23,14 @@ import { RoleMapping } from '../../shared/shared.const'; @Component({ selector: 'project-detail', - templateUrl: "project-detail.component.html", + templateUrl: 'project-detail.component.html', styleUrls: [ 'project-detail.component.css' ] }) export class ProjectDetailComponent { hasSignedIn: boolean; currentProject: Project; - + isMember: boolean; roleName: string; @@ -41,7 +41,7 @@ export class ProjectDetailComponent { private projectService: ProjectService) { this.hasSignedIn = this.sessionService.getCurrentUser() !== null; - this.route.data.subscribe(data=>{ + this.route.data.subscribe(data => { this.currentProject = data['projectResolver']; this.isMember = this.currentProject.is_member; this.roleName = RoleMapping[this.currentProject.role_name]; diff --git a/src/ui_ng/src/i18n/lang/en-us-lang.json b/src/ui_ng/src/i18n/lang/en-us-lang.json index 9e9a2c6a2f..9089c6c015 100644 --- a/src/ui_ng/src/i18n/lang/en-us-lang.json +++ b/src/ui_ng/src/i18n/lang/en-us-lang.json @@ -161,7 +161,22 @@ "REPLICATION": "Replication", "USERS": "Members", "LOGS": "Logs", - "PROJECTS": "Projects" + "PROJECTS": "Projects", + "CONFIG": "Configuration" + }, + "PROJECT_CONFIG": { + "REGISTRY": "Project registry", + "PUBLIC_TOGGLE": "Public", + "PUBLIC_POLICY": "Making a project registry public will make all repositories accessible to everyone.", + "SECURITY": "Deployment security", + "CONTENT_TRUST_TOGGLE": "Enable content trust", + "CONTENT_TRUST_POLCIY": "Only allow verified images to be deployed.", + "PREVENT_VULNERABLE_TOGGLE": "Prevent vulnerable images from running.", + "PREVENT_VULNERABLE_1": "Prevent images with vulnerability serverity of", + "PREVENT_VULNERABLE_2": "and above from being deployed.", + "SCAN": "Vulnerability scanning", + "AUTOSCAN_TOGGLE": "Automatically scan images on push", + "AUTOSCAN_POLICY": "Automatically scan images when they are pushed to the project registry." }, "MEMBER": { "NEW_MEMBER": "New Member", diff --git a/src/ui_ng/src/i18n/lang/es-es-lang.json b/src/ui_ng/src/i18n/lang/es-es-lang.json index 4dedf8255f..8b1b400782 100644 --- a/src/ui_ng/src/i18n/lang/es-es-lang.json +++ b/src/ui_ng/src/i18n/lang/es-es-lang.json @@ -161,7 +161,22 @@ "REPLICATION": "Replicación", "USERS": "Miembros", "LOGS": "Logs", - "PROJECTS": "Proyectos" + "PROJECTS": "Proyectos", + "CONFIG": "Configuración" + }, + "PROJECT_CONFIG": { + "REGISTRY": "Registro de proyectos", + "PUBLIC_TOGGLE": "Público", + "PUBLIC_POLICY": "Hacer público un registro de proyecto hará que todos los repositorios sean accesibles para todos.", + "SECURITY": "Seguridad de despliegue", + "CONTENT_TRUST_TOGGLE": "Habilitar la confianza de contenido", + "CONTENT_TRUST_POLCIY": "Solo permita la implementación de imágenes verificadas.", + "PREVENT_VULNERABLE_TOGGLE": "Evitar que se ejecuten imágenes vulnerables.", + "PREVENT_VULNERABLE_1": "Impedir imágenes con la gravedad de la vulnerabilidad de", + "PREVENT_VULNERABLE_2": "y más arriba de ser desplegado.", + "SCAN": "Escaneo de vulnerabilidad", + "AUTOSCAN_TOGGLE": "Escanee automáticamente las imágenes al instante", + "AUTOSCAN_POLICY": "Escanee automáticamente las imágenes cuando son enviadas al registro del proyecto." }, "MEMBER": { "NEW_MEMBER": "Nuevo miembro", diff --git a/src/ui_ng/src/i18n/lang/zh-cn-lang.json b/src/ui_ng/src/i18n/lang/zh-cn-lang.json index f99227f06b..af643351b6 100644 --- a/src/ui_ng/src/i18n/lang/zh-cn-lang.json +++ b/src/ui_ng/src/i18n/lang/zh-cn-lang.json @@ -161,7 +161,22 @@ "REPLICATION": "复制", "USERS": "成员", "LOGS": "日志", - "PROJECTS": "项目" + "PROJECTS": "项目", + "CONFIG": "配置管理" + }, + "PROJECT_CONFIG": { + "REGISTRY": "项目仓库", + "PUBLIC_TOGGLE": "公开", + "PUBLIC_POLICY": "此项目的仓库对所有访客公开。", + "SECURITY": "部署安全", + "CONTENT_TRUST_TOGGLE": "内容信任", + "CONTENT_TRUST_POLCIY": "仅允许部署通过认证的镜像。", + "PREVENT_VULNERABLE_TOGGLE": "阻止潜在漏洞镜像", + "PREVENT_VULNERABLE_1": "阻止危害级别", + "PREVENT_VULNERABLE_2": "以上的镜像运行。", + "SCAN": "漏洞扫描", + "AUTOSCAN_TOGGLE": "自动扫描镜像", + "AUTOSCAN_POLICY": "当镜像上传后,自动进行扫描" }, "MEMBER": { "NEW_MEMBER": "新建成员",