IONIC 4 - Angular / Firestore

IONIC 4 - Angular / Firestore

我遇到了有关身份验证和用户配置文件的问题。 我正在使用 ionic v4 / angular 和 firestore。 目前我可以通过电子邮件和密码登录,但是当我想进入配置文件以获取此用户数据时,我面对的是一个空白页面。

这是我的 user.service.ts

import { Injectable } from '@angular/core'
import { AngularFireAuth } from '@angular/fire/auth'
import { first } from 'rxjs/operators'
import { auth } from 'firebase/app'

interface user {
    username: string,
    uid: string
}

@Injectable()
export class UserService {
    private user: user

    constructor(private afAuth: AngularFireAuth) {

    }

    setUser(user: user) {
        this.user = user
    }

    getUsername(): string {
        return this.user.username
    }

    reAuth(username: string, password: string) {
        return this.afAuth.auth.currentUser.reauthenticateWithCredential(auth.EmailAuthProvider.credential(username, password))
    }

    updatePassword(newpassword: string) {
        return this.afAuth.auth.currentUser.updatePassword(newpassword)
    }

    updateEmail(newemail: string) {
        return this.afAuth.auth.currentUser.updateEmail(newemail)
    }

    async isAuthenticated() {
        if(this.user) return true

        const user = await this.afAuth.authState.pipe(first()).toPromise()

        if(user) {
            this.setUser({
                username: user.email.split('@')[0],
                uid: user.uid
            })

            return true
        }
        return false
    }

    getUID(): string {
        return this.user.uid
    }
}

这是我的login.page.ts

export class LoginPage implements OnInit {

    username: string = ""
    password: string = ""

    constructor(public afAuth: AngularFireAuth, public user: UserService, public router: Router) { }

    ngOnInit() {
    }

    async login() {
        const { username, password } = this
        try {
            // kind of a hack. 
            const res = await this.afAuth.auth.signInWithEmailAndPassword(username, password)

            if(res.user) {
                this.user.setUser({
                    username,
                    uid: res.user.uid,
                })
                console.log(res.user.uid)
                this.router.navigate(['/home-results'])
            }

        } catch(err) {
      alert("Bad Credentials")
            console.dir(err)
            if(err.code === "auth/user-not-found") {
                console.log("User not found")
            }
        }
    }
}

profil.page.ts

@Component({
  selector: 'app-profil',
  template: `
  <!-- User logged in -->
  <ng-template #authenticated>
  <div *ngIf="auth.user | async as user">
    <h3>Howdy, {{ user.username }}</h3>
    <p>UID: {{ user.uid }}</p>
    <!-- <p>Favorite Color: {{ user.countryBirth }} </p> -->
    <button (click)="auth.signOut()">Logout</button>
  </div>
  </ng-template>`,


  styleUrls: ['./profil.page.scss'],
})
export class ProfilPage {

  constructor(public auth: AuthService ,public user:UserService){}

}

而不是使用 Router 尝试使用 NavController

import { NavController } from '@ionic/angular';

constructor(private navCtrl: NavController) {
   if (this.user) {
     this.navCtrl.navigateRoot('/home-results');
   }
}

我不确定 Firebase 身份验证将在多大程度上维护用户个人资料(尽管像 Facebook 这样的第三方身份验证会为身份验证对象提供用户详细信息,但您无法更新这些信息)。您可能希望通过用户集合中的用户文档维护 FireStore 中的用户配置文件,利用 Firebase UID 作为文档的属性之一。这样您就可以存储特定于您的应用程序需求的自定义用户配置文件数据。

AngularFire docs 可以帮助您设置集合并向您展示如何 get/set 集合中的文档。但具体关于如何获取用户身份验证数据的问题,您可以订阅 Firebase Authentication authstate,它将为您提供所有用户的身份验证信息,包括电子邮件和 UID。

user.service.ts

user: any = null;

constructor(private afAuth: AngularFireAuth){  }

init(){
   this.afAuth.authState.subscribe(auth => {
     this.user = auth;
   });
}

app.component.ts

constructor(public userService: UserService){
  this.userService.init();
}

我有一个 Ionic Firebase Auth starter repo,您可能也会发现它对您有用以供参考。

希望对您有所帮助。

我用以下内容替换当前行:

this.usersCollection = afs.collection<User>('users'+ firebase.auth().currentUser.uid);

而不是

this.usersCollection = afs.collection<User>('users/');

但 html 仍然空白

终于找到并解决了我的问题。

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