support 'remember me' and root cert downloading

This commit is contained in:
Steven Zou 2017-03-27 15:58:00 +08:00
parent 5c4e17638f
commit 5fb2605a45
8 changed files with 64 additions and 5 deletions

3
.gitignore vendored
View File

@ -24,5 +24,8 @@ src/ui_ng/typings/
**/*yarn-error.log.* **/*yarn-error.log.*
.idea/ .idea/
.DS_Store .DS_Store
**/node_modules
**/ssl/
**/proxy.config.json

View File

@ -23,7 +23,7 @@
</span> </span>
</label> </label>
<div class="checkbox"> <div class="checkbox">
<input type="checkbox" id="rememberme"> <input type="checkbox" id="rememberme" #rememberMeBox (click)="clickRememberMe($event)" [checked]="rememberMe">
<label for="rememberme">{{ 'SIGN_IN.REMEMBER' | translate }}</label> <label for="rememberme">{{ 'SIGN_IN.REMEMBER' | translate }}</label>
<a href="javascript:void(0)" class="forgot-password-link" (click)="forgotPassword()">{{'SIGN_IN.FORGOT_PWD' | translate}}</a> <a href="javascript:void(0)" class="forgot-password-link" (click)="forgotPassword()">{{'SIGN_IN.FORGOT_PWD' | translate}}</a>
</div> </div>

View File

@ -14,10 +14,14 @@ import { AppConfigService } from '../../app-config.service';
import { AppConfig } from '../../app-config'; import { AppConfig } from '../../app-config';
import { User } from '../../user/user'; import { User } from '../../user/user';
import { CookieService, CookieOptions } from 'angular2-cookie/core';
//Define status flags for signing in states //Define status flags for signing in states
export const signInStatusNormal = 0; export const signInStatusNormal = 0;
export const signInStatusOnGoing = 1; export const signInStatusOnGoing = 1;
export const signInStatusError = -1; export const signInStatusError = -1;
const remCookieKey = "rem-username";
const expireDays = 10;
@Component({ @Component({
selector: 'sign-in', selector: 'sign-in',
@ -28,6 +32,9 @@ export const signInStatusError = -1;
export class SignInComponent implements AfterViewChecked, OnInit { export class SignInComponent implements AfterViewChecked, OnInit {
private redirectUrl: string = ""; private redirectUrl: string = "";
private appConfig: AppConfig = new AppConfig(); private appConfig: AppConfig = new AppConfig();
//Remeber me indicator
private rememberMe: boolean = false;
private rememberedName: string = "";
//Form reference //Form reference
signInForm: NgForm; signInForm: NgForm;
@ViewChild('signInForm') currentForm: NgForm; @ViewChild('signInForm') currentForm: NgForm;
@ -47,13 +54,14 @@ export class SignInComponent implements AfterViewChecked, OnInit {
private router: Router, private router: Router,
private session: SessionService, private session: SessionService,
private route: ActivatedRoute, private route: ActivatedRoute,
private appConfigService: AppConfigService private appConfigService: AppConfigService,
private cookie: CookieService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
//Make sure the updated configuration can be loaded //Make sure the updated configuration can be loaded
this.appConfigService.load() this.appConfigService.load()
.then(updatedConfig => this.appConfig = updatedConfig); .then(updatedConfig => this.appConfig = updatedConfig);
this.route.queryParams this.route.queryParams
.subscribe(params => { .subscribe(params => {
this.redirectUrl = params["redirect_url"] || ""; this.redirectUrl = params["redirect_url"] || "";
@ -62,6 +70,14 @@ export class SignInComponent implements AfterViewChecked, OnInit {
this.signUp();//Open sign up this.signUp();//Open sign up
} }
}); });
let remUsername = this.cookie.get(remCookieKey);
remUsername = remUsername ? remUsername.trim() : "";
if (remUsername) {
this.signInCredential.principal = remUsername;
this.rememberMe = true;
this.rememberedName = remUsername;
}
} }
//For template accessing //For template accessing
@ -84,6 +100,31 @@ export class SignInComponent implements AfterViewChecked, OnInit {
&& this.appConfig.self_registration; && this.appConfig.self_registration;
} }
private clickRememberMe($event): void {
if ($event && $event.target) {
this.rememberMe = $event.target.checked;
if (!this.rememberMe) {
//Remove cookie data
this.cookie.remove(remCookieKey);
this.rememberedName = "";
}
}
}
private remeberMe(): void {
if (this.rememberMe) {
if (this.rememberedName != this.signInCredential.principal) {
//Set expire time
let expires: number = expireDays * 3600 * 24 * 1000;
let date = new Date(Date.now() + expires);
let cookieptions = new CookieOptions({
expires: date
});
this.cookie.put(remCookieKey, this.signInCredential.principal, cookieptions);
}
}
}
//General error handler //General error handler
private handleError(error) { private handleError(error) {
//Set error status //Set error status
@ -150,6 +191,9 @@ export class SignInComponent implements AfterViewChecked, OnInit {
//Set status //Set status
this.signInStatus = signInStatusNormal; this.signInStatus = signInStatusNormal;
//Remeber me
this.remeberMe();
//Redirect to the right route //Redirect to the right route
if (this.redirectUrl === "") { if (this.redirectUrl === "") {
//Routing to the default location //Routing to the default location

View File

@ -8,6 +8,7 @@ export class AppConfig {
this.registry_url = ""; this.registry_url = "";
this.project_creation_restriction = "everyone"; this.project_creation_restriction = "everyone";
this.self_registration = true; this.self_registration = true;
this.has_ca_root = false;
} }
with_notary: boolean; with_notary: boolean;
@ -17,4 +18,5 @@ export class AppConfig {
registry_url: string; registry_url: string;
project_creation_restriction: string; project_creation_restriction: string;
self_registration: boolean; self_registration: boolean;
has_ca_root: boolean;
} }

View File

@ -31,6 +31,7 @@
<div class="dropdown-menu"> <div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem (click)="openAccountSettingsModal()">{{'ACCOUNT_SETTINGS.PROFILE' | translate}}</a> <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 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> <a href="javascript:void(0)" clrDropdownItem (click)="openAboutDialog()">{{'ACCOUNT_SETTINGS.ABOUT' | translate}}</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="javascript:void(0)" clrDropdownItem (click)="logOut()">{{'ACCOUNT_SETTINGS.LOGOUT' | translate}}</a> <a href="javascript:void(0)" clrDropdownItem (click)="logOut()">{{'ACCOUNT_SETTINGS.LOGOUT' | translate}}</a>

View File

@ -70,6 +70,13 @@ export class NavigatorComponent implements OnInit {
return this.appConfigService.isIntegrationMode(); return this.appConfigService.isIntegrationMode();
} }
public get canDownloadCert(): boolean {
return this.session.getCurrentUser() &&
this.session.getCurrentUser().has_admin_role>0 &&
this.appConfigService.getConfig() &&
this.appConfigService.getConfig().has_ca_root;
}
matchLang(lang: string): boolean { matchLang(lang: string): boolean {
return lang.trim() === this.selectedLang; return lang.trim() === this.selectedLang;
} }

View File

@ -81,7 +81,8 @@
"PROFILE": "User Profile", "PROFILE": "User Profile",
"CHANGE_PWD": "Change Password", "CHANGE_PWD": "Change Password",
"ABOUT": "About", "ABOUT": "About",
"LOGOUT": "Log Out" "LOGOUT": "Log Out",
"ROOT_CERT": "Download Root Cert"
}, },
"GLOBAL_SEARCH": { "GLOBAL_SEARCH": {
"PLACEHOLDER": "Search Harbor..." "PLACEHOLDER": "Search Harbor..."

View File

@ -81,7 +81,8 @@
"PROFILE": "用户设置", "PROFILE": "用户设置",
"CHANGE_PWD": "修改密码", "CHANGE_PWD": "修改密码",
"ABOUT": "关于", "ABOUT": "关于",
"LOGOUT": "退出" "LOGOUT": "退出",
"ROOT_CERT": "下载根证书"
}, },
"GLOBAL_SEARCH": { "GLOBAL_SEARCH": {
"PLACEHOLDER": "搜索 Harbor..." "PLACEHOLDER": "搜索 Harbor..."