0
votes

I'm having a hard time getting my angular 4 service authObj working which implements firebase.auth() and should return the current logged in status (true/false).

The service is part of a feature module (authenticationModule) that is imported into my appModule.

authenticationModule

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';

import { AngularFireAuthModule} from 'angularfire2/auth';

import { authObjService } from './service/authObj';
import {loginButton} from './directive/login-button/login-button'
import {logoutButton} from './directive/logout-button/logout-button'
import {userLoginState} from './directive/user-login-state/user-login-state'


@NgModule({
  declarations: [loginButton, logoutButton, userLoginState],
  imports: [CommonModule, AngularFireAuthModule],
  exports: [loginButton, logoutButton, userLoginState]
})

export class authenticationModule {
    static forRoot(): ModuleWithProviders {
        return {
            ngModule: authenticationModule,
            providers: [authObjService]
        }
    }
}

appModule

import 'hammerjs';

import {NgModule} from '@angular/core';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {RouterModule}  from '@angular/router';

import * as firebase from 'firebase/app';

import {FirebaseConfig} from '../configuration/firebaseConfig';

import {dealsModule} from '../deals/module';
import {authenticationModule} from '../authentication/module';

import {appRoot} from './component/app-root/app-root';
import {appLogin} from './component/app-login/app-login';
import {appRoutes} from './routes';

firebase.initializeApp(FirebaseConfig);

@NgModule({
    declarations: [
        appRoot,
        appLogin,
    ],
    imports: [
        RouterModule.forRoot(appRoutes),
        dealsModule,
        authenticationModule.forRoot(),
        BrowserAnimationsModule,
    ],
    providers: [],
    bootstrap: [appRoot]
})
export class appModule {
}

The service, authObj, has a lot going on:

  • login()
  • logout()
  • userIsLoggedIn()
  • ...

authObj

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

import {appSettings} from '../../configuration/appSettings'
import {authObjModel} from '../model/authObj';

import * as firebase from 'firebase/app';

@Injectable()
export class authObjService {

    private userLoginStatus:boolean;

    currentUser = new authObjModel();
    provider = new firebase.auth.GoogleAuthProvider();

    constructor(public router: Router) {

        this.observeUserState();

    }

    observeUserState(){
        firebase.auth().onAuthStateChanged(user => {

            if(user){
                this.setCurrentUser(user);
                this.userLoginStatus = true;
                this.router.navigate([appSettings.userLoginRedirectRoute]);
            } else {
                this.userLoginStatus = false;
                this.router.navigate([appSettings.userLogoutRedirectRoute]);
            }
        });

    }

    getCurrentUser() {
        //return this.firebaseAuth;
    }

    userIsLoggedIn(){
        return this.userLoginStatus;
    }

    login(){
        firebase.auth().signInWithPopup(this.provider);
    }

    logout(){
        firebase.auth().signOut();
    }

    setCurrentUser(user){

        if(user){
            this.currentUser.uid = user.uid;
            this.currentUser.displayName = user.displayName;
            this.currentUser.email = user.email;
            this.currentUser.photoUrl = user.photoURL;
        } else {
            this.currentUser = null;
        }


    }

}

Everything works, except, the boolean that should return the login status of the user. This 'always' returns undefined. This should work because i set the userLoginStatus to true 'before' i redirect the user to this.router.navigate([appSettings.userLoginRedirectRoute]);

userIsLoggedIn(){
    return this.userLoginStatus;
}

Additional information

When login is successful, this.router.navigate([appSettings.userLoginRedirectRoute]) is called and the user gets redirect to /deals/deals-add/ which is part of another feature module: dealsModule

dealsModule

import 'hammerjs';

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule }  from '@angular/router';
import {MdMenuModule, MdButtonModule} from '@angular/material';

import {authenticationModule} from '../authentication/module';

import { dealsPage } from './component/deals-page/deals-page';
import { dealsAdd } from './component/deals-add/deals-add';
import { dealsManage } from './component/deals-manage/deals-manage';
import { dealsRoutes } from './routes';

@NgModule({
    declarations: [
        dealsPage,
        dealsAdd,
        dealsManage,
    ],
    imports: [
        CommonModule,
        MdMenuModule,
        MdButtonModule,
        authenticationModule.forRoot(),
        RouterModule.forChild(dealsRoutes),
    ],
    providers: [],
    exports:[]
})
export class dealsModule {}

The html of the dealsPage component has an $ngIf that calls a method that inturn calls the authObj service which should return the current user login state.

<div *ngIf="getUserState()">should show this text</div> 

dealsPage component

import { Component, OnInit } from '@angular/core';

import {authObjService} from '../../../authentication/service/authObj'

@Component({
    selector: 'deals-page',
    templateUrl: './deals-page.html',
    styleUrls: ['./deals-page.css'],
    providers:[authObjService]
})
export class dealsPage implements OnInit{

    constructor(public authObj:authObjService){}

    ngOnInit(){
        this.getUserState();
    }

    getUserState(){

        return this.authObj.userIsLoggedIn();

    }

}

What am i missing in this setup?

Thx for you're insights...

1

1 Answers

0
votes

Firebase has an Observable to subscribe on for changes on the Auth object.

constructor(private afAuth: AngularFireAuth)
//something to pass true or false
isLoggedIn: boolean;

this.afAuth.auth.signInWithEmailAndPassword(email, password).then(result => {
      this.afAuth.auth.onAuthStateChanged((user) => {

        if (user) {
          isLoggedIn(true);
        } else {
          isLoggedIn(false);
        }

      });
    }).catch(function (error) {
      // Handle Errors here.
      let errorCode = error.name;
      if (errorCode === 'auth/wrong-password') {
      } else {
        console.log(error.message);
      }
    });
  }

Firebase keeps track on the app, the only thing you have to do is check if you get an Auth object. From the Firebase API