diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index bbb5677..a2ab328 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -28,7 +28,7 @@ export const routes: Routes = [ { path: 'login/notice/:id', component: LoginComponent }, { path: 'register', component: RegisterComponent }, { path: 'forgot-pw', component: ForgotPwComponent }, - { path: 'pw-reset', component: PwResetComponent }, + { path: 'pw-reset/:uid/:token', component: PwResetComponent }, { path: 'login/imprint', component: ImprintComponent }, { path: 'login/privacy-policy', component: PrivacyPolicyComponent }, ], diff --git a/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.html b/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.html index 23b5944..c1037d3 100644 --- a/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.html +++ b/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.html @@ -43,7 +43,7 @@
@if (!password.valid && password.touched) {

{{ "register.errorPassword0" | translate }}

- } @else { @if (pwResetData.password.length < 6 && password.touched) { + } @else { @if (pwResetData.password.length < 8 && password.touched) {

{{ "register.errorPassword1" | translate }}

} }
@@ -79,6 +79,8 @@ } @if (pwResetData.password !== pwResetData.passwordConfirm && pwResetData.password !== "" && pwResetData.passwordConfirm !== "") {

{{ "register.errorPassword2" | translate }}

+ } @if (errorHttpMessage === 'Invalid reset link.') { +

{{ "forgotPW.invalidLink" | translate }}

} diff --git a/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.ts b/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.ts index 2225a61..a4b20b4 100644 --- a/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.ts +++ b/src/app/components/login/forgot-pw/pw-reset/pw-reset.component.ts @@ -5,10 +5,11 @@ import { FormBtnComponent } from '../../../../shared/components/buttons/form-btn import { FooterComponent } from '../../footer/footer.component'; import { HeaderComponent } from '../../header/header.component'; import { TranslateModule } from '@ngx-translate/core'; -import { LoginService } from '../../../../services/login.service'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs'; import { ButtonStateService } from '../../../../services/button-state.service'; +import { AuthService } from '../../../../services/auth.service'; +import { LoginService } from '../../../../services/login.service'; @Component({ selector: 'app-pw-reset', @@ -25,8 +26,11 @@ import { ButtonStateService } from '../../../../services/button-state.service'; styleUrl: './pw-reset.component.scss', }) export class PwResetComponent { - oobCode: string = ''; - private queryParamsSubscription: Subscription = new Subscription(); + private routeSubscription: Subscription = new Subscription(); + + uid: string = ''; + token: string = ''; + errorHttpMessage: string = ''; pwResetData = { password: '', @@ -35,26 +39,42 @@ export class PwResetComponent { constructor( public loginService: LoginService, + private authService: AuthService, private buttonStateService: ButtonStateService, private route: ActivatedRoute ) {} ngOnInit(): void { - this.queryParamsSubscription = this.route.queryParams.subscribe( - (params) => { - this.oobCode = params['oobCode']; - } - ); + this.routeSubscription = this.route.params.subscribe((params) => { + this.uid = params['uid']; + this.token = params['token']; + }); + } + + ngOnDestroy(): void { + if (this.routeSubscription) { + this.routeSubscription.unsubscribe(); + } } isButtonDisabled() { return this.buttonStateService.isButtonDisabled; } - onSubmit(ngForm: NgForm) { - this.buttonStateService.enableButton(); + async onSubmit(ngForm: NgForm) { + this.buttonStateService.disableButton(); if (ngForm.submitted && ngForm.form.valid) { - this.loginService.newPassword(this.pwResetData.password, this.oobCode); + try { + await this.authService.resetPasswordConfirm( + this.pwResetData.password, + this.uid, + this.token + ); + this.buttonStateService.enableButton(); + } catch (error: any) { + this.errorHttpMessage = error.message; + this.buttonStateService.enableButton(); + } } } } diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts index ad6072d..9f2118b 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -76,6 +76,7 @@ export class LoginComponent { async onSubmit(ngForm: NgForm) { this.buttonStateService.disableButton(); if (ngForm.submitted && ngForm.form.valid) { + this.loginData.email = this.loginData.email.toLowerCase(); try { await this.authService.login(this.loginData, this.checkboxRememberMe); this.router.navigate(['/summary']); diff --git a/src/app/components/login/register/register.component.ts b/src/app/components/login/register/register.component.ts index 527f746..bf1f177 100644 --- a/src/app/components/login/register/register.component.ts +++ b/src/app/components/login/register/register.component.ts @@ -53,6 +53,7 @@ export class RegisterComponent { this.buttonStateService.disableButton(); if (ngForm.submitted && ngForm.form.valid) { this.extractFirstAndLastName(); + this.registerData.email = this.registerData.email.toLowerCase(); try { await this.authService.register(this.registerData); this.buttonStateService.enableButton(); @@ -71,8 +72,11 @@ export class RegisterComponent { extractFirstAndLastName() { const names = this.registerData.name.split(' '); - this.registerData.firstName = names[0]; - this.registerData.lastName = names.slice(1).join(' '); + this.registerData.firstName = + names[0].charAt(0).toUpperCase() + names[0].slice(1).toLowerCase(); + this.registerData.lastName = + names.slice(1).join(' ').charAt(0).toUpperCase() + + names.slice(1).join(' ').slice(1).toLowerCase(); } isEmailValid(emailValue: string) { diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index d1c9b1c..3e8c8c6 100755 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -84,6 +84,23 @@ export class AuthService { } } + async resetPasswordConfirm(password: string, uid: string, token: string) { + try { + await lastValueFrom( + this.apiService.request('POST', `/auth/reset/confirm/`, { + password, + uid, + token, + }) + ); + this.toastNotificationService.resetPasswordConfirmSuccessToast(); + this.router.navigate(['/login']); + } catch (error: any) { + console.error('Password reset confirmation failed:', error); + throw new Error(error?.error?.error); + } + } + checkAuthUser(): Observable { return this.apiService.request('GET', `/auth/`).pipe( map(() => true), diff --git a/src/app/services/error-notification.service.ts b/src/app/services/error-notification.service.ts index 38be159..fe880f7 100755 --- a/src/app/services/error-notification.service.ts +++ b/src/app/services/error-notification.service.ts @@ -33,6 +33,10 @@ export class ErrorNotificationService { errorMessage = 'The requested page could not be found. Please make sure the URL is correct and try again.'; break; + case 406: + errorMessage = + 'The request was not acceptable. Invalid request parameters were provided.'; + break; case 408: errorMessage = 'The request timed out. Please check your connection and try again later.'; diff --git a/src/app/services/toast-notification.service.ts b/src/app/services/toast-notification.service.ts index 3536305..87b9ea1 100755 --- a/src/app/services/toast-notification.service.ts +++ b/src/app/services/toast-notification.service.ts @@ -36,6 +36,13 @@ export class ToastNotificationService { ); } + resetPasswordConfirmSuccessToast(): void { + this.createSuccessToast( + 'You have successfully reset your password. Please log in.', + 'Password Reset Successful' + ); + } + showSessionExpiredMessage(): void { this.createInfoToast( 'Your session has expired, please log in again.', diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 3ab72dd..0f6a5f6 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -20,6 +20,7 @@ "email": "Ihre E-Mail", "sendMail": "E-Mail senden", "pwChange": "Passwort ändern", + "invalidLink": "Dieser Link zum Zurücksetzen Ihres Passworts ist ungültig", "notice": "Wir senden Ihnen eine E-Mail, über die Sie Ihr Passwort ändern können" }, "msgDialog": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 0e43199..565b450 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -20,6 +20,7 @@ "email": "Your Email", "sendMail": "Send Mail", "pwChange": "Change Password", + "invalidLink": "This link to reset your password is invalid", "notice": "We will send you an email to change your password." }, "msgDialog": {