UNPKG

ngx-auth-firebaseui-updated

Version:

From ngx-auth-firbaseui but updated to fix dependency issues with Angular 16. Open Source Library for Angular Web Apps to integrate a material user interface for firebase authentication

648 lines (638 loc) 235 kB
import * as i0 from '@angular/core'; import { InjectionToken, Injectable, EventEmitter, forwardRef, Inject, Component, ChangeDetectionStrategy, Input, Output, ViewChild, PLATFORM_ID, ViewEncapsulation, NgModule } from '@angular/core'; import '@firebase/auth'; import * as i2 from '@angular/material/snack-bar'; import { MAT_SNACK_BAR_DEFAULT_OPTIONS, MatSnackBarModule } from '@angular/material/snack-bar'; import firebase from 'firebase/compat/app'; import { BehaviorSubject, Subject } from 'rxjs'; import { map, take, takeUntil } from 'rxjs/operators'; import * as i1$1 from '@angular/fire/compat/auth'; import { AngularFireAuthModule } from '@angular/fire/compat/auth'; import * as i1 from '@angular/fire/compat/firestore'; import { AngularFirestoreModule } from '@angular/fire/compat/firestore'; import * as i4 from '@angular/router'; import { RouterModule } from '@angular/router'; import * as i4$1 from '@angular/common'; import { isPlatformBrowser, CommonModule } from '@angular/common'; import * as i8 from '@angular/material/card'; import { MatCardModule } from '@angular/material/card'; import * as i6 from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button'; import * as i7 from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon'; import * as i7$1 from '@angular/material/progress-bar'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import * as i1$2 from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; import * as i6$1 from '@angular/forms'; import { UntypedFormGroup, UntypedFormControl, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms'; import * as i8$1 from '@angular/material/checkbox'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatLegacyTabGroup } from '@angular/material/legacy-tabs'; import * as i15 from '@angular-material-extensions/password-strength'; import { MatPasswordStrengthComponent, MatPasswordStrengthModule } from '@angular-material-extensions/password-strength'; import { animation, style, animate, trigger, transition, useAnimation, state, query, stagger, animateChild } from '@angular/animations'; import * as i3$1 from '@angular/material/legacy-dialog'; import * as i7$2 from '@angular/material/tabs'; import { MatTabsModule } from '@angular/material/tabs'; import * as i4$2 from '@angular/material/input'; import { MatInputModule } from '@angular/material/input'; import * as i5 from '@angular/material/form-field'; import * as i13 from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider'; import * as i3 from '@angular/cdk/layout'; import { Breakpoints } from '@angular/cdk/layout'; import * as i8$2 from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip'; import * as i9 from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu'; import { HttpClientModule } from '@angular/common/http'; import { FIREBASE_OPTIONS, FIREBASE_APP_NAME } from '@angular/fire/compat'; import { MatChipsModule } from '@angular/material/chips'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import * as i2$1 from '@angular/platform-browser'; var Accounts; (function (Accounts) { Accounts["NONE"] = "account"; Accounts["CHECK"] = "account-check"; Accounts["EDIT"] = "account-edit"; Accounts["OFF"] = "account-off"; Accounts["REMOVE"] = "account-remove"; })(Accounts || (Accounts = {})); // This token is the official token containing the final configuration; ie. the merge between default and user provided configurations const NgxAuthFirebaseUIConfigToken = new InjectionToken('NgxAuthFirebaseUIConfigToken'); // This is an intermediate token containing only user-provided configuration const UserProvidedConfigToken = new InjectionToken('UserProvidedConfigToken'); const collections = { users: "users", }; class FirestoreSyncService { constructor(afs) { this.afs = afs; // this.afs.firestore.settings({timestampsInSnapshots: true}); } // get timestamp() { // return firebase.firestore.FieldValue.serverTimestamp(); // } getUserDocRefByUID(uid) { return this.afs.doc(`${collections.users}/${uid}`); } deleteUserData(uid) { const userRef = this.getUserDocRefByUID(uid); return userRef.delete(); } updateUserData(user) { // Sets user$ data to firestore on login const userRef = this.getUserDocRefByUID(user.uid); const data = { uid: user.uid, email: user.email, displayName: user.displayName, photoURL: user.photoURL, phoneNumber: user.phoneNumber, providerId: user.providerId, }; return userRef.set(data, { merge: true }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FirestoreSyncService, deps: [{ token: i1.AngularFirestore }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FirestoreSyncService, providedIn: "root" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FirestoreSyncService, decorators: [{ type: Injectable, args: [{ providedIn: "root", }] }], ctorParameters: function () { return [{ type: i1.AngularFirestore }]; } }); const facebookAuthProvider = new firebase.auth.FacebookAuthProvider(); const googleAuthProvider = new firebase.auth.GoogleAuthProvider(); const appleAuthProvider = new firebase.auth.OAuthProvider("apple.com"); const twitterAuthProvider = new firebase.auth.TwitterAuthProvider(); const githubAuthProvider = new firebase.auth.GithubAuthProvider(); const microsoftAuthProvider = new firebase.auth.OAuthProvider("microsoft.com"); const yahooAuthProvider = new firebase.auth.OAuthProvider("yahoo.com"); var AuthProvider; (function (AuthProvider) { AuthProvider["ALL"] = "all"; AuthProvider["ANONYMOUS"] = "anonymous"; AuthProvider["EmailAndPassword"] = "firebase"; AuthProvider["Google"] = "google"; AuthProvider["Apple"] = "apple"; AuthProvider["Facebook"] = "facebook"; AuthProvider["Twitter"] = "twitter"; AuthProvider["Github"] = "github"; AuthProvider["Microsoft"] = "microsoft"; AuthProvider["Yahoo"] = "yahoo"; AuthProvider["PhoneNumber"] = "phoneNumber"; })(AuthProvider || (AuthProvider = {})); class AuthProcessService { get user$() { return this._user$.asObservable(); } constructor(afa, config, snackBar, fireStoreService, matSnackBarConfig) { this.afa = afa; this.config = config; this.snackBar = snackBar; this.fireStoreService = fireStoreService; this.matSnackBarConfig = matSnackBarConfig; this.onSuccessEmitter = new EventEmitter(); this.onErrorEmitter = new EventEmitter(); // Useful to know about auth state even between reloads. // Replace emailConfirmationSent and emailToConfirm. this._user$ = new BehaviorSubject(null); } listenToUserEvents() { this.afa.user.subscribe((user) => { this._user$.next(user); this.user = user; }); } /** * Reset the password of the ngx-auth-firebaseui-user via email * * @param email - the email to reset */ async resetPassword(email) { try { console.log("Password reset email sent"); return await this.afa.sendPasswordResetEmail(email); } catch (error) { return this.notifyError(error); } } /** * General sign in mechanism to authenticate the users with a firebase project * using a traditional way, via username and password or by using an authentication provider * like google, facebook, twitter and github * * @param provider - the provider to authenticate with (google, facebook, twitter, github) * @param credentials optional email and password */ async signInWith(provider, credentials) { try { let signInResult; switch (provider) { case AuthProvider.ANONYMOUS: signInResult = (await this.afa.signInAnonymously()); break; case AuthProvider.EmailAndPassword: signInResult = (await this.afa.signInWithEmailAndPassword(credentials.email, credentials.password)); break; case AuthProvider.Google: signInResult = (await this.afa.signInWithPopup(googleAuthProvider)); break; case AuthProvider.Apple: signInResult = (await this.afa.signInWithPopup(appleAuthProvider)); break; case AuthProvider.Facebook: signInResult = (await this.afa.signInWithPopup(facebookAuthProvider)); break; case AuthProvider.Twitter: signInResult = (await this.afa.signInWithPopup(twitterAuthProvider)); break; case AuthProvider.Github: signInResult = (await this.afa.signInWithPopup(githubAuthProvider)); break; case AuthProvider.Microsoft: signInResult = (await this.afa.signInWithPopup(microsoftAuthProvider)); break; case AuthProvider.Yahoo: signInResult = (await this.afa.signInWithPopup(yahooAuthProvider)); break; case AuthProvider.PhoneNumber: // coming soon - see feature/sms branch break; default: throw new Error(`${AuthProvider[provider]} is not available as auth provider`); } await this.handleSuccess(signInResult); } catch (err) { this.handleError(err); } } /** * Sign up new users via email and password. * After that the ngx-auth-firebaseui-user should verify and confirm an email sent via the firebase * * @param displayName - the displayName if the new ngx-auth-firebaseui-user * @param credentials email and password * @returns - */ async signUp(displayName, credentials) { try { const userCredential = await this.afa.createUserWithEmailAndPassword(credentials.email, credentials.password); const user = userCredential.user; await this.updateProfile(displayName, user.photoURL); if (this.config.enableFirestoreSync) { await this.fireStoreService.getUserDocRefByUID(user.uid).set({ uid: user.uid, displayName, email: user.email, photoURL: user.photoURL, }); } if (this.config.enableEmailVerification) { await user.sendEmailVerification(); } // Legacy fields this.emailConfirmationSent = true; this.emailToConfirm = credentials.email; await this.handleSuccess(userCredential); } catch (err) { this.handleError(err); } } async sendNewVerificationEmail() { if (!this.user) { return Promise.reject(new Error("No signed in user")); } return this.user.sendEmailVerification(); } async signOut() { try { await this.afa.signOut(); } catch (error) { this.notifyError(error); } } /** * Update the profile (name + photo url) of the authenticated ngx-auth-firebaseui-user in the * firebase authentication feature (not in firestore) * * @param name - the new name of the authenticated ngx-auth-firebaseui-user * @param photoURL - the new photo url of the authenticated ngx-auth-firebaseui-user * @returns - */ updateProfile(name, photoURL) { return this.afa.currentUser.then((user) => { if (!photoURL) { return user.updateProfile({ displayName: name }); } else { return user.updateProfile({ displayName: name, photoURL }); } }); } parseUserInfo(user) { return { uid: user.uid, displayName: user.displayName, email: user.email, phoneNumber: user.phoneNumber, photoURL: user.photoURL, providerId: user.providerData.length > 0 ? user.providerData[0].providerId : null, }; } getUserPhotoUrl() { return this._user$.pipe(map((user) => { if (!user) { return null; } else if (user.photoURL) { return user.photoURL; } else if (user.emailVerified) { return this.getPhotoPath(Accounts.CHECK); } else if (user.isAnonymous) { return this.getPhotoPath(Accounts.OFF); } else { return this.getPhotoPath(Accounts.NONE); } })); } getPhotoPath(image) { return `assets/user/${image}.svg`; } signInWithPhoneNumber() { // todo: 3.1.18 } async handleSuccess(userCredential) { if (this.config.useRawUserCredential) { this.onSuccessEmitter.next(userCredential); } else { this.onSuccessEmitter.next(userCredential.user); } if (this.config.enableFirestoreSync) { try { await this.fireStoreService.updateUserData(this.parseUserInfo(userCredential.user)); } catch (e) { console.error(`Error occurred while updating user data with firestore: ${e}`); } } if (this.config.toastMessageOnAuthSuccess) { const fallbackMessage = `Hello ${userCredential.user.displayName ? userCredential.user.displayName : ""}!`; this.showToast(this.messageOnAuthSuccess || fallbackMessage); } } handleError(error) { this.notifyError(error); console.error(error); } // Refresh user info. Can be useful for instance to get latest status regarding email verification. reloadUserInfo() { return this._user$ .pipe(take(1)) .subscribe((user) => user && user.reload()); } // Search for an error message. // Consumers of this library are given the possibility to provide a // function in case they want to instrument message based on error properties. getMessageOnAuthError(error) { // eslint-disable-next-line no-bitwise return (error.toString() || "Sorry, something went wrong. Please retry later."); } // Show a toast using current snackbar config. If message is empty, no toast is displayed allowing to opt-out when needed. // Default MatSnackBarConfig has no duration, meaning it stays visible forever. // If that's the case, an action button is added to allow the end-user to dismiss the toast. showToast(message) { if (message) { this.snackBar.open(message, this.matSnackBarConfig.duration ? null : "OK"); } } showErrorToast(error) { if (this.config.toastMessageOnAuthError) { this.showToast(this.getMessageOnAuthError(error)); } } notifyError(error) { this.onErrorEmitter.emit(error); this.showErrorToast(error); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthProcessService, deps: [{ token: i1$1.AngularFireAuth }, { token: forwardRef(() => NgxAuthFirebaseUIConfigToken) }, { token: i2.MatSnackBar }, { token: FirestoreSyncService }, { token: MAT_SNACK_BAR_DEFAULT_OPTIONS }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthProcessService, providedIn: "root" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthProcessService, decorators: [{ type: Injectable, args: [{ providedIn: "root", }] }], ctorParameters: function () { return [{ type: i1$1.AngularFireAuth }, { type: undefined, decorators: [{ type: Inject, args: [forwardRef(() => NgxAuthFirebaseUIConfigToken)] }] }, { type: i2.MatSnackBar }, { type: FirestoreSyncService }, { type: i2.MatSnackBarConfig, decorators: [{ type: Inject, args: [MAT_SNACK_BAR_DEFAULT_OPTIONS] }] }]; } }); const defaultTranslations = { verifyEmailTitleText: 'Confirm your e-mail address!', verifyEmailConfirmationText: 'A confirmation e-mail has been sent.' + ' Check your inbox and click on the link "Confirm my e-mail" to confirm your e-mail address.', verifyEmailGoBackText: 'Go back', sendNewVerificationEmailText: 'Send new confirmation e-mail', signOutText: 'Sign out', messageOnEmailConfirmationSuccess: 'A new confirmation e-mail has been sent. Please check your inbox.', }; class EmailConfirmationComponent { constructor(authProcess, router, changeDetectorRef) { this.authProcess = authProcess; this.router = router; this.changeDetectorRef = changeDetectorRef; this.signOut = new EventEmitter(); } ngOnChanges(changes) { if (changes.verifyEmailTemplate && changes.verifyEmailTemplate.currentValue == null) { this.verifyEmailTemplate = this.defaultTemplate; console.log('ngOnChanges - defaultTemplate:', this.verifyEmailTemplate); } this.verifyEmailContext = this.createTemplateContext(); } ngOnInit() { if (!this.verifyEmailTemplate) { console.log('ngOnInit - defaultTemplate'); this.verifyEmailTemplate = this.defaultTemplate; } this.verifyEmailContext = this.createTemplateContext(); console.log('verifyEmailTemplate:', this.verifyEmailTemplate); console.log('verifyEmailContext:', this.verifyEmailContext); } async continue() { try { await this.authProcess.reloadUserInfo(); await this.router.navigate([this.goBackURL]); } catch (error) { this.authProcess.notifyError(error); } } async sendNewVerificationEmail() { try { this.isLoading = true; this.changeDetectorRef.markForCheck(); await this.authProcess.sendNewVerificationEmail(); this.authProcess.showToast(this.verifyEmailContext.messageOnEmailConfirmationSuccess); } catch (error) { this.authProcess.notifyError(error); } finally { this.isLoading = false; this.changeDetectorRef.markForCheck(); } } createTemplateContext() { return { email: this.email, goBackURL: this.goBackURL, verifyEmailTitleText: this.verifyEmailTitleText || defaultTranslations.verifyEmailTitleText, verifyEmailConfirmationText: this.verifyEmailConfirmationText || defaultTranslations.verifyEmailConfirmationText, verifyEmailGoBackText: this.verifyEmailGoBackText || defaultTranslations.verifyEmailGoBackText, sendNewVerificationEmailText: this.sendNewVerificationEmailText || defaultTranslations.sendNewVerificationEmailText, signOutText: this.signOutText || defaultTranslations.signOutText, messageOnEmailConfirmationSuccess: this.messageOnEmailConfirmationSuccess || defaultTranslations.messageOnEmailConfirmationSuccess }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EmailConfirmationComponent, deps: [{ token: AuthProcessService }, { token: i4.Router }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: EmailConfirmationComponent, selector: "ngx-auth-firebaseui-email-confirmation", inputs: { email: "email", goBackURL: "goBackURL", verifyEmailTitleText: "verifyEmailTitleText", verifyEmailConfirmationText: "verifyEmailConfirmationText", verifyEmailGoBackText: "verifyEmailGoBackText", sendNewVerificationEmailText: "sendNewVerificationEmailText", signOutText: "signOutText", messageOnEmailConfirmationSuccess: "messageOnEmailConfirmationSuccess", template: "template" }, outputs: { signOut: "signOut" }, viewQueries: [{ propertyName: "defaultTemplate", first: true, predicate: ["defaultVerifyEmail"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngTemplateOutlet=\"verifyEmailTemplate; context: verifyEmailContext\"></ng-container>\n<ng-template #defaultVerifyEmail let-email=\"email\" let-goBackURL=\"goBackURL\"\n let-sendNewVerificationEmailText=\"sendNewVerificationEmailText\"\n let-signOutText=\"signOutText\"\n let-verifyEmailConfirmationText=\"verifyEmailConfirmationText\" let-verifyEmailGoBackText=\"verifyEmailGoBackText\"\n let-verifyEmailTitleText=\"verifyEmailTitleText\">\n <mat-card class=\"verify-email\">\n <mat-card-content style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <mat-icon>email</mat-icon>\n <p class=\"title\" style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <span class=\"mat-subheading-2\">{{ verifyEmailTitleText }}</span>\n <span class=\"mat-body-2\">{{ email }}</span>\n </p>\n <p class=\"subtitle\">{{ verifyEmailConfirmationText }}</p>\n <mat-progress-bar *ngIf=\"isLoading\" mode=\"indeterminate\"></mat-progress-bar>\n </mat-card-content>\n <mat-card-actions style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <button (click)=\"continue()\" *ngIf=\"goBackURL\" class=\"go-back-button action-button\" mat-stroked-button>\n {{ verifyEmailGoBackText }}\n </button>\n <button (click)=\"sendNewVerificationEmail()\" class=\"send-new-mail-button action-button\"\n mat-stroked-button>{{ sendNewVerificationEmailText }}</button>\n <button (click)=\"this.signOut.emit()\" class=\"sign-out-button action-button\" color=\"warn\"\n mat-stroked-button>{{ signOutText }}</button>\n </mat-card-actions>\n </mat-card>\n</ng-template>\n", styles: [".material-icons{font-size:4rem}.verify-email{width:360px}.verify-email .mat-icon{height:4rem;width:4rem;color:#444}.verify-email .title{margin-top:16px}.verify-email .title .mat-subheading-2{margin-bottom:0}.verify-email .subtitle{margin:16px auto;text-align:justify}.verify-email p{display:block;-webkit-margin-before:1em;-webkit-margin-after:1em;-webkit-margin-start:0px;-webkit-margin-end:0px}.verify-email mat-card-actions{text-align:center;margin-top:1rem}.verify-email mat-card-actions .action-button{width:100%}.verify-email mat-card-actions .action-button+.action-button{margin-top:1rem}\n"], dependencies: [{ kind: "directive", type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i8.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i8.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i8.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EmailConfirmationComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-auth-firebaseui-email-confirmation', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngTemplateOutlet=\"verifyEmailTemplate; context: verifyEmailContext\"></ng-container>\n<ng-template #defaultVerifyEmail let-email=\"email\" let-goBackURL=\"goBackURL\"\n let-sendNewVerificationEmailText=\"sendNewVerificationEmailText\"\n let-signOutText=\"signOutText\"\n let-verifyEmailConfirmationText=\"verifyEmailConfirmationText\" let-verifyEmailGoBackText=\"verifyEmailGoBackText\"\n let-verifyEmailTitleText=\"verifyEmailTitleText\">\n <mat-card class=\"verify-email\">\n <mat-card-content style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <mat-icon>email</mat-icon>\n <p class=\"title\" style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <span class=\"mat-subheading-2\">{{ verifyEmailTitleText }}</span>\n <span class=\"mat-body-2\">{{ email }}</span>\n </p>\n <p class=\"subtitle\">{{ verifyEmailConfirmationText }}</p>\n <mat-progress-bar *ngIf=\"isLoading\" mode=\"indeterminate\"></mat-progress-bar>\n </mat-card-content>\n <mat-card-actions style=\"flex-direction: column\" fxLayoutAlign=\"center center\">\n <button (click)=\"continue()\" *ngIf=\"goBackURL\" class=\"go-back-button action-button\" mat-stroked-button>\n {{ verifyEmailGoBackText }}\n </button>\n <button (click)=\"sendNewVerificationEmail()\" class=\"send-new-mail-button action-button\"\n mat-stroked-button>{{ sendNewVerificationEmailText }}</button>\n <button (click)=\"this.signOut.emit()\" class=\"sign-out-button action-button\" color=\"warn\"\n mat-stroked-button>{{ signOutText }}</button>\n </mat-card-actions>\n </mat-card>\n</ng-template>\n", styles: [".material-icons{font-size:4rem}.verify-email{width:360px}.verify-email .mat-icon{height:4rem;width:4rem;color:#444}.verify-email .title{margin-top:16px}.verify-email .title .mat-subheading-2{margin-bottom:0}.verify-email .subtitle{margin:16px auto;text-align:justify}.verify-email p{display:block;-webkit-margin-before:1em;-webkit-margin-after:1em;-webkit-margin-start:0px;-webkit-margin-end:0px}.verify-email mat-card-actions{text-align:center;margin-top:1rem}.verify-email mat-card-actions .action-button{width:100%}.verify-email mat-card-actions .action-button+.action-button{margin-top:1rem}\n"] }] }], ctorParameters: function () { return [{ type: AuthProcessService }, { type: i4.Router }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { email: [{ type: Input }], goBackURL: [{ type: Input }], verifyEmailTitleText: [{ type: Input }], verifyEmailConfirmationText: [{ type: Input }], verifyEmailGoBackText: [{ type: Input }], sendNewVerificationEmailText: [{ type: Input }], signOutText: [{ type: Input }], messageOnEmailConfirmationSuccess: [{ type: Input }], template: [{ type: Input }], signOut: [{ type: Output }], defaultTemplate: [{ type: ViewChild, args: ['defaultVerifyEmail', { static: true }] }] } }); class LegalityDialogComponent { constructor(dialogRef, data) { this.dialogRef = dialogRef; this.data = data; // eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle, id-blacklist, id-match this._disableConfirmActionButton = false; } get disableConfirmActionButton() { if (this.data.tosUrl && this.data.privacyPolicyUrl) { this._disableConfirmActionButton = !(this.checkTOS && this.checkPrivacyPolicy); } else if (this.data.tosUrl && !this.data.privacyPolicyUrl) { this._disableConfirmActionButton = !this.checkTOS; } else if (!this.data.tosUrl && this.data.privacyPolicyUrl) { this._disableConfirmActionButton = !this.checkPrivacyPolicy; } return this._disableConfirmActionButton; } closeDialog() { const result = { checked: !this.disableConfirmActionButton, authProvider: this.data.authProvider }; this.dialogRef.close(result); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LegalityDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LegalityDialogComponent, selector: "ngx-auth-firebaseui-legality-dialog", ngImport: i0, template: "<h1 matDialogTitle>Legal requirements</h1>\n\n<mat-dialog-content>\n <div style=\"flex-direction: column\" fxLayoutAlign=\"start\">\n <mat-checkbox *ngIf=\"this.data.tosUrl\" [(ngModel)]=\"checkTOS\">\n I agree to the\n <span>&nbsp;</span>\n <a [href]=\"this.data.tosUrl\"\n target=\"_blank\">\n Terms of Service and Conditions\n </a>\n </mat-checkbox>\n\n <mat-checkbox *ngIf=\"this.data.privacyPolicyUrl\"\n [(ngModel)]=\"checkPrivacyPolicy\">\n I have read and agree to the\n <span>&nbsp;</span>\n <a [href]=\"this.data.privacyPolicyUrl\"\n target=\"_blank\">\n Privacy\n </a>\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button color=\"warn\"\n id=\"decline-action\"\n mat-raised-button\n matDialogClose>Decline\n </button>\n <button (click)=\"closeDialog()\"\n [disabled]=\"disableConfirmActionButton\"\n color=\"primary\"\n id=\"confirm-action\"\n mat-raised-button>Confirm\n </button>\n</mat-dialog-actions>\n\n", styles: ["::ng-deep .mat-checkbox-label{display:flex;flex-wrap:wrap}mat-dialog-content div{margin-top:1.5rem}mat-dialog-actions{margin-top:1rem}\n"], dependencies: [{ kind: "directive", type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i1$2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: i8$1.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LegalityDialogComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-auth-firebaseui-legality-dialog', template: "<h1 matDialogTitle>Legal requirements</h1>\n\n<mat-dialog-content>\n <div style=\"flex-direction: column\" fxLayoutAlign=\"start\">\n <mat-checkbox *ngIf=\"this.data.tosUrl\" [(ngModel)]=\"checkTOS\">\n I agree to the\n <span>&nbsp;</span>\n <a [href]=\"this.data.tosUrl\"\n target=\"_blank\">\n Terms of Service and Conditions\n </a>\n </mat-checkbox>\n\n <mat-checkbox *ngIf=\"this.data.privacyPolicyUrl\"\n [(ngModel)]=\"checkPrivacyPolicy\">\n I have read and agree to the\n <span>&nbsp;</span>\n <a [href]=\"this.data.privacyPolicyUrl\"\n target=\"_blank\">\n Privacy\n </a>\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button color=\"warn\"\n id=\"decline-action\"\n mat-raised-button\n matDialogClose>Decline\n </button>\n <button (click)=\"closeDialog()\"\n [disabled]=\"disableConfirmActionButton\"\n color=\"primary\"\n id=\"confirm-action\"\n mat-raised-button>Confirm\n </button>\n</mat-dialog-actions>\n\n", styles: ["::ng-deep .mat-checkbox-label{display:flex;flex-wrap:wrap}mat-dialog-content div{margin-top:1.5rem}mat-dialog-actions{margin-top:1rem}\n"] }] }], ctorParameters: function () { return [{ type: i1$2.MatDialogRef }, { type: undefined, decorators: [{ type: Inject, args: [MAT_DIALOG_DATA] }] }]; } }); // import * as firebase from 'firebase'; const defaultAuthFirebaseUIConfig = { // authMethod: 'redirect', // authProviders: [new GoogleAuthProvider(), new FacebookAuthProvider(), new TwitterAuthProvider(), new GithubAuthProvider()], enableFirestoreSync: true, toastMessageOnAuthSuccess: true, toastMessageOnAuthError: true, authGuardFallbackURL: '/', authGuardLoggedInURL: '/', // Password length min/max in forms independently of each componenet min/max. // `min/max` input parameters in components should be within this range. passwordMaxLength: 60, passwordMinLength: 8, // Same as password but for the name nameMaxLength: 50, nameMinLength: 2, // If set, sign-in/up form is not available until email has been verified. // Plus protected routes are still protected even though user is connected. guardProtectedRoutesUntilEmailIsVerified: true, // Default to email verification on enableEmailVerification: true, // Default to false to keep the current projects working as is useRawUserCredential: false }; // Merge default config with user provided config. function ngxAuthFirebaseUIConfigFactory(userProvidedConfig) { return Object.assign({}, defaultAuthFirebaseUIConfig, userProvidedConfig); } var Theme; (function (Theme) { Theme["DEFAULT"] = "default"; Theme["CLASSIC"] = "classic"; Theme["STROKED"] = "stroked"; Theme["FAB"] = "fab"; Theme["MINI_FAB"] = "mini-fab"; Theme["RAISED"] = "raised"; })(Theme || (Theme = {})); var Layout; (function (Layout) { Layout["ROW"] = "row"; Layout["COLUMN"] = "column"; })(Layout || (Layout = {})); const EMAIL_REGEX = new RegExp([ '^(([^<>()[\\]\\.,;:\\s@"]+(\\.[^<>()\\[\\]\\.,;:\\s@"]+)*)', '|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.', '[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+', '[a-zA-Z]{2,}))$', ].join('')); // eslint-disable-next-line max-len const PHONE_NUMBER_REGEX = new RegExp([ '^[+]{0,1}[(]{0,1}[0-9]{1,4}[)]{0,1}[-\\s\\.]{0,1}[(]{0,1}[0-9]{1,4}[)]{0,1}[-\\s\\./0-9]{4,12}$', ].join('')); const customAnimation = animation([ style({ opacity: '{{opacity}}', transform: 'scale({{scale}}) translate3d({{x}}, {{y}}, {{z}})' }), animate('{{duration}} {{delay}} cubic-bezier(0.0, 0.0, 0.2, 1)', style('*')) ], { params: { duration: '200ms', delay: '0ms', opacity: '0', scale: '1', x: '0', y: '0', z: '0' } }); const NgxAuthFirebaseuiAnimations = [ trigger('animate', [transition('void => *', [useAnimation(customAnimation)])]), trigger('animateStagger', [ state('50', style('*')), state('100', style('*')), state('200', style('*')), transition('void => 50', query('@*', [stagger('50ms', [animateChild()])], { optional: true })), transition('void => 100', query('@*', [stagger('100ms', [animateChild()])], { optional: true })), transition('void => 200', query('@*', [stagger('200ms', [animateChild()])], { optional: true })) ]), ]; class AuthProvidersComponent { constructor(authProcess, dialog, renderer, breakpointObserver) { this.authProcess = authProcess; this.dialog = dialog; this.renderer = renderer; this.breakpointObserver = breakpointObserver; this.layout = Layout.ROW; this.providers = AuthProvider.ALL; // google, facebook, twitter, github, microsoft, yahoo this.themes = Theme; this.authProvider = AuthProvider; this.onSuccess = authProcess.onSuccessEmitter; this.onError = authProcess.onErrorEmitter; } ngOnInit() { this.breakpointObserver.observe([Breakpoints.XSmall]) .subscribe(result => { this.isXsScreen = result.matches; }); } processLegalSignUP(authProvider) { if (this.tosUrl || this.privacyPolicyUrl) { const params = { tosUrl: this.tosUrl, privacyPolicyUrl: this.privacyPolicyUrl, authProvider }; this.dialogRef = this.dialog.open(LegalityDialogComponent, { data: params }); this.dialogRef.afterClosed().subscribe((result) => { if (result && result.checked) { // this._afterSignUpMiddleware(result.authProvider).then(() => this.signUpFormGroup.reset()); this.authProcess.signInWith(authProvider); } this.dialogRef = null; }); } else { // this._afterSignUpMiddleware(authProvider).then(() => this.signUpFormGroup.reset()); this.authProcess.signInWith(authProvider); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthProvidersComponent, deps: [{ token: AuthProcessService }, { token: i1$2.MatDialog }, { token: i0.Renderer2 }, { token: i3.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AuthProvidersComponent, selector: "ngx-auth-firebaseui-providers", inputs: { theme: "theme", layout: "layout", providers: "providers", tosUrl: "tosUrl", privacyPolicyUrl: "privacyPolicyUrl" }, outputs: { onSuccess: "onSuccess", onError: "onError" }, ngImport: i0, template: "<div [@animateStagger]=\"{ value: '50' }\" [ngSwitch]=\"theme\">\n\n <!--default icon buttons-->\n <div *ngSwitchDefault\n [ngStyle]=\"{'flex-direction': isXsScreen ? 'column' : layout, 'justify-content': layout == 'row' ? 'space-around center' : 'stretch'}\">\n <button (click)=\"processLegalSignUP(authProvider.Google)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Google)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n mat-button>\n <mat-icon svgIcon=\"google-colored\"></mat-icon>\n Google\n </button>\n\n <button (click)=\"processLegalSignUP(authProvider.Apple)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Apple)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"apple-filled\"\n mat-button>\n <mat-icon svgIcon=\"apple\"></mat-icon>\n Apple\n </button>\n\n <button (click)=\"processLegalSignUP(authProvider.Facebook)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Facebook)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"facebook-filled\"\n mat-button>\n <mat-icon svgIcon=\"facebook\"></mat-icon>\n Facebook\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Twitter)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Twitter)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"twitter-filled\"\n mat-button>\n <mat-icon svgIcon=\"twitter\"></mat-icon>\n Twitter\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Github)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Github)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n mat-button>\n <mat-icon svgIcon=\"github\"></mat-icon>\n GitHub\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Microsoft)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Microsoft)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n mat-button>\n <mat-icon svgIcon=\"microsoft\"></mat-icon>\n Microsoft\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Yahoo)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Yahoo)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n mat-button>\n <mat-icon svgIcon=\"yahoo\"></mat-icon>\n Yahoo\n </button>\n </div>\n\n <!--classic-->\n <div *ngSwitchCase=\"themes.CLASSIC\"\n [ngStyle]=\"{'flex-direction': isXsScreen ? 'column' : layout, 'justify-content': layout == 'row'? 'space-around center' : 'stretch'}\"\n class=\"buttons-classic\">\n <button (click)=\"processLegalSignUP(authProvider.Google)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Google)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"google-classic\"\n mat-button>\n Google\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Apple)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Apple)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"apple-classic\"\n mat-button>\n Apple\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Facebook)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Facebook)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"facebook-classic\"\n mat-button>\n Facebook\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Twitter)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Twitter)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"twitter-classic\"\n mat-button>\n Twitter\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Github)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Github)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"github-classic\"\n mat-button>\n GitHub\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Microsoft)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Microsoft)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"microsoft-classic\"\n mat-button>\n Microsoft\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Yahoo)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Yahoo)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"yahoo-classic\"\n mat-button>\n Yahoo\n </button>\n </div>\n\n <!--stroked-->\n <div *ngSwitchCase=\"themes.STROKED\"\n\n [ngStyle]=\"{'flex-direction': isXsScreen ? 'column' : layout, 'justify-content': layout == 'row' ? 'space-around center' : 'stretch'}\"\n class=\"buttons-classic\">\n <button (click)=\"processLegalSignUP(authProvider.Google)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Google)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':true}\"\n class=\"google-classic\"\n mat-stroked-button>\n Google\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Apple)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Apple)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"apple-classic\"\n mat-stroked-button>\n Apple\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Facebook)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Facebook)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"facebook-classic\"\n mat-stroked-button>\n Facebook\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Twitter)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Twitter)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"twitter-classic\"\n mat-stroked-button>\n Twitter\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Github)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Github)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"github-classic\"\n mat-stroked-button>\n GitHub\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Microsoft)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Microsoft)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"microsoft-classic\"\n mat-stroked-button>\n Microsoft\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Yahoo)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Yahoo)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"yahoo-classic\"\n mat-stroked-button>\n Yahoo\n </button>\n </div>\n\n <!--raised-->\n <div *ngSwitchCase=\"themes.RAISED\"\n [ngStyle]=\"{'flex-direction': isXsScreen ? 'column' : layout, 'justify-content': layout == 'row' ? 'space-around center' : 'stretch'}\"\n class=\"buttons-raised\">\n <button (click)=\"processLegalSignUP(authProvider.Google)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Google)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"google-raised\"\n mat-raised-button>\n Google\n </button>\n <button (click)=\"processLegalSignUP(authProvider.Apple)\"\n *ngIf=\"providers === authProvider.ALL || providers.includes(authProvider.Apple)\"\n [@animate]=\"{value:'*',params:{duration:'300ms',y:'100px'}}\"\n [ngClass]=\"{'space-full-xs':isXsScreen}\"\n class=\"apple-ra