harbor/src/portal/src/app/account/sign-in/sign-in.component.ts

319 lines
10 KiB
TypeScript
Raw Normal View History

// Copyright Project Harbor Authors
2017-04-14 04:06:23 +02:00
//
// 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 {
AfterViewChecked,
Component,
Input,
OnInit,
ViewChild,
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
2017-02-21 07:54:42 +01:00
import { NgForm } from '@angular/forms';
import { SessionService } from '../../shared/services/session.service';
import { SignUpComponent } from '../sign-up/sign-up.component';
import { ForgotPasswordComponent } from '../../base/password-setting/forgot-password/forgot-password.component';
import { AppConfigService } from '../../services/app-config.service';
import { AppConfig } from '../../services/app-config';
import { User } from '../../base/left-side-nav/user/user';
import { CookieOptions, CookieService } from 'ngx-cookie';
import { SkinableConfig } from '../../services/skinable-config.service';
import { ModalEvent } from '../../base/modal-event';
import { modalEvents } from '../../base/modal-events.const';
import { AboutDialogComponent } from '../../shared/components/about-dialog/about-dialog.component';
import {
CommonRoutes,
CONFIG_AUTH_MODE,
} from '../../shared/entities/shared.const';
import { SignInCredential } from './sign-in-credential';
import { UserPermissionService } from '../../shared/services';
import { finalize } from 'rxjs/operators';
// Define status flags for signing in states
2017-02-21 07:54:42 +01:00
export const signInStatusNormal = 0;
export const signInStatusOnGoing = 1;
export const signInStatusError = -1;
const remCookieKey = 'rem-username';
const expireDays = 10;
2017-02-21 07:54:42 +01:00
@Component({
selector: 'sign-in',
templateUrl: 'sign-in.component.html',
styleUrls: ['sign-in.component.scss'],
2017-02-21 07:54:42 +01:00
})
2017-03-07 10:20:33 +01:00
export class SignInComponent implements AfterViewChecked, OnInit {
showPwd: boolean = false;
redirectUrl: string = '';
// Remeber me indicator
2017-04-20 17:47:06 +02:00
rememberMe: boolean = false;
rememberedName: string = '';
2017-10-16 04:54:38 +02:00
customLoginBgImg: string;
2017-11-16 07:55:44 +01:00
customAppTitle: string;
// Form reference
2017-02-21 07:54:42 +01:00
signInForm: NgForm;
@ViewChild('signInForm', { static: true }) currentForm: NgForm;
@ViewChild('signupDialog') signUpDialog: SignUpComponent;
@ViewChild('forgotPwdDialog') forgotPwdDialog: ForgotPasswordComponent;
@ViewChild(AboutDialogComponent) aboutDialog: AboutDialogComponent;
2017-02-21 07:54:42 +01:00
// Status flag
2017-03-07 10:20:33 +01:00
signInStatus: number = signInStatusNormal;
2017-02-21 07:54:42 +01:00
// Initialize sign in credential
2017-02-21 07:54:42 +01:00
@Input() signInCredential: SignInCredential = {
principal: '',
password: '',
2017-02-21 07:54:42 +01:00
};
isCoreServiceAvailable: boolean = true;
steps: number = 1;
hasLoadedAppConfig: boolean = false;
2017-02-21 07:54:42 +01:00
constructor(
private router: Router,
2017-03-07 10:20:33 +01:00
private session: SessionService,
private route: ActivatedRoute,
private appConfigService: AppConfigService,
2017-10-16 04:54:38 +02:00
private cookie: CookieService,
private skinableConfig: SkinableConfig,
private userPermissionService: UserPermissionService
) {}
2017-02-21 07:54:42 +01:00
2017-03-07 10:20:33 +01:00
ngOnInit(): void {
2017-10-16 04:54:38 +02:00
// custom skin
let customSkinObj = this.skinableConfig.getSkinConfig();
2017-11-16 07:55:44 +01:00
if (customSkinObj) {
if (customSkinObj.loginBgImg) {
this.customLoginBgImg = customSkinObj.loginBgImg;
}
if (customSkinObj.loginTitle) {
this.customAppTitle = customSkinObj.loginTitle;
}
2017-10-16 04:54:38 +02:00
}
this.route.queryParams.subscribe(params => {
this.redirectUrl = params['redirect_url'] || '';
let isSignUp = params['sign_up'] || '';
if (isSignUp !== '') {
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;
}
2017-03-07 10:20:33 +01:00
}
// App title
2017-03-30 06:33:42 +02:00
public get appTitle(): string {
return 'APP_TITLE.VMW_HARBOR';
2017-03-30 06:33:42 +02:00
}
// For template accessing
2017-02-28 05:46:15 +01:00
public get isError(): boolean {
return this.signInStatus === signInStatusError;
2017-02-21 07:54:42 +01:00
}
2017-02-28 05:46:15 +01:00
public get isOnGoing(): boolean {
return this.signInStatus === signInStatusOnGoing;
2017-02-21 07:54:42 +01:00
}
// Validate the related fields
2017-02-28 05:46:15 +01:00
public get isValid(): boolean {
return this.currentForm.form.valid;
2017-02-21 07:54:42 +01:00
}
// Whether show the 'sign up' link
public get selfSignUp(): boolean {
return (
this.appConfigService.getConfig() &&
this.appConfigService.getConfig().auth_mode ===
CONFIG_AUTH_MODE.DB_AUTH &&
this.appConfigService.getConfig().self_registration
);
}
public get isOidcLoginMode(): boolean {
return (
this.appConfigService.getConfig() &&
this.appConfigService.getConfig().auth_mode ===
CONFIG_AUTH_MODE.OIDC_AUTH
);
}
2017-04-20 17:47:06 +02:00
clickRememberMe($event: any): void {
if ($event && $event.target) {
this.rememberMe = $event.target.checked;
if (!this.rememberMe) {
// Remove cookie data
this.cookie.remove(remCookieKey);
this.rememberedName = '';
}
}
}
2017-04-20 17:47:06 +02:00
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);
2017-04-20 17:47:06 +02:00
let cookieptions: CookieOptions = {
path: '/',
expires: date,
2017-04-20 17:47:06 +02:00
};
this.cookie.put(
remCookieKey,
this.signInCredential.principal,
cookieptions
);
}
}
}
// General error handler
2017-04-20 17:47:06 +02:00
handleError(error: any) {
// Set error status
2017-02-21 07:54:42 +01:00
this.signInStatus = signInStatusError;
let message = error.status
? error.status + ':' + error.statusText
: error;
console.error('An error occurred when signing in:', message);
2017-02-21 07:54:42 +01:00
}
// Hande form values changes
2017-04-20 17:47:06 +02:00
formChanged() {
2017-02-21 07:54:42 +01:00
if (this.currentForm === this.signInForm) {
return;
}
this.signInForm = this.currentForm;
if (this.signInForm) {
this.signInForm.valueChanges.subscribe(data => {
this.updateState();
});
2017-02-21 07:54:42 +01:00
}
}
// Fill the new user info into the sign in form
2017-04-20 17:47:06 +02:00
handleUserCreation(user: User): void {
2017-03-24 11:29:51 +01:00
if (user) {
this.currentForm.setValue({
login_username: user.username,
login_password: '',
});
}
}
// Implement interface
// Watch the view change only when view is in error state
2017-02-21 07:54:42 +01:00
ngAfterViewChecked() {
if (this.signInStatus === signInStatusError) {
this.formChanged();
}
}
// Update the status if we have done some changes
2017-02-21 07:54:42 +01:00
updateState(): void {
if (this.signInStatus === signInStatusError) {
this.signInStatus = signInStatusNormal; // reset
2017-02-21 07:54:42 +01:00
}
}
// Trigger the signin action
2017-02-21 07:54:42 +01:00
signIn(): void {
// Should validate input firstly
if (!this.isValid) {
// Set error status
this.signInStatus = signInStatusError;
return;
}
if (this.isOnGoing) {
// Ongoing, directly return
2017-02-21 07:54:42 +01:00
return;
}
// Start signing in progress
2017-02-21 07:54:42 +01:00
this.signInStatus = signInStatusOnGoing;
// Call the service to send out the http request
this.session.signIn(this.signInCredential).subscribe(
() => {
// Set status
// Keep it ongoing to keep the button 'disabled'
// this.signInStatus = signInStatusNormal;
// clear permissions cache
this.userPermissionService.clearPermissionCache();
// Remeber me
this.remeberMe();
// Redirect to the right router-guard
if (
!this.redirectUrl ||
this.redirectUrl.startsWith(CommonRoutes.EMBEDDED_SIGN_IN)
) {
// Routing to the default location
this.router.navigateByUrl(CommonRoutes.HARBOR_DEFAULT);
} else {
2017-03-07 10:20:33 +01:00
this.router.navigateByUrl(this.redirectUrl);
}
this.isCoreServiceAvailable = true;
// after login successfully: Make sure the updated configuration can be loaded
this.appConfigService.load().subscribe();
},
error => {
// 403 oidc login no body;
if (this.isOidcLoginMode && error && error.status === 403) {
try {
let redirect_location = '';
redirect_location =
error.error && error.error.redirect_location
? error.error.redirect_location
: JSON.parse(error.error).redirect_location;
window.location.href = redirect_location;
return;
} catch (error) {}
}
// core service is not available for error code 5xx
if (error && /5[0-9][0-9]/.test(error.status)) {
this.isCoreServiceAvailable = false;
}
this.handleError(error);
}
);
2017-02-21 07:54:42 +01:00
}
// Open sign up dialog
2017-02-21 07:54:42 +01:00
signUp(): void {
2017-03-07 10:20:33 +01:00
this.signUpDialog.open();
}
// Open forgot password dialog
2017-03-07 10:20:33 +01:00
forgotPassword(): void {
this.forgotPwdDialog.open();
2017-02-21 07:54:42 +01:00
}
// Open modal dialog
openModal(event: ModalEvent): void {
switch (event.modalName) {
case modalEvents.ABOUT:
this.aboutDialog.open();
break;
default:
break;
}
}
}