UNPKG

ng7-auth

Version:

Firestore Authentication with Angular. A Fork form Anthony Nahas.

1,303 lines (1,242 loc) 64.5 kB
import { Injectable, EventEmitter, Inject, Component, Input, Output, PLATFORM_ID, NgModule, InjectionToken } from '@angular/core'; import { AngularFirestore, AngularFirestoreModule } from '@angular/fire/firestore'; import { MatSnackBar, MAT_DIALOG_DATA, MatDialogRef, MatDialog, MatIconRegistry, MatButtonModule, MatCardModule, MatChipsModule, MatDialogModule, MatDividerModule, MatIconModule, MatInputModule, MatSnackBarModule, MatTabsModule, MatTooltipModule, MatProgressSpinnerModule, MatProgressBarModule, MatCheckboxModule } from '@angular/material'; import { AngularFireAuth, AngularFireAuthModule } from '@angular/fire/auth'; import { auth } from 'firebase/app'; import 'firebase/auth'; import { FormControl, FormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { isPlatformBrowser, CommonModule } from '@angular/common'; import { DomSanitizer } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { FirebaseOptionsToken, FirebaseNameOrConfigToken } from '@angular/fire'; import { FlexLayoutModule } from '@angular/flex-layout'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** @type {?} */ const collections = { users: 'users', }; class FirestoreSyncService { /** * @param {?} afs */ constructor(afs) { this.afs = afs; // this.afs.firestore.settings({timestampsInSnapshots: true}); } // get timestamp() { // return firebase.firestore.FieldValue.serverTimestamp(); // } /** * @param {?} uid * @return {?} */ getUserDocRefByUID(uid) { return this.afs.doc(`${collections.users}/${uid}`); } /** * @param {?=} queryFn * @return {?} */ getUsersCollectionRef(queryFn) { return this.afs.collection(`${collections.users}/`, queryFn); } /** * @param {?} uid * @return {?} */ deleteUserData(uid) { /** @type {?} */ const userRef = this.getUserDocRefByUID(uid); return userRef.delete(); } /** * @param {?} user * @return {?} */ updateUserData(user) { // Sets user$ data to firestore on login /** @type {?} */ const userRef = this.getUserDocRefByUID(user.uid); /** @type {?} */ 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 }); } } FirestoreSyncService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ FirestoreSyncService.ctorParameters = () => [ { type: AngularFirestore } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** @enum {string} */ const Accounts = { NONE: 'account', CHECK: 'account-check', EDIT: 'account-edit', OFF: 'account-off', REMOVE: 'account-remove', }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /** @type {?} */ const facebookAuthProvider = new auth.FacebookAuthProvider(); /** @type {?} */ const googleAuthProvider = new auth.GoogleAuthProvider(); /** @type {?} */ const twitterAuthProvider = new auth.TwitterAuthProvider(); /** @type {?} */ const githubAuthProvider = new auth.GithubAuthProvider(); /** @enum {string} */ const AuthProvider$$1 = { ALL: 'all', ANONYMOUS: 'anonymous', EmailAndPassword: 'firebase', Google: 'google', Facebook: 'facebook', Twitter: 'twitter', Github: 'github', PhoneNumber: 'phoneNumber', }; class AuthProcessService$$1 { /** * @param {?} config * @param {?} afa * @param {?} _snackBar * @param {?} _fireStoreService */ constructor(config, afa, _snackBar, _fireStoreService) { this.config = config; this.afa = afa; this._snackBar = _snackBar; this._fireStoreService = _fireStoreService; this.onSuccessEmitter = new EventEmitter(); this.onErrorEmitter = new EventEmitter(); } /** * Reset the password of the user via email * * @param {?} email - the email to reset * @return {?} */ resetPassword(email) { return this.afa.auth.sendPasswordResetEmail(email) .then(() => console.log('email sent')) .catch((error) => this.onErrorEmitter.next(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 {?=} email - (optional) the email of user - used only for a traditional sign in * @param {?=} password - (optional) the password of user - used only for a traditional sign in * @return {?} */ signInWith(provider, email, password) { return __awaiter(this, void 0, void 0, function* () { try { this.isLoading = true; /** @type {?} */ let signInResult; switch (provider) { case AuthProvider$$1.ANONYMOUS: signInResult = (/** @type {?} */ (yield this.afa.auth.signInAnonymously())); break; case AuthProvider$$1.EmailAndPassword: signInResult = (/** @type {?} */ (yield this.afa.auth.signInWithEmailAndPassword(email, password))); break; case AuthProvider$$1.Google: signInResult = (/** @type {?} */ (yield this.afa.auth.signInWithPopup(googleAuthProvider))); break; case AuthProvider$$1.Facebook: signInResult = (/** @type {?} */ (yield this.afa.auth.signInWithPopup(facebookAuthProvider))); break; case AuthProvider$$1.Twitter: signInResult = (/** @type {?} */ (yield this.afa.auth.signInWithPopup(twitterAuthProvider))); break; case AuthProvider$$1.Github: signInResult = (/** @type {?} */ (yield this.afa.auth.signInWithPopup(githubAuthProvider))); break; default: throw new Error(`${AuthProvider$$1[provider]} is not available as auth provider`); } yield this.handleSuccess(signInResult); } catch (err) { this.handleError(err); console.error(err); // this._snackBar.open(err.message, 'OK', {duration: 5000}); this.onErrorEmitter.next(err); } finally { this.isLoading = false; } }); } /** * Sign up new users via email and password. * After that the user should verify and confirm an email sent via the firebase * * @param {?} name - the name if the new user * @param {?} email - the email if the new user * @param {?} password - the password if the new user * @return {?} */ signUp(name, email, password) { return __awaiter(this, void 0, void 0, function* () { try { this.isLoading = true; /** @type {?} */ const userCredential = yield this.afa.auth.createUserWithEmailAndPassword(email, password); /** @type {?} */ const user = userCredential.user; console.log('onsignUp the user = ', user); yield this._fireStoreService .getUserDocRefByUID(user.uid) .set((/** @type {?} */ ({ uid: user.uid, displayName: name, email: user.email, photoURL: user.photoURL }))); yield user.sendEmailVerification(); yield this.updateProfile(name, user.photoURL); this.emailConfirmationSent = true; this.emailToConfirm = email; yield this.handleSuccess(userCredential); } catch (err) { this.handleError(err); } finally { this.isLoading = false; } }); } /** * Update the profile (name + photo url) of the authenticated user in the * firebase authentication feature (not in firestore) * * @param {?} name - the new name of the authenticated user * @param {?} photoURL - the new photo url of the authenticated user * @return {?} */ updateProfile(name, photoURL) { return __awaiter(this, void 0, void 0, function* () { return yield this.afa.auth.currentUser.updateProfile({ displayName: name, photoURL: photoURL }); }); } /** * @return {?} */ deleteAccount() { return __awaiter(this, void 0, void 0, function* () { return yield this.afa.auth.currentUser.delete(); }); } /** * @param {?} user * @return {?} */ 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 }; } /** * @return {?} */ getUserPhotoUrl() { /** @type {?} */ const user = this.afa.auth.currentUser; if (!user) { return; } 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); } } /** * @param {?} image * @return {?} */ getPhotoPath(image) { return `assets/user/${image}.svg`; } /** * @return {?} */ signInWithPhoneNumber() { // todo: 3.1.18 } /** * @param {?} userCredential * @return {?} */ handleSuccess(userCredential) { return __awaiter(this, void 0, void 0, function* () { yield this._fireStoreService.updateUserData(this.parseUserInfo(userCredential.user)); if (this.config.toastMessageOnAuthSuccess) { this._snackBar.open(`Hallo ${userCredential.user.displayName ? userCredential.user.displayName : ''}!`, 'OK', { duration: 5000 }); } this.onSuccessEmitter.next(userCredential.user); }); } /** * @param {?} error * @return {?} */ handleError(error) { if (this.config.toastMessageOnAuthError) { this._snackBar.open(error.message, 'OK', { duration: 5000 }); } console.error(error); this.onErrorEmitter.next(error); } } AuthProcessService$$1.decorators = [ { type: Injectable }, ]; /** @nocollapse */ AuthProcessService$$1.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: [NgxAuthFirebaseUIConfigToken,] }] }, { type: AngularFireAuth }, { type: MatSnackBar }, { type: FirestoreSyncService } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class LegalityDialogComponent { /** * @param {?} dialogRef * @param {?} data */ constructor(dialogRef, data) { this.dialogRef = dialogRef; this.data = data; this._disableConfirmActionButton = false; } /** * @return {?} */ 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; } /** * @return {?} */ closeDialog() { /** @type {?} */ const result = { checked: !this.disableConfirmActionButton, authProvider: this.data.authProvider }; this.dialogRef.close(result); } } LegalityDialogComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-auth-firebaseui-legality-dialog', template: ` <h1 matDialogTitle>Legal requirements</h1> <mat-dialog-content> <div fxLayout="column" fxLayoutAlign="start"> <mat-checkbox *ngIf="this.data.tosUrl" [(ngModel)]="checkTOS"> I agree to the <span>&nbsp;</span> <a target="_blank" [href]="this.data.tosUrl"> Terms of Service and Conditions </a> </mat-checkbox> <mat-checkbox *ngIf="this.data.privacyPolicyUrl" [(ngModel)]="checkPrivacyPolicy"> I have read and agree to the <span>&nbsp;</span> <a target="_blank" [href]="this.data.privacyPolicyUrl"> Privacy </a> </mat-checkbox> </div> </mat-dialog-content> <mat-dialog-actions> <button id="decline-action" mat-raised-button matDialogClose color="warn">Decline</button> <button id="confirm-action" mat-raised-button color="primary" [disabled]="disableConfirmActionButton" (click)="closeDialog()">Confirm </button> </mat-dialog-actions> `, 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} `] },] }, ]; /** @nocollapse */ LegalityDialogComponent.ctorParameters = () => [ { type: MatDialogRef }, { type: undefined, decorators: [{ type: Inject, args: [MAT_DIALOG_DATA,] }] } ]; var __awaiter$1 = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /** @type {?} */ 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('')); /** @type {?} */ const PHONE_NUMBER_REGEX = new RegExp(/^\+(?:[0-9] ?){6,14}[0-9]$/); class AuthComponent { /** * @param {?} platformId * @param {?} auth * @param {?} authProcess * @param {?} dialog */ constructor(platformId, auth$$1, authProcess, dialog) { this.platformId = platformId; this.auth = auth$$1; this.authProcess = authProcess; this.dialog = dialog; this.providers = AuthProvider$$1.ALL; // google, facebook, twitter, github as array or all as one single string this.guestEnabled = true; this.authProvider = AuthProvider$$1; this.authenticationError = false; this.passReset = false; this.authProviders = AuthProvider$$1; this.onSuccess = authProcess.onSuccessEmitter; this.onError = authProcess.onErrorEmitter; } /** * @return {?} */ ngOnInit() { if (isPlatformBrowser(this.platformId)) { this.onErrorSubscription = this.onError.subscribe(() => this.authenticationError = true); } this._initSignInFormGroupBuilder(); this._initSignUpFormGroupBuilder(); this._initResetPasswordFormGroupBuilder(); } /** * @return {?} */ ngOnDestroy() { if (this.onErrorSubscription) { this.onErrorSubscription.unsubscribe(); } } /** * @return {?} */ get color() { return this.authenticationError ? 'warn' : 'primary'; } /** * @return {?} */ createForgotPasswordTab() { this.passwordResetWished = true; setTimeout(() => this.tabIndex = 0, 100); } /** * @param {?=} authProvider * @return {?} */ openLegalityDialog(authProvider) { if (this.tosUrl || this.privacyPolicyUrl) { /** @type {?} */ const params = { tosUrl: this.tosUrl, privacyPolicyUrl: this.privacyPolicyUrl, authProvider: authProvider }; this.dialogRef = this.dialog.open(LegalityDialogComponent, { data: params }); this.dialogRef.afterClosed().subscribe((result) => { console.log('this.dialogRef.afterClosed(): ', result); if (result && result.checked) { this._afterSignUpMiddleware(result.authProvider).then(() => this.signUpFormGroup.reset()); } this.dialogRef = null; }); } else { this._afterSignUpMiddleware(authProvider).then(() => this.signUpFormGroup.reset()); } } /** * @return {?} */ signUp() { return __awaiter$1(this, void 0, void 0, function* () { return yield this.authProcess.signUp(this.signUpFormGroup.value.name, this.signUpFormGroup.value.email, this.signUpFormGroup.value.password); }); } /** * @return {?} */ signUpAnonymously() { return __awaiter$1(this, void 0, void 0, function* () { return yield this.authProcess.signInWith(this.authProvider.ANONYMOUS); }); } /** * @return {?} */ resetPassword() { this.authProcess.resetPassword(this.resetPasswordEmailFormControl.value) .then(() => this.passReset = true); } /** * @return {?} */ _initSignInFormGroupBuilder() { this.signInFormGroup = new FormGroup({}); this.signInFormGroup.registerControl('email', this.signInEmailFormControl = new FormControl('', [ Validators.required, Validators.pattern(EMAIL_REGEX) ])); this.signInFormGroup.registerControl('password', this.sigInPasswordFormControl = new FormControl('', [ Validators.required, Validators.minLength(6), Validators.maxLength(25), ])); } /** * @return {?} */ _initSignUpFormGroupBuilder() { this.signUpFormGroup = new FormGroup({ name: this.sigUpNameFormControl = new FormControl('', [ Validators.required, Validators.minLength(2), Validators.maxLength(30), ]), email: this.sigUpEmailFormControl = new FormControl('', [ Validators.required, Validators.pattern(EMAIL_REGEX) ]), password: this.sigUpPasswordFormControl = new FormControl('', [ Validators.required, Validators.minLength(6), Validators.maxLength(25), ]) }); } /** * @return {?} */ _initResetPasswordFormGroupBuilder() { this.resetPasswordFormGroup = new FormGroup({ email: this.resetPasswordEmailFormControl = new FormControl('', [ Validators.required, Validators.pattern(EMAIL_REGEX) ]) }); } /** * @param {?=} authProvider * @return {?} */ _afterSignUpMiddleware(authProvider) { if (authProvider === this.authProvider.ANONYMOUS) { return this.signUpAnonymously(); } return this.signUp(); } } AuthComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-auth-firebaseui', template: ` <mat-tab-group [color]="color" [selectedIndex]="tabIndex"> <!--Reset password tab--> <mat-tab *ngIf="passwordResetWished" label="Reset Password"> <form [formGroup]="resetPasswordFormGroup" (ngSubmit)="resetPasswordFormGroup.valid && resetPassword()"> <mat-card> <mat-card-header fxLayoutAlign="end"> <button mat-icon-button [color]="color" matTooltip="close" matTooltipPosition="above" (click)="passwordResetWished = false"> <mat-icon>close</mat-icon> </button> </mat-card-header> <mat-card-content> <mat-form-field class="full-width" [appearance]="appearance"> <mat-label>Reset e-mail address to password</mat-label> <input matInput [readonly]="passReset" formControlName="email" title="Reset e-mail address to password" required> <mat-icon matSuffix [color]="color">email</mat-icon> <mat-error *ngIf="resetPasswordEmailFormControl.hasError('required')"> E-mail is required to reset the password! </mat-error> <mat-error *ngIf="resetPasswordEmailFormControl.hasError('pattern')"> Please enter a valid e-mail address </mat-error> </mat-form-field> </mat-card-content> <mat-card-actions fxLayoutAlign="center"> <button mat-raised-button type="submit" [color]="color" [disabled]="passReset"> Reset </button> </mat-card-actions> <mat-card-footer *ngIf="passReset" fxLayoutAlign="center"> <p>Reset requested. Check your e-mail instructions.</p> </mat-card-footer> <mat-card-footer> <mat-progress-bar *ngIf="authProcess.isLoading" mode="indeterminate"></mat-progress-bar> </mat-card-footer> </mat-card> </form> </mat-tab> <!--Sign in tab--> <mat-tab label="Sign in"> <mat-card> <mat-card-title>Signing in</mat-card-title> <mat-card-content> <form [formGroup]="signInFormGroup" (ngSubmit)="signInFormGroup.valid && authProcess.signInWith (authProviders.EmailAndPassword,signInFormGroup.value.email,signInFormGroup.value.password)"> <div fxLayout="column" fxLayoutAlign="center"> <mat-form-field [appearance]="appearance"> <mat-label>E-mail</mat-label> <input matInput placeholder="E-mail" formControlName="email" required> <mat-icon matSuffix [color]="color">email</mat-icon> <mat-error *ngIf="signInEmailFormControl.hasError('required')"> E-mail is required </mat-error> <mat-error *ngIf="signInEmailFormControl.hasError('pattern')"> Please enter a valid e-mail address </mat-error> </mat-form-field> <mat-form-field [appearance]="appearance"> <mat-label>Password</mat-label> <input matInput type="current-password" placeholder="Password" minlength="6" maxlength="25" formControlName="password" required> <mat-icon matSuffix [color]="color">lock</mat-icon> <mat-hint align="end" aria-live="polite"> {{signInFormGroup.value.password.length}} / 25 </mat-hint> <mat-error *ngIf="sigInPasswordFormControl.hasError('required')"> Please do not forget the password </mat-error> <mat-error *ngIf="sigInPasswordFormControl.hasError('minlength')"> The password must be at least 6 characters long. </mat-error> <mat-error *ngIf="sigInPasswordFormControl.hasError('maxlength')"> The password must not exceed 25 characters </mat-error> </mat-form-field> <button mat-raised-button style="margin-top: 20px" type="submit" class="space-top" [color]="color"> Log In </button> </div> </form> <div fxLayoutAlign="center"> <button mat-button class="space-top" [color]="color" (click)="createForgotPasswordTab()"> Forgot Password? </button> </div> </mat-card-content> <mat-card-footer *ngIf="authProcess.isLoading"> <mat-progress-bar mode="indeterminate"></mat-progress-bar> </mat-card-footer> </mat-card> </mat-tab> <!--tab register--> <mat-tab label="Register"> <mat-card> <mat-card-title>Registration</mat-card-title> <div *ngIf="!authProcess.emailConfirmationSent;then register else confirm"></div> <ng-template #register> <mat-card-content fxLayout="column" fxLayoutAlign="center"> <form [formGroup]="signUpFormGroup" (ngSubmit)="signUpFormGroup.valid && authProcess.signUp (signUpFormGroup.value.name,signUpFormGroup.value.email,signUpFormGroup.value.password)"> <div fxLayout="column" fxLayoutAlign="center"> <!--name--> <mat-form-field [appearance]="appearance"> <!--labels will work only with @angular/material@6.2.0 --> <mat-label>Name</mat-label> <input matInput placeholder="Name" minlength="2" maxlength="30" [formControl]="sigUpNameFormControl" required> <mat-icon matSuffix [color]="color">person</mat-icon> <mat-hint align="end" aria-live="polite"> {{signUpFormGroup.value.name?.length}} / 25 </mat-hint> <mat-error *ngIf="sigUpNameFormControl.hasError('required')"> Name is required </mat-error> <mat-error *ngIf="sigUpPasswordFormControl.hasError('minlength')"> The name is too short! </mat-error> <mat-error *ngIf="sigUpPasswordFormControl.hasError('maxlength')"> The name is too long! </mat-error> </mat-form-field> <!--email--> <mat-form-field [appearance]="appearance"> <mat-label>E-mail</mat-label> <input matInput placeholder="E-mail" type="email" [formControl]="sigUpEmailFormControl"> <mat-icon matSuffix [color]="color">email</mat-icon> <mat-error *ngIf="sigUpEmailFormControl.hasError('required')"> E-mail is required </mat-error> <mat-error *ngIf="sigUpEmailFormControl.hasError('pattern')"> Please enter a valid e-mail address </mat-error> </mat-form-field> <!--password--> <div fxLayout="column"> <mat-form-field [appearance]="appearance"> <mat-label>Password</mat-label> <input matInput type="password" placeholder="password" name="password" [formControl]="sigUpPasswordFormControl" required> <mat-icon matSuffix [color]="color">lock</mat-icon> <mat-hint align="end" aria-live="polite"> {{signUpFormGroup.value.password?.length}} / 25 </mat-hint> <mat-error *ngIf="sigUpPasswordFormControl.hasError('required')" class="cut-text"> Please do not forget the password </mat-error> <mat-error *ngIf="sigUpPasswordFormControl.hasError('minlength')" class="cut-text"> The password must be at least 6 characters long. </mat-error> <mat-error *ngIf="sigUpPasswordFormControl.hasError('maxlength')" class="cut-text"> The password can not be longer than 25 characters. </mat-error> </mat-form-field> </div> <button mat-raised-button style="margin-top: 20px" type="submit" [color]="color"> Register </button> </div> </form> <button *ngIf="guestEnabled" mat-button style="margin-top: 20px" [color]="color" (click)="openLegalityDialog(authProvider.ANONYMOUS)"> <mat-icon>fingerprint</mat-icon> continue as guest </button> </mat-card-content> <mat-card-footer *ngIf="authProcess.isLoading"> <mat-progress-bar mode="indeterminate"></mat-progress-bar> </mat-card-footer> </ng-template> <!--confirm template--> <ng-template #confirm> <ngx-auth-firebaseui-email-confirmation [email]="authProcess.emailToConfirm" [goBackURL]="goBackURL"> </ngx-auth-firebaseui-email-confirmation> </ng-template> </mat-card> </mat-tab> </mat-tab-group> <mat-divider></mat-divider> <ngx-auth-firebaseui-providers [providers]="providers"></ngx-auth-firebaseui-providers> `, styles: [` .mat-card{margin:2rem}.space-top{margin-top:.5rem}.full-width{width:100%}.cut-text{text-overflow:ellipsis;overflow:hidden;white-space:nowrap} `] },] }, ]; /** @nocollapse */ AuthComponent.ctorParameters = () => [ { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }, { type: AngularFireAuth }, { type: AuthProcessService$$1 }, { type: MatDialog } ]; AuthComponent.propDecorators = { providers: [{ type: Input }], appearance: [{ type: Input }], tabIndex: [{ type: Input }], guestEnabled: [{ type: Input }], tosUrl: [{ type: Input }], privacyPolicyUrl: [{ type: Input }], goBackURL: [{ type: Input }], onSuccess: [{ type: Output }], onError: [{ type: Output }] }; var __awaiter$2 = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class UserComponent { /** * @param {?} auth * @param {?} authProcess * @param {?} _fireStoreService * @param {?} snackBar */ constructor(auth$$1, authProcess, _fireStoreService, snackBar) { this.auth = auth$$1; this.authProcess = authProcess; this._fireStoreService = _fireStoreService; this.snackBar = snackBar; this.onAccountDeleted = new EventEmitter(); } /** * @return {?} */ ngOnInit() { } /** * @return {?} */ initUpdateFormGroup() { /** @type {?} */ const currentUser = this.auth.auth.currentUser; this.updateFormGroup = new FormGroup({ name: this.updateNameFormControl = new FormControl({ value: currentUser.displayName, disabled: true }, [ Validators.required, Validators.minLength(2), Validators.maxLength(25), ]), email: this.updateEmailFormControl = new FormControl({ value: currentUser.email, disabled: true }, [ Validators.required, Validators.pattern(EMAIL_REGEX) ]), phoneNumber: this.updatePhoneNumberFormControl = new FormControl('', [Validators.pattern(PHONE_NUMBER_REGEX)]) }); this.updateFormGroup.enable(); } /** * @return {?} */ changeEditMode() { this.editMode = !this.editMode; this.editMode ? this.initUpdateFormGroup() : this.reset(); } /** * @return {?} */ reset() { this.updateFormGroup.reset(); this.updateFormGroup.disable(); this.updateFormGroup = null; } // todo: 31.3.18 /** * @return {?} */ save() { return __awaiter$2(this, void 0, void 0, function* () { if (this.updateFormGroup.dirty) { /** @type {?} */ const user = this.auth.auth.currentUser; // user.updateProfile() // user.updateEmail() console.log('form = ', this.updateFormGroup); /** @type {?} */ const snackBarMsg = []; try { if (this.updateNameFormControl.dirty) { yield user.updateProfile({ displayName: this.updateNameFormControl.value, photoURL: null }); snackBarMsg.push(`your name has been update to ${user.displayName}`); } if (this.updateEmailFormControl.dirty) { yield user.updateEmail(this.updateEmailFormControl.value); snackBarMsg.push(`your email has been update to ${user.email}`); } if (this.updatePhoneNumberFormControl.dirty) { yield user.updatePhoneNumber(this.updatePhoneNumberFormControl.value); console.log('phone number = ', this.updatePhoneNumberFormControl.value); snackBarMsg.push(`your phone number has been update to ${user.phoneNumber}`); } yield this._fireStoreService.updateUserData(this.authProcess.parseUserInfo(user)); } catch (error) { error.message ? this.snackBar.open(error.message, 'Ok') : this.snackBar.open(error, 'Ok'); console.error(error); console.error(error.code); console.error(error.message); } if (snackBarMsg.length > 0) { this.snackBar.open(snackBarMsg.join('\\n'), 'Ok'); } // this.updateFormGroup.reset(); } this.editMode = false; }); } /** * Delete the account of the current firebase user * * On Success, emit the <onAccountDeleted> event and toast a msg!# * Otherwise, log the and toast and error msg! * * @return {?} */ deleteAccount() { return __awaiter$2(this, void 0, void 0, function* () { try { /** @type {?} */ const user = this.auth.auth.currentUser; yield this.authProcess.deleteAccount(); yield this._fireStoreService.deleteUserData(user.uid); this.onAccountDeleted.emit(); this.editMode = false; this.snackBar.open('Your account has been successfully deleted!', 'OK', { duration: 5000 }); } catch (error) { console.log('Error while delete user\'s account', error); this.snackBar.open('Error occurred while deleting your account!', 'OK', { duration: 5000 }); } }); } } UserComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-auth-firebaseui-user', template: ` <div *ngIf="auth.authState| async as user; then authenticated else none"> </div> <ng-template #authenticated> <mat-card *ngIf="auth.user | async as user"> <!--<form [formGroup]="updateFormGroup" >--> <!--card header--> <mat-card-header fxLayout="column" fxLayoutAlign="center center"> <img mat-card-avatar [src]="authProcess?.getUserPhotoUrl()"> <div *ngIf="user.emailVerified; then emailVerified else emailNotVerified"></div> <ng-template #emailVerified> <mat-icon color="primary" matTooltip="email is verified" matTooltipPosition="after"> verified_user </mat-icon> </ng-template> <ng-template #emailNotVerified> <mat-icon color="warn" matTooltip="email is not verified" matTooltipPosition="after"> warning </mat-icon> </ng-template> </mat-card-header> <!--card content--> <mat-card-content *ngIf="editMode; then edit else readonly"> </mat-card-content> <ng-template #edit> <form [formGroup]="updateFormGroup" (submit)="save()"> <mat-card-content fxLayout="column" fxLayoutAlign="center center"> <div fxLayoutAlign="center"> <button mat-raised-button color="warn" class="edit-button" (click)="changeEditMode()"> cancel </button> </div> <!--name--> <mat-form-field class="full-width" [appearance]="appearance"> <mat-label>Name</mat-label> <input matInput placeholder="Name" [formControl]="updateNameFormControl" [value]="user.displayName"> <mat-icon matSuffix>person</mat-icon> <mat-hint align="end" aria-live="polite"> {{updateNameFormControl.value.length}} / 25 </mat-hint> <mat-error *ngIf="updateNameFormControl.hasError('required')"> Name is required </mat-error> </mat-form-field> <!--email--> <mat-form-field class="full-width" [appearance]="appearance"> <mat-label>E-mail</mat-label> <input matInput placeholder="E-mail" [formControl]="updateEmailFormControl" [value]="user.email"> <mat-icon matSuffix>email</mat-icon> <mat-error *ngIf="updateEmailFormControl.hasError('required')"> E-mail is required {{updateEmailFormControl.value}} </mat-error> <mat-error *ngIf="updateEmailFormControl.hasError('pattern')"> Please enter a valid e-mail address {{updateEmailFormControl.value}} </mat-error> </mat-form-field> <!--phone number--> <mat-form-field class="full-width" [appearance]="appearance"> <mat-label>Phone number</mat-label> <input matInput type="number" placeholder="Phone number" [formControl]="updatePhoneNumberFormControl" [value]="user.phoneNumber"> <mat-icon matSuffix>phone</mat-icon> <mat-hint align="end" aria-live="polite"> The phone number is international. Therefore, it should start with a + sign or 00, followed by the country code, - and national number e.g: +49-12345678 or 0041-1234567890 NOTE : the phone number must be a valid phone credential !! </mat-hint> <mat-error *ngIf="updatePhoneNumberFormControl.hasError('pattern')"> Please enter a valid phone number </mat-error> </mat-form-field> </mat-card-content> <mat-card-actions fxLayout="column"> <button mat-button color="primary" type="submit"> Save changes </button> </mat-card-actions> </form> </ng-template> <ng-template #readonly> <div fxLayoutAlign="center"> <button mat-raised-button color="primary" class="edit-button" (click)="changeEditMode()"> edit </button> </div> <!--name--> <mat-form-field class="full-width" [appearance]="appearance"> <mat-label>Name</mat-label> <input matInput placeholder="Name" [value]="user.displayName" [disabled]="!editMode"> <mat-icon matSuffix color="primary">person</mat-icon> </mat-form-field> <!--email--> <mat-form-field class="full-width" [appearance]="appearance"> <mat-label>E-mail</mat-label> <input matInput placeholder="E-mail" [value]="user.email" [disabled]="!editMode"> <mat-icon matSuffix color="primary">email</mat-icon> </mat-form-field> <!--phone number--> <mat-form-field class="full-width" [appearance]="appearance"> <mat-label>Phone number</mat-label> <input matInput placeholder="Phone number" [value]="user.phoneNumber" [disabled]="!editMode"> <mat-icon matSuffix color="primary">phone</mat-icon> </mat-form-field> <mat-card-actions fxLayout="column"> <button mat-button color="primary" (click)="auth.auth.signOut()">Sign out</button> <button mat-button color="warn" (click)="deleteAccount()">Delete account</button> </mat-card-actions> </ng-template> </mat-card> </ng-template> <ng-template #none> <mat-card class="none-card" fxLayout="row" fxLayoutAlign="center center"> <mat-card-content fxLayout="row" fxLayoutAlign="center center"> <mat-icon color="accent">warning</mat-icon> <span>You are not logged in!</span> </mat-card-content> </mat-card> </ng-template> `, styles: [` .edit-button{margin:1rem}.full-width{width:100%}.cut-text{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.none-card{min-height:430px}.none-card span{font-size:24px;text-align:center;color:rgba(0,0,0,.54)} `] },] }, ]; /** @nocollapse */ UserComponent.ctorParameters = () => [ { type: AngularFireAuth }, { type: AuthProcessService$$1 }, { type: FirestoreSyncService }, { type: MatSnackBar } ]; UserComponent.propDecorators = { editMode: [{ type: Input }], appearance: [{ type: Input }], onAccountDeleted: [{ type: Output }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** @enum {string} */ const Theme = { DEFAULT: 'default', CLASSIC: 'classic', STROKED: 'stroked', FAB: 'fab', MINI_FAB: 'mini-fab', RAISED: 'raised', }; /** @enum {string} */ const Layout = { ROW: 'row', COLUMN: 'column', }; class AuthProvidersComponent { /** * @param {?} authProcess * @param {?} _iconRegistry * @param {?} _sanitizer */ constructor(authProcess, _iconRegistry, _sanitizer) { this.authProcess = authProcess; this._iconRegistry = _iconRegistry; this._sanitizer = _sanitizer; // theme: string = Theme.DEFAULT; this.layout = Layout.ROW; this.providers = AuthProvider$$1.ALL; // google, facebook, twitter, github // google, facebook, twitter, github this.themes = Theme; this.authProvider = AuthProvider$$1; _iconRegistry .addSvgIcon('google', _sanitizer.bypassSecurityTrustResourceUrl('/assets/mdi/google.svg')) .addSvgIcon('google-colored', _sanitizer.bypassSecurityTrustResourceUrl('/assets/google.svg')) .addSvgIcon('facebook', _sanitizer.bypassSecurityTrustResourceUrl('/assets/mdi/facebook.svg')) .addSvgIcon('twitter', _sanitizer.bypassSecurityTrustResourceUrl('/assets/mdi/twitter.svg')) .addSvgIcon('github', _sanitizer.bypassSecurityTrustResourceUrl('/assets/mdi/github-circle.svg')) .addSvgIcon('phone', _sanitizer.bypassSecurityTrustResourceUrl('/assets/phone.svg')); } } AuthProvidersComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-auth-firebaseui-providers', template: ` <div [ngSwitch]="theme"> <!--default icon buttons--> <div *ngSwitchDefault [fxLayout]="layout" fxLayout.xs="column" [fxLayoutAlign]="layout == 'row' ? 'space-around center' : 'stretch'"> <button *ngIf="providers === authProvider.ALL || providers.includes(authProvider.Google)" mat-button [ngClass.xs]="{'space-full-xs':true}" (click)="authProcess.signInWith(authProvider.Google)"> <mat-icon svgIcon="google-colored"></mat-icon> Google </button> <button *ngIf="providers === authProvider.ALL || providers.includes(authProvider.Facebook)" mat-button class="facebook-filled" [ngClass.xs]="{'space-full-xs':true}" (click)="authProcess.signInWith(authProvider.Facebook)"> <mat-icon svgIcon="facebook"></mat-icon> Facebook </button> <button *ngIf="providers === authProvider.ALL || providers.includes(authProvider.Twitter)" mat-button class="twitter-filled" [ngClass.xs]="{'space-full-xs':true}" (click)="authProcess.signInWith(authProvider.Twitter)"> <mat-icon svgIcon="twitter"></mat-icon> Twitter </button> <button *ngIf="providers === authProvider.ALL || providers.includes(authProvider.Github)" mat-button [ngCl