简体   繁体   中英

Run Cloud Function to store Firebase Auth'ed user data to Firestore

I've been trying to create a front-end app with Firebase Authentication (Google sign-in) and Firebase Cloud Function which stores the authenticated user data to Firestore.

  1. A user clicks a button to sign in with Google (Firebase Authentication).
  2. The front-end calls Cloud Function ( saveAuthUserData ) after sign-in.
  3. Cloud Function runs to store the authenticated user's profile in Firestore (collection: users ).

The expected Cloud Function (3) is to send an HTTP POST request to Firestore with the user's profile data.

I wrote this public/index.html and functions/index.js (below), but still looking for the way how it should interact with Firebase without any errors, specifically how to send an HTTP POST request from public/index.html to Cloud Function in functions/index.js . Both files are deployed on Firebase Hosting.

public/index.html

import { initializeApp } from "firebase/app";
import { getAuth, signInWithPopup,GoogleAuthProvider } from "firebase/auth";
import { getFirestore, collection, doc, setDoc } from "firebase/firestore";
import { getFunctions, httpsCallable } from "firebase/functions";
const config = {
    apiKey: "xxxxxx",
    authDomain: "yyyyy.web.app",
    projectId: "zzzzzz"
};
const app = initializeApp(config);
const db = getFirestore(app);
const provider = new GoogleAuthProvider();
const auth = getAuth();
const functions = getFunctions();
var btn = document.getElementById("#sign-in-with-google");
btn.addEventListener("click", function() {
    signInWithPopup(auth, provider).then((result) => {
    var credential = GoogleAuthProvider.credentialFromResult(result);
    var user = result.user;
    if(user !== null) {
        var profile = {
            email: user.email,
            name: user.displayName,
            uid: user.uid
        };
        const setAuthUserData = httpsCallable(functions, "setAuthUserData");
        setAuthUserData(profile).then((result) => {
            console.log(result.data);
        });
    }
});

functions/index.js

const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
const fireStore = admin.firestore();

const express = require("express");
const axios = require("axios");
const cors = require("cors");
const app = express();
app.use(cors({ origin: true }));

const setAuthUserData = async (profile) => {
    var isAuthUserSet = false;
    const db = fireStore.collection("users");
    const email = profile.email;
    if(email) {
        const ref = await db.doc(email).set(profile).then(() => {
            isUpdated = true;
      });
    }
  }
  return isUpdated;
}

app.post("/setAuthUserData/", (req, res) => {
  setAuthUserData(req.params.profile).then((response) => res.send(response));
});

const api = functions.https.onRequest(app);
module.exports = { api };

Since you do

const setAuthUserData = httpsCallable(functions, "setAuthUserData");
setAuthUserData(profile).then((result) => {
        console.log(result.data);
    });

in your front-end, you need your Cloud Function to be of type Callable ;

Something along the following lines:

exports.setAuthUserData = functions.https.onCall(async (data, context) => {

    try {
        const userData = data;

        // Do whatever you need with userData, e.g. write to Firestore
        const db = fireStore.collection("users");
        const email = profile.email;

        if (email) {
            const ref = await db.doc(email).set(profile);
        };

        return { isUpdated: true }
    } catch (error) {
        // See https://firebase.google.com/docs/functions/callable#handle_errors
    }

});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM