Etosticity
Etosticity

Reputation: 237

Get User UID from Firebase via Service

Forgive me, I don't know RxJS that well.

I would like to know, how to extract a User's UID from Firebase as a Service that I've created. And implement it inside a component.

Here's the code.

Filename: auth.service.ts

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

import * as firebase from 'firebase/app';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';

import 'rxjs/add/operator/switchMap';
import { Observable } from 'rxjs/Observable';

declare var $: any;
declare var jQuery: any;

interface User {
    uid: string;
    email: string;
    photoURL?: string;
    displayName?: string;
}

@Injectable()
export class AuthService {

    user: Observable<User>;

    constructor(private afAuth: AngularFireAuth, private afs: AngularFirestore, private router: Router) {
        this.user = this.afAuth.authState.switchMap(user => {
            if (user) {
                return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
            } else {
                return Observable.of(null);
            }
        })
    }

    googleLogin() {
        const provider = new firebase.auth.GoogleAuthProvider();
        return this.oAuthLogin(provider);
    }

    githubLogin() {
        const provider = new firebase.auth.GithubAuthProvider();
        return this.oAuthLogin(provider);
    }

    private oAuthLogin(provider) {
        return this.afAuth.auth.signInWithPopup(provider).then((credential) => {
            this.updateUserData(credential.user)
        }).catch((err) => {
            if (err.code === 'auth/account-exists-with-different-credential') {
                ...
            } else if (err.code === 'auth/internal-error') {
                ...
            } else {
                ...
            }
        })
    }

    private updateUserData(user) {
        const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`);

        const data: User = {
            uid: user.uid,
            email: user.email,
            displayName: user.displayName,
            photoURL: user.photoURL
        }

        return userRef.set(data);
    }

    signOut() {
        ...
    }

    deleteUser() {
        ...
    }

}

Additional Info:

@angular/animations: 4.2.4
@angular/common: 4.2.4
@angular/compiler: 4.2.4
@angular/core: 4.2.4
@angular/forms: 4.2.4
@angular/http: 4.2.4
@angular/platform-browser: 4.2.4
@angular/platform-browser-dynamic: 4.2.4
@angular/router: 4.2.4
angular2-materialize: 15.1.10
angularfire2: 5.0.0-rc.3
core-js: 2.4.1
firebase: 4.6.1
font-awesome: 4.7.0
hammerjs: 2.0.8
jquery: 2.2.4
materialize-css: 0.100.2
rxjs: 5.4.2
zone.js: 0.8.14

It would also be great if I can get all properties as well, would be handy.

Any ideas, suggestions would be of great help.

Upvotes: 0

Views: 4776

Answers (2)

Ryann Galea
Ryann Galea

Reputation: 307

I prefer using a Behavioursubject, this is how I currently have my Auth.Service setup.

Note that on user registration I will save the users UID back into the user's details in the firebase, so when i pull all that users data, it has everything i need.

I can use this.as.user.uid to get that specific detail. or any other.

      @Injectable()
      export class AuthService {

        private userSubject: BehaviorSubject<any> = new BehaviorSubject<any>(false);

        constructor(private afAuth: AngularFireAuth) {
          this.afAuth.authState
            .switchMap(user => user ? this.fb.user(user.uid).valueChanges() : Observable.of(false))
            .subscribe(userData => this.userSubject.next(userData));
        }

        get user() {
          return this.userSubject.value;
        }

        get loggedIn() {
          return !!this.userSubject.value;
        }

        userObservable() {
          return this.userSubject.asObservable();
        }

And then in my other components i can always wait on user data like this.

 this.as.userObservable()
   .filter(res => res)
   .subscribe(res => this.user = res)

Upvotes: 3

aevansme
aevansme

Reputation: 105

Below is a copy of my Auth Service. I have two properties "currentUserId()" and "currentUserDisplayName()".

  user: Observable<firebase.User>;
  private userDetails: firebase.User = null;

  constructor(private firebaseAuth: AngularFireAuth, private router: Router) {
     this.user = firebaseAuth.authState;
     this.user.subscribe((user) => {
        if (user) {
          this.userDetails = user;
        }
        else {
          this.userDetails = null;
        }
     });
  } 

    // Returns true if user is logged in
 get authenticated(): boolean {
  // consider changing to 'return this.userDetails != null'
    if (this.userDetails == null ) {
       return false;
    } else {
       return true;
    }
  }

  // Returns current user UID
  get currentUserId(): string {
     return this.authenticated ? this.userDetails.uid : '';
  }

  // Returns current user display name or Guest
  get currentUserDisplayName(): string {
      return this.userDetails.displayName || this.userDetails.email; 
  }

So to use this in a component just inject your authSvc and ...

this.authSvc.currentUserId

Upvotes: 0

Related Questions