【问题标题】:Firebase does not save userdata to Firestore after creating user with FirebaseAuthentication - Angular 9使用 FirebaseAuthentication 创建用户后,Firebase 不会将用户数据保存到 Firestore - Angular 9
【发布时间】:2020-10-10 16:00:04
【问题描述】:

我有一个 Angular 9 网络应用程序,到目前为止,我已经使它与 Firestore 配合得非常好。我有一个添加用户的表单,它可以正确地将用户保存到 Firestore,但没有将其添加到 Authenticated users,当我解决以下问题时,添加功能将被删除。

users.component.ts:

this.userService.addUser(user);

在 userService 中我调用:

 async addUser(user: User) {
      await this.firestore.collection('users').doc(user.email).set(user);
 }

问题是,当我想用​​ FirebaseAuthentication 注册新用户时,用户数据没有保存在 users 集合中。当用户点击 register.component.ts 中的 Register 时,我调用:

   register() {
        this.authenticationService
            .register(this.form.controls['email'].value, this.form.controls['password'].value)
            .then(() => {
                this.userService.addUser({
                    nickname: this.form.controls['nickname'].value,
                    email: this.form.controls['email'].value,
                    role: 'Customer',
                });
            })
            .catch((error) => {
                console.log(error);
            });
    }

authenticationService.ts中的注册方法:

    register(email: string, password: string) {
        return this.angularFireAuth.auth.createUserWithEmailAndPassword(email, password);
    }

我尝试了不同的方法,使用 Promises、async / await、直接从 authenticationService.ts 中的 register 方法调用、使用 collection('users').add 而不是 set、使用我得到的 uid作为文档 uid 而不是电子邮件的响应。

我倾向于认为有某种回滚机制,因为我订阅了data$:

this.firestore
    .collection<User>(this.path)
    .snapshotChanges()
    .pipe(
        takeUntil(this.destroy$),
        map((items) => {
            return items.map((item) => {
                const data = item.payload.doc.data() as User;

                return {
                    ...data,
                };
            });
        })
    )
    .subscribe((data) => {
        this.users$.next(data);
    });

在 register.component.ts ngOnInit:

  this.userService.users$.subscribe((data) => {
        console.log(data);
  });

这给了我一些见解:

主题立即触发两次,4个元素,然后3个。

users.component.ts

constructor(private userService: UserService, public dialog: MatDialog) {}

register.component.ts

constructor(
    private userService: UserService,
    private formBuilder: FormBuilder,
    private authenticationService: AuthenticationService
) {}

两个组件都是同一个模块的一部分,但由于某种原因,如果我导航到 users.component.ts 然后到 register.component.ts 保存用户 有效!它会同时添加到 Authenticated users 和 Firestore 用户集合中。

我在任何时候都没有收到任何错误。

所以我真的不知道是什么导致它的行为不同,但我需要它从 register.component.ts 开始工作,而无需先导航到 users.component.ts。

编辑:

我的规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // This rule allows anyone on the internet to view, edit, and delete
    // all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // your app will lose access to your Firestore database
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2020, 8, 6);
    }
  }
}

【问题讨论】:

    标签: javascript firebase google-cloud-firestore firebase-authentication angularfire2


    【解决方案1】:

    如果您看到这样的回滚,通常意味着服务器根据您为数据库指定的安全规则拒绝了写入操作。所以看起来用户没有写权限。

    您必须将security rules of the database 修改为allow the user to write their profile data。

    【讨论】:

    • 我还没有制定任何规则,所以我有默认规则,只有日期作为限制。规则版本='2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { 允许读取,写入:如果 request.time
    【解决方案2】:

    您必须手动将创建的用户添加到您的收藏中。 在 createUserWithEmailAndPassword() 成功执行后,您应该调用一个自定义函数来获取用户对象并将其保存到 Firestore。 示例:

    register(email: string, password: string) {
        let rs = this.angularFireAuth.auth.createUserWithEmailAndPassword(email, password);
        return this.saveUser(rs.user)
    }
    saveUser(user){
        const userRef: AngularFirestoreDocument<User> = this.angularFistore.doc(`users/${user.email}`);
    
        userRef.get().subscribe(snapDoc =>{
          if(!snapDoc.exists){
            const data; //Initialize 
            //do anything else
            return userRef.set(data, { merge: true })
          })
    }
    

    【讨论】:

    • 这似乎行得通。愿意给出更详细的解释,为什么它需要显式调用而不是简单的 add / set in then 回调?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-17
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 2017-03-09
    • 2021-06-21
    相关资源
    最近更新 更多