WIP
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { DialogModule, DialogService } from '@progress/kendo-angular-dialog';
|
||||
import { ButtonsModule } from '@progress/kendo-angular-buttons';
|
||||
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { InputsModule } from '@progress/kendo-angular-inputs';
|
||||
import { LabelModule } from '@progress/kendo-angular-label';
|
||||
import { IndicatorsModule } from '@progress/kendo-angular-indicators';
|
||||
import { MfaDialogComponent } from '../../shared/mfa-dialog/mfa-dialog.component';
|
||||
import { AuthService, LoginCredentials, LoginResultType, TokenVerificationResult } from '../../shared/services/auth.service';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login-page',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
DialogModule,
|
||||
ButtonsModule,
|
||||
ReactiveFormsModule,
|
||||
InputsModule,
|
||||
LabelModule,
|
||||
IndicatorsModule,
|
||||
MfaDialogComponent
|
||||
],
|
||||
templateUrl: './login-page.component.html',
|
||||
styleUrls: ['./login-page.component.scss']
|
||||
})
|
||||
export class LoginPage implements OnInit {
|
||||
@ViewChild('mfaDialog') mfaDialog!: MfaDialogComponent;
|
||||
|
||||
activeTab: 'user' | 'admin' = 'user';
|
||||
showLoginForm = false;
|
||||
loginForm: FormGroup;
|
||||
isProcessing = false;
|
||||
showError = false;
|
||||
errorMessage = '';
|
||||
|
||||
constructor(
|
||||
private dialogService: DialogService,
|
||||
private authService: AuthService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private fb: FormBuilder
|
||||
) {
|
||||
this.loginForm = this.fb.group({
|
||||
email: ['', [Validators.required, Validators.email]],
|
||||
password: ['', [Validators.required, Validators.minLength(6)]],
|
||||
rememberMe: [false]
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// Check if user is already logged in
|
||||
if (this.authService.isAuthenticated()) {
|
||||
this.redirectToDashboard();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for token in URL parameters
|
||||
this.route.queryParams.subscribe(params => {
|
||||
const token = params['token'];
|
||||
if (token) {
|
||||
this.verifySecretLinkToken(token);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setActiveTab(tab: 'user' | 'admin'): void {
|
||||
this.activeTab = tab;
|
||||
}
|
||||
|
||||
copyToClipboard(text: string): void {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
// You could add a toast notification here
|
||||
console.log('Copied to clipboard:', text);
|
||||
}).catch(err => {
|
||||
console.error('Failed to copy text: ', err);
|
||||
});
|
||||
}
|
||||
|
||||
showLoginFormView(): void {
|
||||
this.showLoginForm = true;
|
||||
// Focus on email input when form appears
|
||||
setTimeout(() => {
|
||||
const emailInput = document.querySelector('input[formControlName="email"]') as HTMLInputElement;
|
||||
if (emailInput) {
|
||||
emailInput.focus();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
goBackToInitialState(): void {
|
||||
this.showLoginForm = false;
|
||||
this.loginForm.reset();
|
||||
this.showError = false;
|
||||
this.errorMessage = '';
|
||||
}
|
||||
|
||||
onSubmit(): void {
|
||||
if (this.loginForm.valid && !this.isProcessing) {
|
||||
this.isProcessing = true;
|
||||
this.showError = false;
|
||||
|
||||
const credentials: LoginCredentials = this.loginForm.value;
|
||||
|
||||
this.authService.login(credentials).subscribe({
|
||||
next: (result) => {
|
||||
this.isProcessing = false;
|
||||
|
||||
if (result.result === LoginResultType.Success) {
|
||||
this.authService.setCurrentUser(result.responseData!);
|
||||
this.redirectToDashboard();
|
||||
} else if (result.result === LoginResultType.MfaRequired) {
|
||||
this.showMfaDialog(credentials);
|
||||
} else {
|
||||
this.showError = true;
|
||||
this.errorMessage = result.message || 'Invalid email or password';
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
this.isProcessing = false;
|
||||
this.showError = true;
|
||||
this.errorMessage = 'An error occurred during login. Please try again.';
|
||||
console.error('Login error:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get emailControl() {
|
||||
return this.loginForm.get('email');
|
||||
}
|
||||
|
||||
get passwordControl() {
|
||||
return this.loginForm.get('password');
|
||||
}
|
||||
|
||||
private showMfaDialog(credentials: LoginCredentials): void {
|
||||
if (this.mfaDialog) {
|
||||
// Set the login data for MFA dialog
|
||||
(this.mfaDialog as any).loginData = credentials;
|
||||
|
||||
// Show MFA dialog
|
||||
this.mfaDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
onMfaSuccess(userData: any): void {
|
||||
this.authService.setCurrentUser(userData);
|
||||
this.redirectToDashboard();
|
||||
}
|
||||
|
||||
onMfaCancel(): void {
|
||||
// Reset form and focus on email
|
||||
this.loginForm.reset();
|
||||
setTimeout(() => {
|
||||
const emailInput = document.querySelector('input[formControlName="email"]') as HTMLInputElement;
|
||||
if (emailInput) {
|
||||
emailInput.focus();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
|
||||
private verifySecretLinkToken(token: string): void {
|
||||
this.isProcessing = true;
|
||||
this.showError = false;
|
||||
|
||||
// First check if token is expired locally
|
||||
if (this.authService.isTokenExpired(token)) {
|
||||
this.isProcessing = false;
|
||||
this.showError = true;
|
||||
this.errorMessage = 'This link has expired. Please request a new one.';
|
||||
return;
|
||||
}
|
||||
|
||||
this.authService.verifySecretLinkToken(token).subscribe({
|
||||
next: (result: TokenVerificationResult) => {
|
||||
this.isProcessing = false;
|
||||
|
||||
if (result.isValid && result.user) {
|
||||
// Token is valid, set user and redirect
|
||||
this.authService.setCurrentUser(result.user);
|
||||
this.redirectToDashboard();
|
||||
} else {
|
||||
// Token verification failed
|
||||
this.showError = true;
|
||||
this.errorMessage = result.message || 'Invalid or expired link. Please request a new one.';
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
this.isProcessing = false;
|
||||
this.showError = true;
|
||||
this.errorMessage = 'An error occurred while verifying the link. Please try again.';
|
||||
console.error('Token verification error:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private redirectToDashboard(): void {
|
||||
const redirectUrl = this.authService.getRedirectUrl();
|
||||
this.router.navigate([redirectUrl || '/dashboard']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user