Reputation: 237
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
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
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