Firebase Authentication with Angular

Viewed 292

What I'm Using

  • Angular 5
  • AngularFire5
  • Firebase & Firestore

What I'm Trying to Achieve

I am trying to make a simple authentication/login & registration system. I actually have one already made, though I am running into some issues, and I want to make sure I am going about the best way to setup authentication.

What I have So Far

auth.service.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AngularFireAuth } from 'angularfire2/auth';

@Injectable()
export class AuthService {

  authState: any = null;
  email = '';
  username = '';
  password = '';
  errorMessage = '';
  error: {name: string, message: string} = {name: '', message: ''};

  constructor(private afAuth: AngularFireAuth, private router: Router) {
    this.afAuth.authState.subscribe((auth) => {
      this.authState = auth
    });
  }
  get isUserEmailLoggedIn(): boolean {
    if (this.authState !== null) {
      return true
    } else {
      return false
    }
  }
  get currentUser(): any {
    return (this.authState !== null) ? this.authState : null;
  }
  get currentUserId(): string {
    return (this.authState !== null) ? this.authState.uid : ''
  }
  get currentUserName(): string {
    return this.authState['email']
  }
  signUpWithEmail(email: string, password: string) {
    return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
      .then((user) => {
        this.authState = user
      })
      .catch(error => {
        console.log(error)
        throw error
      });
  }
  loginWithEmail(email: string, password: string) {
    return this.afAuth.auth.signInWithEmailAndPassword(email, password)
      .then((user) => {
        this.authState = user
      })
      .catch(error => {
        console.log(error)
        throw error
      });
  }
  signOut(): void {
    this.afAuth.auth.signOut();
    this.router.navigate(['/'])
  }
  onSignUp(): void {
    this.clearErrorMessage()
    if (this.validateForm(this.email, this.password)) {
      this.signUpWithEmail(this.email, this.password)
        .then(() => {
          this.router.navigate(['/home'])
        }).catch(_error => {
          this.error = _error
          this.router.navigate(['/register'])
        })
    }
  }
  onLoginEmail(): void {
    this.clearErrorMessage()
    if (this.validateForm(this.email, this.password)) {
      this.loginWithEmail(this.email, this.password)
        .then(() => this.router.navigate(['/home']))
        .catch(_error => {
          this.error = _error
          this.router.navigate(['/login'])
        })
    }
  }
  validateForm(email: string, password: string): boolean {
    if (email.length === 0) {
      this.errorMessage = 'Please enter Email!'
      return false
    }
    if (password.length === 0) {
      this.errorMessage = 'Please enter Password!'
      return false
    }

    if (password.length < 6) {
      this.errorMessage = 'Password should be at least 6 characters!'
      return false
    }
    this.errorMessage = ''
    return true

  }
  clearErrorMessage() {
    this.errorMessage = '';
    this.error = {name: '', message: ''};
  }
}

link.service.ts

import { Injectable, OnInit } from '@angular/core';
import { AuthService } from './auth.service';
import { AngularFirestore, AngularFirestoreDocument, AngularFirestoreCollection } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

export interface Link { uid: string; url: string; shortURL: string; clicks: number }

@Injectable()
export class LinkService implements OnInit {
  url: string;
  shortURL: string;
  showAlert: boolean;
  links: Observable<any>;

  constructor(public authService: AuthService, private afs: AngularFirestore) {
        this.links = afs.collection('Links').valueChanges();
  }
  ngOnInit() {
  }
  createShortURL() {
    var text = '';
    var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var length = 6;

    for(var i = 0; i < length; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return this.shortURL = text;
  }
  addLink() {
    if (this.authService.isUserEmailLoggedIn) {
      this.createShortURL();
      this.afs.collection('Links').doc(this.shortURL).set({
        'uid': this.authService.currentUserId,
        'url': this.url,
        'shortURL': this.shortURL,
        'clicks': 0
      });
      this.clearFields();
      this.showAlert = false;
    } else {
      this.showAlert = true;
    }
  }
  clearFields() {
    return this.url = '';
  }
}

Where I'm Stuck

With the information provided. I am trying to get the currentUserID in the link.service.ts though it is coming back as undefined. However with the addLink() function, this.authService.isUserEmailLoggedIn works perfectly fine, and Im not sure why it is not returning the correct value otherwise.

2 Answers

You need to get id like this.

 this.items = this.itemCollection.snapshotChanges().map(changes => {
          return changes.map(a => {
            const data = a.payload.doc.data();
            data.id = a.payload.doc.id;
            return data;
          });
        });

currentUserId() is a function you should use 'uid': this.authService.currentUserId(),

Related