Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 1x 10x 10x 10x 10x 10x 3x 3x 1x 2x 2x 2x 2x 1x 1x 2x | import { ChangeDetectionStrategy, Component, inject, signal, } from '@angular/core'; import type { Signal, WritableSignal } from '@angular/core'; import { Auth, sendPasswordResetEmail } from '@angular/fire/auth'; import { FormGroup, ReactiveFormsModule } from '@angular/forms'; import type { FormControl, ValidationErrors } from '@angular/forms'; import { RouterLink } from '@angular/router'; import { SpinnerComponent } from '@app/shared/spinner/spinner.component'; import { AuthErrorMessagesComponent } from '../auth-error-messages/auth-error-messages.component'; import { getErrorCode } from '../error-code'; import { createEmailControl } from '../identity-forms'; /** FormGroup allows the use of (ngSubmit) on the Form element. */ type ForgotFormGroup = FormGroup<{ email: FormControl<string | null> }>; /** * Sends email to reset password for a user's account. */ @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [ AuthErrorMessagesComponent, ReactiveFormsModule, RouterLink, SpinnerComponent, ], selector: 'app-forgot-password', templateUrl: './forgot-password.component.html', }) export class ForgotPasswordComponent { /** Errors specific to the email field. */ public readonly $emailCntrlErrors: Signal<ValidationErrors | undefined>; /** Aria-invalid attribute for the email field. */ public readonly $emailCntrlInvalid: Signal<boolean>; /** Form submission errors from Firebase Authentication response. */ public readonly $errorCode: WritableSignal<string>; /** Toggle the HTML form and spinner. */ public readonly $showForm: WritableSignal<boolean>; public readonly emailCntrl: FormControl<string | null>; public readonly forgotForm: ForgotFormGroup; private readonly _auth: Auth; constructor() { this._auth = inject(Auth); ({ $errors: this.$emailCntrlErrors, $invalid: this.$emailCntrlInvalid, control: this.emailCntrl } = createEmailControl()); this.forgotForm = new FormGroup({ email: this.emailCntrl }); this.$errorCode = signal<string>(''); this.$showForm = signal<boolean>(true); } /** * Sends password reset email to submitted email address, if it exists in Firebase Authentication. * * Email enumeration protection is enabled in production, so errors should not indicate if an * account exists with the submitted email address. */ public async onSubmit(): Promise<void> { const { email } = this.forgotForm.value; // Validators prevent email being falsy, but TypeScript doesn't know that. if (this.forgotForm.invalid || !email) { throw new Error('Invalid form submitted'); } this.$showForm.set(false); this.$errorCode.set(''); // Clear out any existing errors try { await sendPasswordResetEmail(this._auth, email); } catch (err: unknown) { const code = getErrorCode(err); this.$errorCode.set(code); } this.$showForm.set(true); } } |