AngularFire / Firebase - checking the authentication state

ε祈祈猫儿з 提交于 2019-12-11 01:47:18

问题


Note: I'm new to all of this, please excuse what might be obvious. Any help is massively appreciated :)

What I have

  • An auth service to log in and out
  • An album service to fetch items based on user id
    • albumList > UserId > albumKey
  • In my album list service I query the path 'albumList > userId'
  • Once I log in, this works perfectly, and only the results based on the matched query of the above are returned

Issues

  • If I were to copy and paste the URL of 'localhost:4200/albums' into another tab, the console reads

Uncaught (in promise): TypeError: Cannot read property 'uid' of null

  • As a result, nothing loads and the URL pasted isn't maintained

Questions

  • Do I need to add a user observable in all my components?
  • How do I ensure that the user state is checked before loading my data?
  • Is it possible to just use my Auth.Service as a reference point for all other components?

My Auth Service

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

import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthService {
  user: Observable<firebase.User>;


  constructor(
    private firebaseAuth: AngularFireAuth,
    private router: Router) {
    this.user = firebaseAuth.authState;
  }

  login(email: string, password: string) {
    this.firebaseAuth
      .auth
      .signInWithEmailAndPassword(email, password)
      .then(value => {
        console.log('Nice, it worked!');
        console.log(this.firebaseAuth.auth.currentUser.uid);

        this.router.navigate(['/albums'])
      })
      .catch(err => {
        console.log('Something went wrong:', err.message);
      });
  }

  logout() {
    this.firebaseAuth
      .auth
      .signOut();
  }


}

My Album List Service

note: If i remove the albumList query with the user id on the end (commented out query), I can copy and paste the URL into a new tab and the URL is maintained (url.com/albums). However, any data won't be filtered by the user key first.

import { Injectable } from '@angular/core';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';

import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class ProjectsListService {
  albumList: FirebaseListObservable<any[]>;
  user: Observable<firebase.User>;

  constructor(
    private database: AngularFireDatabase,
    private firebaseAuth: AngularFireAuth) {

    //this.albumList = database.list('/albumList');
    this.albumList = database.list('/albumList/' + this.firebaseAuth.auth.currentUser.uid);
    //console.log(this.firebaseAuth.auth.currentUser.uid);
  }

  getAlbumList() {
    return this.albumList;
    }


}

回答1:


Questions

  • Do I need to add a user observable in all my components?

Yes, you are working with async data all the time, you need to subscribe to the changes coming from the firebase

  • How do I ensure that the user state is checked before loading my data?

It seems that you are also relatively new to angular, it might be harder for you to learn everything at once. You should check the Router tutorial, more exactly the module 5 Route Guards.

  • Is it possible to just use my Auth.Service as a reference point for all other components?

Yes, that's entirely up to you and it's a very common thing.

As for the Type error, you are trying to accessing a value that doesn't exist when you initialize your app, since you get that asynchronously you need to subscribe to the authState

import { Injectable } from '@angular/core';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';

import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class ProjectsListService {
  albumList: FirebaseListObservable<any[]>;
  user: Observable<firebase.User>;

  constructor(
    private database: AngularFireDatabase,
    private firebaseAuth: AngularFireAuth
  ) {
      firebaseAuth.authState.subscribe(user => {
        console.log(user);
        if (user) {
          this.albumList = database.list('/albumList/' + user.uid);
        }
      })
  }

  getAlbumList() {
    return this.albumList;
  }
}

Edit

The previous code didn't work, because when you first run your app, the albumList is an empty var, that's why after you navigate everything works fine, because after that it's already initialised and you can subscribe to it.

So because you depend on the auth state you should be subscribing to your albumList on your components instead. Why? Because if your user for some reason logs out, you also hide the information.

So instead of using ProjectsListService on your component you will do something like this:

import { Component } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database'

@Component({
  selector: 'your-component',
  template: `<ul><li *ngFor="let album of albumList | async">{{ todo.text }}</li></ul>`
})
export class YOURComponent {
  albumList: FirebaseListObservable<any[]>;

  constructor(
    private fAuth: AngularFireAuth,
    private database: AngularFireDatabase
  ) {
    fAuth.authState.subscribe(user => {
      if (user) {
        this.albumList = database.list('/albumList/' + user.uid);
        return;
      }
      this.albumList = null;
    })
  }
}


来源:https://stackoverflow.com/questions/44928646/angularfire-firebase-checking-the-authentication-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!