Merge pull request #1846 from steven-zou/dev

Fix issues
This commit is contained in:
kun wang 2017-03-29 11:29:56 +08:00 committed by GitHub
commit 8260f204a0
22 changed files with 156 additions and 71 deletions

View File

@ -141,6 +141,18 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
this.account = Object.assign({}, this.session.getCurrentUser());
this.formValueChanged = false;
//Confirm inline alert is closed
this.inlineAlert.close();
//Clear check history
this.mailAlreadyChecked = {};
//Reset validation status
this.validationStateMap = {
"account_settings_email": true,
"account_settings_full_name": true
};
this.opened = true;
}

View File

@ -1,4 +1,4 @@
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true">
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true" [clrModalClosable]="false">
<h3 class="modal-title">{{'RESET_PWD.TITLE' | translate}}</h3>
<label class="modal-title reset-modal-title-override">{{'RESET_PWD.CAPTION' | translate}}</label>
<inline-alert class="modal-title"></inline-alert>

View File

@ -32,10 +32,15 @@ export class ForgotPasswordComponent {
}
public open(): void {
this.opened = true;
//Clear state data
this.validationState = true;
this.forceValid = true;
this.onGoing = false;
this.email = "";
this.forgotPwdForm.resetForm();
this.inlineAlert.close();
this.opened = true;
}
public close(): void {

View File

@ -93,9 +93,18 @@ export class PasswordSettingComponent implements AfterViewChecked {
//Open modal dialog
open(): void {
this.opened = true;
this.pwdForm.reset();
//Reset state
this.formValueChanged = false;
this.onCalling = false;
this.error = null;
this.validationStateMap = {
"newPassword": true,
"reNewPassword": true
};
this.pwdForm.reset();
this.inlineAlert.close();
this.opened = true;
}
//Close the moal dialog

View File

@ -1,4 +1,4 @@
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true">
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true" [clrModalClosable]="false">
<h3 class="modal-title">{{'RESET_PWD.TITLE' | translate}}</h3>
<label class="modal-title reset-modal-title-override">{{'RESET_PWD.CAPTION2' | translate}}</label>
<div class="modal-body" style="overflow-y: hidden;">

View File

@ -15,7 +15,10 @@ export class ResetPasswordComponent implements OnInit {
opened: boolean = true;
private onGoing: boolean = false;
private password: string = "";
private validationState: any = {};
private validationState: any = {
"newPassword": true,
"reNewPassword": true
};
private resetUuid: string = "";
private resetOk: boolean = false;
@ -49,8 +52,15 @@ export class ResetPasswordComponent implements OnInit {
public open(): void {
this.resetOk = false;
this.opened = true;
this.onGoing = false;
this.validationState = {
"newPassword": true,
"reNewPassword": true
};
this.resetPwdForm.resetForm();
this.inlineAlert.close();
this.opened = true;
}
public close(): void {

View File

@ -153,8 +153,7 @@ export class SignInComponent implements AfterViewChecked, OnInit {
private handleUserCreation(user: User): void {
if (user) {
this.currentForm.setValue({
"login_username": user.username,
"login_password": user.password
"login_username": user.username
});
}

View File

@ -59,8 +59,13 @@ export class SignUpComponent {
}
open(): void {
this.newUserForm.reset();//Reset form
//Reset state
this.newUserForm.reset();
this.formValueChanged = false;
this.error = null;
this.onGoing = false;
this.inlienAlert.close();
this.modal.open();
}

View File

@ -30,7 +30,7 @@
</button>
<div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem (click)="openAccountSettingsModal()">{{'ACCOUNT_SETTINGS.PROFILE' | translate}}</a>
<a href="javascript:void(0)" clrDropdownItem (click)="openChangePwdModal()">{{'ACCOUNT_SETTINGS.CHANGE_PWD' | translate}}</a>
<a *ngIf="canChangePassword" href="javascript:void(0)" clrDropdownItem (click)="openChangePwdModal()">{{'ACCOUNT_SETTINGS.CHANGE_PWD' | translate}}</a>
<a *ngIf="canDownloadCert" href="/api/systeminfo/getcert" clrDropdownItem target="_blank">{{'ACCOUNT_SETTINGS.ROOT_CERT' | translate}}</a>
<a href="javascript:void(0)" clrDropdownItem (click)="openAboutDialog()">{{'ACCOUNT_SETTINGS.ABOUT' | translate}}</a>
<div class="dropdown-divider"></div>

View File

@ -76,6 +76,12 @@ export class NavigatorComponent implements OnInit {
this.appConfigService.getConfig().has_ca_root;
}
public get canChangePassword(): boolean {
return this.session.getCurrentUser() &&
this.appConfigService.getConfig() &&
this.appConfigService.getConfig().auth_mode != 'ldap_auth';
}
matchLang(lang: string): boolean {
return lang.trim() === this.selectedLang;
}

View File

@ -13,4 +13,5 @@
font-size: 10px;
font-weight: 400;
line-height: 12px;
left: 170px;
}

View File

@ -3,7 +3,7 @@
<div class="form-group">
<label for="authMode">{{'CONFIG.AUTH_MODE' | translate }}</label>
<div class="select">
<select id="authMode" name="authMode" [disabled]="disabled(currentConfig.auth_mode)" [(ngModel)]="currentConfig.auth_mode.value">
<select id="authMode" name="authMode" (change)="handleOnChange($event)" [disabled]="disabled(currentConfig.auth_mode)" [(ngModel)]="currentConfig.auth_mode.value">
<option value="db_auth">{{'CONFIG.AUTH_MODE_DB' | translate }}</option>
<option value="ldap_auth">{{'CONFIG.AUTH_MODE_LDAP' | translate }}</option>
</select>
@ -128,7 +128,7 @@
<span class="tooltip-content">{{'CONFIG.TOOLTIP.PRO_CREATION_RESTRICTION' | translate}}</span>
</a>
</div>
<div class="form-group">
<div class="form-group" *ngIf="showSelfReg">
<label for="selfReg">{{'CONFIG.SELF_REGISTRATION' | translate}}</label>
<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:-8px;">

View File

@ -1,6 +1,6 @@
import { Component, Input, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Subscription } from 'rxjs/Subscription';
import { Subscription } from 'rxjs/Subscription';
import { Configuration } from '../config';
@ -23,6 +23,14 @@ export class ConfigurationAuthComponent {
this.currentConfig.auth_mode.value === 'ldap_auth';
}
public get showSelfReg(): boolean {
if (!this.currentConfig || !this.currentConfig.auth_mode) {
return true;
} else {
return this.currentConfig.auth_mode.value != 'ldap_auth';
}
}
private disabled(prop: any): boolean {
return !(prop && prop.editable);
}
@ -30,4 +38,15 @@ export class ConfigurationAuthComponent {
public isValid(): boolean {
return this.authForm && this.authForm.valid;
}
private handleOnChange($event): void {
if ($event && $event.target && $event.target["value"]) {
let authMode = $event.target["value"];
if (authMode === 'ldap_auth') {
if (this.currentConfig.self_registration.value) {
this.currentConfig.self_registration.value = false;//uncheck
}
}
}
}
}

View File

@ -280,14 +280,13 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
}
let allChanges = this.getChanges();
for (let prop in allChanges) {
if (prop.startsWith("ldap_")) {
ldapSettings[prop] = allChanges[prop];
}
let ldapSearchPwd = allChanges["ldap_search_password"];
if(ldapSearchPwd){
ldapSettings['ldap_search_password'] = ldapSearchPwd;
}else{
delete ldapSettings['ldap_search_password'];
}
console.info(ldapSettings);
this.testingOnGoing = true;
this.configService.testLDAPServer(ldapSettings)
.then(respone => {
@ -300,7 +299,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
if(!err){
err = "UNKNOWN";
}
this.msgHandler.showError("CONFIG.TEST_LDAP_FAILED", err);
this.msgHandler.showError("CONFIG.TEST_LDAP_FAILED", {'param': err});
});
}

View File

@ -96,6 +96,7 @@ export class RecentLogComponent implements OnInit {
let reg = new RegExp('.*' + terms + '.*', 'i');
return reg.test(log.username) ||
reg.test(log.repo_name) ||
reg.test(log.operation);
reg.test(log.operation) ||
reg.test(log.repo_tag);
}
}

View File

@ -21,7 +21,6 @@ import { SessionService } from '../../shared/session.service';
export class NewUserFormComponent implements AfterViewChecked, OnInit {
newUser: User = new User();
confirmedPwd: string = "";
@Input() isSelfRegistration: boolean = false;
newUserFormRef: NgForm;
@ -33,17 +32,10 @@ export class NewUserFormComponent implements AfterViewChecked, OnInit {
constructor(private session: SessionService) { }
ngOnInit() {
this.formValueChanged = false;
this.resetState();
}
private validationStateMap: any = {
"username": true,
"email": true,
"realname": true,
"newPassword": true,
"confirmPassword": true,
"comment": true
};
private validationStateMap: any = {};
private mailAlreadyChecked: any = {};
private userNameAlreadyChecked: any = {};
@ -51,10 +43,27 @@ export class NewUserFormComponent implements AfterViewChecked, OnInit {
private usernameTooltip: string = 'TOOLTIP.USER_NAME';
private formValueChanged: boolean = false;
private checkOnGoing: any = {
"username": false,
"email": false
};
private checkOnGoing: any = {};
private resetState(): void {
this.mailAlreadyChecked = {};
this.userNameAlreadyChecked = {};
this.emailTooltip = 'TOOLTIP.EMAIL';
this.usernameTooltip = 'TOOLTIP.USER_NAME';
this.formValueChanged = false;
this.checkOnGoing = {
"username": false,
"email": false
};
this.validationStateMap = {
"username": true,
"email": true,
"realname": true,
"newPassword": true,
"confirmPassword": true,
"comment": true
};
}
public isChecking(key: string): boolean {
return !this.checkOnGoing[key];
@ -161,7 +170,7 @@ export class NewUserFormComponent implements AfterViewChecked, OnInit {
pwdEqualStatus = this.newUserForm.controls["confirmPassword"].value === this.newUserForm.controls["newPassword"].value;
}
return this.newUserForm &&
this.newUserForm.valid &&
this.newUserForm.valid &&
pwdEqualStatus &&
this.validationStateMap["username"] &&
this.validationStateMap["email"];//Backend check should be valid as well
@ -186,6 +195,7 @@ export class NewUserFormComponent implements AfterViewChecked, OnInit {
//Reset form
reset(): void {
this.resetState();
if (this.newUserForm) {
this.newUserForm.reset();
}

View File

@ -11,6 +11,7 @@ import { CommonRoutes, AdmiralQueryParamKey } from '../../shared/shared.const';
import { AppConfigService } from '../../app-config.service';
import { maintainUrlQueryParmas } from '../../shared/shared.utils';
import { MessageHandlerService } from '../message-handler/message-handler.service';
import { SearchTriggerService } from '../../base/global-search/search-trigger.service';
@Injectable()
export class AuthCheckGuard implements CanActivate, CanActivateChild {
@ -18,7 +19,8 @@ export class AuthCheckGuard implements CanActivate, CanActivateChild {
private authService: SessionService,
private router: Router,
private appConfigService: AppConfigService,
private msgHandler: MessageHandlerService) { }
private msgHandler: MessageHandlerService,
private searchTrigger: SearchTriggerService) { }
private isGuest(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
const proRegExp = /\/harbor\/projects\/[\d]+\/.+/i;
@ -33,6 +35,7 @@ export class AuthCheckGuard implements CanActivate, CanActivateChild {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> | boolean {
//When routing change, clear
this.msgHandler.clear();
this.searchTrigger.closeSearch(true);
return new Promise((resolve, reject) => {
//Before activating, we firstly need to confirm whether the route is coming from peer part - admiral

View File

@ -16,7 +16,7 @@ export class SignInGuard implements CanActivate, CanActivateChild {
//If user has logged in, should not login again
return new Promise((resolve, reject) => {
let user = this.authService.getCurrentUser();
if (!user) {
if (user === null) {
this.authService.retrieveUser()
.then(() => {
this.router.navigate([CommonRoutes.HARBOR_DEFAULT]);

View File

@ -55,6 +55,10 @@ export class NewUserModalComponent {
open(): void {
this.newUserForm.reset();//Reset form
this.formValueChanged = false;
this.onGoing = false;
this.error = null;
this.inlineAlert.close();
this.opened = true;
}

View File

@ -1,37 +1,37 @@
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h2 class="custom-h2">{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}</h2>
<div class="action-panel-pos">
<span>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h2 class="custom-h2">{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}</h2>
<div class="action-panel-pos">
<span>
<button *ngIf="canCreateUser" type="submit" class="btn btn-primary custom-add-button" (click)="addNewUser()"><clr-icon shape="add"></clr-icon> {{'USER.ADD_ACTION' | translate}}</button>
</span>
<grid-filter class="filter-pos" filterPlaceholder='{{"USER.FILTER_PLACEHOLDER" | translate}}' (filter)="doFilter($event)"></grid-filter>
<span class="refresh-btn" (click)="refreshUser()">
<grid-filter class="filter-pos" filterPlaceholder='{{"USER.FILTER_PLACEHOLDER" | translate}}' (filter)="doFilter($event)"></grid-filter>
<span class="refresh-btn" (click)="refreshUser()">
<clr-icon shape="refresh" [hidden]="inProgress" ng-disabled="inProgress"></clr-icon>
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
</span>
</span>
</div>
<div>
<clr-datagrid>
<clr-dg-column>{{'USER.COLUMN_NAME' | translate}}</clr-dg-column>
<clr-dg-column>{{'USER.COLUMN_ADMIN' | translate}}</clr-dg-column>
<clr-dg-column>{{'USER.COLUMN_EMAIL' | translate}}</clr-dg-column>
<clr-dg-column>{{'USER.COLUMN_REG_NAME' | translate}}</clr-dg-column>
<clr-dg-row *ngFor="let user of users" [clrDgItem]="user">
<clr-dg-action-overflow [hidden]="isMySelf(user.user_id)">
<button class="action-item" (click)="changeAdminRole(user)">{{adminActions(user)}}</button>
<button class="action-item" (click)="deleteUser(user)">{{'USER.DEL_ACTION' | translate}}</button>
</clr-dg-action-overflow>
<clr-dg-cell>{{user.username}}</clr-dg-cell>
<clr-dg-cell>{{isSystemAdmin(user)}}</clr-dg-cell>
<clr-dg-cell>{{user.email}}</clr-dg-cell>
<clr-dg-cell>
{{user.creation_time}}
</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{users.length}} {{'USER.ITEMS' | translate}}</clr-dg-footer>
</clr-datagrid>
</div>
<new-user-modal (addNew)="addUserToList($event)"></new-user-modal>
</div>
<div>
<clr-datagrid>
<clr-dg-column>{{'USER.COLUMN_NAME' | translate}}</clr-dg-column>
<clr-dg-column>{{'USER.COLUMN_ADMIN' | translate}}</clr-dg-column>
<clr-dg-column>{{'USER.COLUMN_EMAIL' | translate}}</clr-dg-column>
<clr-dg-column>{{'USER.COLUMN_REG_NAME' | translate}}</clr-dg-column>
<clr-dg-row *ngFor="let user of users" [clrDgItem]="user">
<clr-dg-action-overflow [hidden]="isMySelf(user.user_id)">
<button class="action-item" (click)="changeAdminRole(user)">{{adminActions(user)}}</button>
<button class="action-item" (click)="deleteUser(user)">{{'USER.DEL_ACTION' | translate}}</button>
</clr-dg-action-overflow>
<clr-dg-cell>{{user.username}}</clr-dg-cell>
<clr-dg-cell>{{isSystemAdmin(user)}}</clr-dg-cell>
<clr-dg-cell>{{user.email}}</clr-dg-cell>
<clr-dg-cell>
{{user.creation_time}}
</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{users.length}} {{'USER.ADD_ACTION' | translate}}</clr-dg-footer>
</clr-datagrid>
</div>
<new-user-modal (addNew)="addUserToList($event)"></new-user-modal>
</div>
</div>

View File

@ -114,7 +114,8 @@
"SAVE_SUCCESS": "New user added successfully",
"DELETION_TITLE": "Confirm user deletion",
"DELETION_SUMMARY": "Do you want to delete user {{param}}?",
"DELETE_SUCCESS": "User deleted successfully"
"DELETE_SUCCESS": "User deleted successfully",
"ITEMS": "item(s)"
},
"PROJECT": {
"PROJECTS": "Projects",

View File

@ -114,7 +114,8 @@
"SAVE_SUCCESS": "添加用户成功",
"DELETION_TITLE": "删除用户确认",
"DELETION_SUMMARY": "你确认删除用户 {{param}}?",
"DELETE_SUCCESS": "删除用户成功"
"DELETE_SUCCESS": "删除用户成功",
"ITEMS": "条记录"
},
"PROJECT": {
"PROJECTS": "项目",