Commit ea6fcd2a authored by Deng, Qian's avatar Deng, Qian
Browse files

Fix UAA edit password bug

Fix UAA edit password bug
Fix password edit bug
Remove unused code
Fix some tslint issue
parent db8511bd
{
"name": "harbor-ui",
"version": "0.6.22",
"version": "0.6.24",
"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",
......
{
"name": "harbor-ui",
"version": "0.6.22",
"version": "0.6.24",
"description": "Harbor shared UI components based on Clarity and Angular4",
"author": "VMware",
"module": "index.js",
......
......@@ -65,6 +65,10 @@ export class Configuration {
ldap_uid: StringValueItem;
ldap_url: StringValueItem;
ldap_verify_cert: BoolValueItem;
uaa_client_id: StringValueItem;
uaa_client_secret?: StringValueItem;
uaa_endpoint: StringValueItem;
uaa_verify_cert: BoolValueItem;
email_host: StringValueItem;
email_identity: StringValueItem;
email_from: StringValueItem;
......@@ -91,6 +95,10 @@ export class Configuration {
this.ldap_uid = new StringValueItem("", true);
this.ldap_url = new StringValueItem("", true);
this.ldap_verify_cert = new BoolValueItem(true, true);
this.uaa_client_id = new StringValueItem("", true);
this.uaa_client_secret = new StringValueItem("", true);
this.uaa_endpoint = new StringValueItem("", true);
this.uaa_verify_cert = new BoolValueItem(false, true);
this.email_host = new StringValueItem("", true);
this.email_identity = new StringValueItem("", true);
this.email_from = new StringValueItem("", true);
......
......@@ -9,18 +9,15 @@
"check-space"
],
"curly": true,
"eofline": true,
"forin": true,
"eofline": false,
"forin": false,
"indent": [
true,
"spaces"
],
"label-position": true,
"label-undefined": true,
"max-line-length": [
false,
140
],
"max-line-length": false,
"member-access": false,
"member-ordering": [
true,
......@@ -74,7 +71,8 @@
],
"quotemark": [
true,
"single"
"double",
"avoid-escape"
],
"radix": true,
"semicolon": [
......
......@@ -31,7 +31,7 @@
"clarity-icons": "^0.10.17",
"clarity-ui": "^0.10.17",
"core-js": "^2.4.1",
"harbor-ui": "0.6.23",
"harbor-ui": "0.6.24",
"intl": "^1.2.5",
"mutationobserver-shim": "^0.3.2",
"ngx-cookie": "^1.0.0",
......
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="false">
<h3 class="modal-title">{{'PROFILE.TITLE' | translate}}</h3>
<inline-alert class="modal-title" (confirmEvt)="confirm($event)"></inline-alert>
<inline-alert class="modal-title" (confirmEvt)="confirmYes($event)" (closeEvt)="confirmNo($event)"></inline-alert>
<div class="modal-body" style="overflow-y: hidden;">
<form #accountSettingsFrom="ngForm" class="form">
<section class="form-block">
......
......@@ -240,8 +240,13 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
});
}
confirm($event: any): void {
if(this.RenameOnGoing) {
confirmNo($event: any): void {
if (this.RenameOnGoing) {
this.RenameOnGoing = false;
}
}
confirmYes($event: any): void {
if (this.RenameOnGoing) {
this.confirmRename();
this.RenameOnGoing = false;
}
......
......@@ -165,7 +165,7 @@
<clr-checkbox name="selfReg" id="selfReg" [(ngModel)]="currentConfig.self_registration.value" [disabled]="disabled(currentConfig.self_registration)">
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right" style="top:-7px;">
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
<span *ngIf="checkboxenable; else elseBlock" class="tooltip-content">{{'CONFIG.TOOLTIP.SELF_REGISTRATION_ENABLE' | translate}}</span>
<span *ngIf="checkable; else elseBlock" class="tooltip-content">{{'CONFIG.TOOLTIP.SELF_REGISTRATION_ENABLE' | translate}}</span>
<ng-template #elseBlock><span class="tooltip-content">{{'CONFIG.TOOLTIP.SELF_REGISTRATION_DISABLE' | translate}}</span></ng-template>
</a>
</clr-checkbox>
......
......@@ -19,15 +19,16 @@ import { Configuration } from 'harbor-ui';
@Component({
selector: 'config-auth',
templateUrl: "config-auth.component.html",
templateUrl: 'config-auth.component.html',
styleUrls: ['../config.component.css']
})
export class ConfigurationAuthComponent implements OnChanges {
changeSub: Subscription;
@Input("allConfig") currentConfig: Configuration = new Configuration();
@Input('allConfig') currentConfig: Configuration = new Configuration();
@ViewChild("authConfigFrom") authForm: NgForm;
@ViewChild('authConfigFrom') authForm: NgForm;
constructor() { }
ngOnChanges(): void {
if ( this.currentConfig &&
this.currentConfig.auth_mode &&
......@@ -36,14 +37,12 @@ export class ConfigurationAuthComponent implements OnChanges {
}
}
get checkboxenable(){
get checkable(){
return this.currentConfig &&
this.currentConfig.self_registration &&
this.currentConfig.self_registration.value === true;
}
constructor() { }
public get showLdap(): boolean {
return this.currentConfig &&
this.currentConfig.auth_mode &&
......@@ -62,6 +61,10 @@ export class ConfigurationAuthComponent implements OnChanges {
}
}
public isValid(): boolean {
return this.authForm && this.authForm.valid;
}
setVerifyCertValue($event: any) {
this.currentConfig.ldap_verify_cert.value = $event;
}
......@@ -70,16 +73,12 @@ export class ConfigurationAuthComponent implements OnChanges {
return !(prop && prop.editable);
}
public isValid(): boolean {
return this.authForm && this.authForm.valid;
}
handleOnChange($event: any): void {
if ($event && $event.target && $event.target["value"]) {
let authMode = $event.target["value"];
if (authMode === 'ldap_auth' || authMode === 'uaa_auth') {
if (this.currentConfig.self_registration.value) {
this.currentConfig.self_registration.value = false;//uncheck
this.currentConfig.self_registration.value = false; // uncheck
}
}
}
......
<div class="config-container">
<h2 style="display: inline-block;" class="custom-h2">{{'CONFIG.TITLE' | translate }}</h2>
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
<clr-tabs (clrTabsCurrentTabLinkChanged)="tabLinkChanged($event)">
<clr-tab-link [clrTabLinkId]="'config-auth'" [clrTabLinkActive]='isCurrentTabLink("config-auth")'>{{'CONFIG.AUTH' | translate }}</clr-tab-link>
<clr-tab-link [clrTabLinkId]="'config-replication'" [clrTabLinkActive]='isCurrentTabLink("config-replication")'>{{'CONFIG.REPLICATION' | translate }}</clr-tab-link>
<clr-tab-link [clrTabLinkId]="'config-email'" [clrTabLinkActive]='isCurrentTabLink("config-email")'>{{'CONFIG.EMAIL' | translate }}</clr-tab-link>
<clr-tab-link [clrTabLinkId]="'config-system'" [clrTabLinkActive]='isCurrentTabLink("config-system")'>{{'CONFIG.SYSTEM' | translate }}</clr-tab-link>
<clr-tab-content [clrTabContentId]="'authentication'" [clrTabContentActive]='isCurrentTabContent("authentication")'>
<config-auth [ldapConfig]="allConfig"></config-auth>
</clr-tab-content>
<clr-tab-content [clrTabContentId]="'replication'" [clrTabContentActive]='isCurrentTabContent("replication")'>
<form #repoConfigFrom="ngForm" class="form">
<section class="form-block">
<div class="form-group">
<label for="verifyRemoteCert">{{'CONFIG.VERIFY_REMOTE_CERT' | translate }}</label>
<clr-checkbox name="verifyRemoteCert" id="verifyRemoteCert" [(ngModel)]="allConfig.verify_remote_cert.value" [disabled]="disabled(allConfig.verify_remote_cert)">
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-lg tooltip-top-right" style="top:-8px;">
<clr-icon shape="info-circle" class="is-info" size="24"></clr-icon>
<span class="tooltip-content">{{'CONFIG.TOOLTIP.VERIFY_REMOTE_CERT' | translate }}</span>
</a>
</clr-checkbox>
</div>
</section>
</form>
</clr-tab-content>
<clr-tab-content [clrTabContentId]="'email'" [clrTabContentActive]='isCurrentTabContent("email")'>
<config-email [mailConfig]="allConfig"></config-email>
</clr-tab-content>
<clr-tab-content [clrTabContentId]="'system_settings'" [clrTabContentActive]='isCurrentTabContent("system_settings")'>
<form #systemConfigFrom="ngForm" class="form">
<section class="form-block">
<div class="form-group">
<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" [class.invalid]="tokenExpirationInput.invalid && (tokenExpirationInput.dirty || tokenExpirationInput.touched)">
<input name="tokenExpiration" type="text" #tokenExpirationInput="ngModel" [(ngModel)]="allConfig.token_expiration.value"
required
pattern="^[1-9]{1}[\d]*$"
id="tokenExpiration"
size="40" [disabled]="disabled(allConfig.token_expiration)">
<span class="tooltip-content">
{{'TOOLTIP.NUMBER_REQUIRED' | translate}}
</span>
</label>
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
<clr-icon shape="info-circle" class="is-info" size="24"></clr-icon>
<span class="tooltip-content">{{'CONFIG.TOOLTIP.TOKEN_EXPIRATION' | translate}}</span>
</a>
</div>
</section>
</form>
</clr-tab-content>
</clr-tabs>
<div>
<button type="button" class="btn btn-primary" (click)="save()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.SAVE' | translate}}</button>
<button type="button" class="btn btn-outline" (click)="cancel()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.CANCEL' | translate}}</button>
<button type="button" class="btn btn-outline" (click)="testMailServer()" *ngIf="showTestServerBtn" [disabled]="!isMailConfigValid()">{{'BUTTON.TEST_MAIL' | translate}}</button>
<button type="button" class="btn btn-outline" (click)="testLDAPServer()" *ngIf="showLdapServerBtn" [disabled]="!isLDAPConfigValid()">{{'BUTTON.TEST_LDAP' | translate}}</button>
<span class="spinner spinner-inline" [hidden]="!testingInProgress"></span>
</div>
</div>
\ No newline at end of file
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// 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,
// 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, OnDestroy, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { ConfigurationService } from './config.service';
import { ConfirmationTargets, ConfirmationState } from '../shared/shared.const';;
import { ConfirmationTargets, ConfirmationState } from '../shared/shared.const';
import { ConfirmationDialogService } from '../shared/confirmation-dialog/confirmation-dialog.service';
import { Subscription } from 'rxjs/Subscription';
import { ConfirmationMessage } from '../shared/confirmation-dialog/confirmation-message'
import { ConfirmationMessage } from '../shared/confirmation-dialog/confirmation-message';
import { ConfigurationAuthComponent } from './auth/config-auth.component';
import { ConfigurationEmailComponent } from './email/config-email.component';
......@@ -29,24 +28,22 @@ import { MessageHandlerService } from '../shared/message-handler/message-handler
import {
Configuration,
StringValueItem,
ComplexValueItem,
SystemSettingsComponent,
VulnerabilityConfigComponent,
ClairDBStatus
} from 'harbor-ui';
const fakePass = "aWpLOSYkIzJTTU4wMDkx";
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
const TabLinkContentMap = {
"config-auth": "authentication",
"config-replication": "replication",
"config-email": "email",
"config-system": "system_settings",
"config-vulnerability": "vulnerability"
'config-auth': 'authentication',
'config-replication': 'replication',
'config-email': 'email',
'config-system': 'system_settings',
'config-vulnerability': 'vulnerability'
};
@Component({
selector: 'config',
templateUrl: "config.component.html",
templateUrl: 'config.component.html',
styleUrls: ['config.component.css']
})
export class ConfigurationComponent implements OnInit, OnDestroy {
......@@ -99,36 +96,36 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
let properties = [];
switch (this.currentTabId) {
case "config-auth":
case 'config-auth':
for (let prop in allChanges) {
if (prop.startsWith("ldap_")) {
if (prop.startsWith('ldap_')) {
return allChanges;
}
}
properties = ["auth_mode", "project_creation_restriction", "self_registration"];
properties = ['auth_mode', 'project_creation_restriction', 'self_registration'];
break;
case "config-email":
case 'config-email':
for (let prop in allChanges) {
if (prop.startsWith("email_")) {
if (prop.startsWith('email_')) {
return allChanges;
}
}
return null;
case "config-replication":
properties = ["verify_remote_cert"];
case 'config-replication':
properties = ['verify_remote_cert'];
break;
case "config-system":
properties = ["token_expiration"];
case 'config-system':
properties = ['token_expiration'];
break;
case "config-vulnerability":
properties = ["scan_all_policy"];
case 'config-vulnerability':
properties = ['scan_all_policy'];
break;
default:
return null;
}
for (let prop in allChanges) {
if (properties.indexOf(prop) != -1) {
if (properties.indexOf(prop) !== -1) {
return allChanges;
}
}
......@@ -137,8 +134,8 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
}
ngOnInit(): void {
//First load
//Double confirm the current use has admin role
// First load
// Double confirm the current use has admin role
let currentUser = this.session.getCurrentUser();
if (currentUser && currentUser.has_admin_role > 0) {
this.retrieveConfig();
......@@ -150,8 +147,8 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
if (confirmation.source === ConfirmationTargets.CONFIG) {
this.reset(confirmation.data);
} else if (confirmation.source === ConfirmationTargets.CONFIG_TAB) {
this.reset(confirmation.data["changes"]);
this.currentTabId = confirmation.data["tabId"];
this.reset(confirmation.data['changes']);
this.currentTabId = confirmation.data['tabId'];
}
}
});
......@@ -200,7 +197,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
public get showLdapServerBtn(): boolean {
return this.currentTabId === 'config-auth' &&
this.allConfig.auth_mode &&
this.allConfig.auth_mode.value === "ldap_auth";
this.allConfig.auth_mode.value === 'ldap_auth';
}
public get hideMailTestingSpinner(): boolean {
......@@ -218,7 +215,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
}
public tabLinkClick(tabLink: string) {
//Whether has unsaved changes in current tab
// Whether has unsaved changes in current tab
let changes = this.hasUnsavedChangesOfCurrentTab();
if (!changes) {
this.currentTabId = tabLink;
......@@ -229,18 +226,18 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
}
/**
*
*
* Save the changed values
*
*
* @memberOf ConfigurationComponent
*/
public save(): void {
let changes = this.getChanges();
if (!this.isEmpty(changes)) {
//Fix policy parameters issue
let scanningAllPolicy = changes["scan_all_policy"];
// Fix policy parameters issue
let scanningAllPolicy = changes['scan_all_policy'];
if (scanningAllPolicy &&
scanningAllPolicy.type !== "daily" &&
scanningAllPolicy.type !== 'daily' &&
scanningAllPolicy.parameters) {
delete (scanningAllPolicy.parameters);
}
......@@ -249,32 +246,32 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
this.configService.saveConfiguration(changes)
.then(response => {
this.onGoing = false;
//API should return the updated configurations here
//Unfortunately API does not do that
//To refresh the view, we can clone the original data copy
//or force refresh by calling service.
//HERE we choose force way
// API should return the updated configurations here
// Unfortunately API does not do that
// To refresh the view, we can clone the original data copy
// or force refresh by calling service.
// HERE we choose force way
this.retrieveConfig();
//Reload bootstrap option
this.appConfigService.load().catch(error => console.error("Failed to reload bootstrap option with error: ", error));
// Reload bootstrap option
this.appConfigService.load().catch(error => console.error('Failed to reload bootstrap option with error: ', error));
this.msgHandler.showSuccess("CONFIG.SAVE_SUCCESS");
this.msgHandler.showSuccess('CONFIG.SAVE_SUCCESS');
})
.catch(error => {
this.onGoing = false;
this.msgHandler.handleError(error);
});
} else {
//Inprop situation, should not come here
console.error("Save obort becasue nothing changed");
// Inprop situation, should not come here
console.error('Save obort becasue nothing changed');
}
}
/**
*
*
* Discard current changes if have and reset
*
*
* @memberOf ConfigurationComponent
*/
public cancel(): void {
......@@ -282,98 +279,98 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
if (!this.isEmpty(changes)) {
this.confirmUnsavedChanges(changes);
} else {
//Invalid situation, should not come here
console.error("Nothing changed");
// Invalid situation, should not come here
console.error('Nothing changed');
}
}
/**
*
*
* Test the connection of specified mail server
*
*
*
*
* @memberOf ConfigurationComponent
*/
public testMailServer(): void {
if (this.testingMailOnGoing) {
return;//Should not come here
return; // Should not come here
}
let mailSettings = {};
for (let prop in this.allConfig) {
if (prop.startsWith("email_")) {
if (prop.startsWith('email_')) {
mailSettings[prop] = this.allConfig[prop].value;
}
}
//Confirm port is number
mailSettings["email_port"] = +mailSettings["email_port"];
// Confirm port is number
mailSettings['email_port'] = +mailSettings['email_port'];
let allChanges = this.getChanges();
let password = allChanges["email_password"]
let password = allChanges['email_password'];
if (password) {
mailSettings["email_password"] = password;
mailSettings['email_password'] = password;
} else {
delete mailSettings["email_password"];
delete mailSettings['email_password'];
}
this.testingMailOnGoing = true;
this.configService.testMailServer(mailSettings)
.then(response => {
this.testingMailOnGoing = false;
this.msgHandler.showSuccess("CONFIG.TEST_MAIL_SUCCESS");
this.msgHandler.showSuccess('CONFIG.TEST_MAIL_SUCCESS');
})
.catch(error => {
this.testingMailOnGoing = false;
let err = error._body;
if (!err) {
err = "UNKNOWN";
err = 'UNKNOWN';
}
this.msgHandler.showError("CONFIG.TEST_MAIL_FAILED", { 'param': err });
this.msgHandler.showError('CONFIG.TEST_MAIL_FAILED', { 'param': err });
});
}
public testLDAPServer(): void {
if (this.testingLDAPOnGoing) {
return;//Should not come here
return; // Should not come here
}
let ldapSettings = {};
for (let prop in this.allConfig) {
if (prop.startsWith("ldap_")) {
if (prop.startsWith('ldap_')) {
ldapSettings[prop] = this.allConfig[prop].value;
}
}
let allChanges = this.getChanges();
let ldapSearchPwd = allChanges["ldap_search_password"];
let ldapSearchPwd = allChanges['ldap_search_password'];
if (ldapSearchPwd) {
ldapSettings['ldap_search_password'] = ldapSearchPwd;
} else {
delete ldapSettings['ldap_search_password'];
}
//Fix: Confirm ldap scope is number
// Fix: Confirm ldap scope is number
ldapSettings['ldap_scope'] = +ldapSettings['ldap_scope'];
this.testingLDAPOnGoing = true;
this.configService.testLDAPServer(ldapSettings)
.then(respone => {
this.testingLDAPOnGoing = false;
this.msgHandler.showSuccess("CONFIG.TEST_LDAP_SUCCESS");
this.msgHandler.showSuccess('CONFIG.TEST_LDAP_SUCCESS');
})
.catch(error => {
this.testingLDAPOnGoing = false;
let err = error._body;
if (!err) {
err = "UNKNOWN";
err = 'UNKNOWN';
}
this.msgHandler.showError("CONFIG.TEST_LDAP_FAILED", { 'param': err });
this.msgHandler.showError('CONFIG.TEST_LDAP_FAILED', { 'param': err });
});
}
confirmUnsavedChanges(changes: any) {
let msg = new ConfirmationMessage(
"CONFIG.CONFIRM_TITLE",
"CONFIG.CONFIRM_SUMMARY",
"",
'CONFIG.CONFIRM_TITLE',
'CONFIG.CONFIRM_SUMMARY',
'',
changes,
ConfirmationTargets.CONFIG
);
......@@ -383,12 +380,12 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
confirmUnsavedTabChanges(changes: any, tabId: string) {
let msg = new ConfirmationMessage(
"CONFIG.CONFIRM_TITLE",