仅在functions.auth.user().onCreate完成后如何完成登录 [英] How to complete login only after functions.auth.user().onCreate is finished

查看:54
本文介绍了仅在functions.auth.user().onCreate完成后如何完成登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用firebase函数,并且具有一个在用户创建时添加新集合的函数.问题是有时用户在功能完成之前已登录,因此用户已登录但尚未创建新集合(然后我收到错误消息缺少或权限不足.因为规则无法找到该集合").我该如何处理?

I'm using firebase functions and I have a function which add new collection when user is creating. The problem is sometimes user is logged in before function is done, so user is logged in but new collection is not created yet (and then I have error message 'Missing or insufficient permissions. because a rule cannot find that collection'). How can I handle it?

仅当来自

export const createCollection = functions.auth.user().onCreate(async user => {
  try {
    const addLanguages = await addFirst();
    const addSecondCollection = await addSecond();

    async function addFirst() {
      const userRef = admin.firestore().doc(`languages/${user.uid}`);
      await userRef.set(
        {
          language: null
        },
        { merge: true }
      );

      return 'done';
    }

    async function addSecond() {
      // ...
    }

    return await Promise.all([addLanguages, addSecondCollection]);
  } catch (error) {
    throw new functions.https.HttpsError('unknown', error);
  }
});

完成了吗?因此,谷歌提供者窗口是关闭的,只有在那之后用户才能登录?(并且不要使用setTimeouts等)

is finished? So google provider window is closed and user is logged in only after that? (and don't using setTimeouts etc)

推荐答案

AFAIK无法直接耦合应用程序中隐含的两个过程:

AFAIK it is not possible to directly couple the two processes implied in your application:

  • 一方面,您已经在前端实现了 Google登录流程(即使后端调用了Auth服务),并且
  • 另一方面,您具有在后端 执行的Cloud Function.
  • On one hand you have the Google sign-in flow implemented in your front-end (even if there is a call to the Auth service in the back-end), and;
  • On the other hand you have the Cloud Function that is executed in the back-end.

您遇到的问题来自以下事实: Google登录流程成功后,您的用户已登录到您的应用并尝试阅读云功能要创建的文档.

The problem you encounter comes from the fact that as soon as the Google sign-in flow is successful, your user is signed in to your app and tries to read the document to be created by the Cloud Function.

在某些情况下(例如由于Cloud Function冷启动),在用户登录时尚未创建此文档,从而导致错误.

In some cases (due for example to the Cloud Function cold start) this document is not yet created when the user is signed in, resulting in an error.

一种可能的解决方案是在前端中设置Firestore侦听器,以等待创建此文档,如下所示.请注意,以下代码仅考虑了 addFirst()函数创建的Firestore文档,因为您没有提供有关通过 addSecond()<.

One possible solution would be to set a Firestore listener in your front-end to wait for this document to be created, as follows. Note that the following code only takes into account the Firestore document created by the addFirst() function, since you don't give any details on the second document to be created through addSecond().

firebase.auth().signInWithPopup(provider)
.then(function(result) {
  var token = result.credential.accessToken;
  var user = result.user;  
  //Here we know the userId then we can set a listener to the doc languages/${user.uid}

  firebase.firestore().collection("languages").doc(user.uid)
    .onSnapshot(function(doc) {
       if(doc.exists) {
         console.log("Current data: ", doc.data());
         //Do whatever you want with the user doc
       } else  {
         console.log("Language document not yet created by the Cloud Function");
       }

    });
}).catch(function(error) {
  var errorCode = error.code;
  var errorMessage = error.message;
  var email = error.email;
  var credential = error.credential;
  // ...
});


如上所述,在上面的代码中,我们仅考虑了由 addFirst()函数创建的 first Firestore文档.但是您可能需要等待两个文档创建之后才能从前端读取它们.


As said above, in the above code we only take into account the first Firestore document created by the addFirst() function. But you probably need to wait for the two docs to be created before reading them from the front-end.

因此,您可以按以下方式修改CF:

So, you may modify you CF as follows:

export const createCollection = functions.auth.user().onCreate(async user => {
  try {
    await addFirst();
    await addSecond();
    return null;

    async function addFirst() {
      const userRef = admin.firestore().doc(`languages/${user.uid}`);
      await userRef.set(
        {
          language: null
        },
        { merge: true }
      );
    }

    async function addSecond() {
      // ...
    }

  } catch (error) {
    console.log(error);
    return null;
  }
});

请注意,您无需使用 Promise.all():以下两行已经执行了两次写入Firestore的文档.而且,由于您使用 async/await ,因此第二个文档仅在第一个文档写入后写入.

Note that you don't need to use Promise.all(): the following two lines already execute the two document writes to Firestore. And, since you use async/await the second document is only written after the first one is written.

    const addLanguages = await addFirst();
    const addSecondCollection = await addSecond();

因此,您只需要在第二个文档的路径上设置侦听器,就可以完成!

So you just need to set the listener on the path of the second document, and you are done!

最后,请注意

throw new functions.https.HttpsError('unknown', error);

catch 块中的

是您应该处理可调用云函数错误的方式.在这里,您正在编写后台触发的云函数,您可以只使用 return null;

in your catch block is the way you should handle errors for a Callable Cloud Function. Here, you are writing a background triggered Cloud Function, and you can just use return null;

这篇关于仅在functions.auth.user().onCreate完成后如何完成登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆