2
votes

I have created a callable Cloud Function to read data from Firebase and send back the results to the client, however, only "null" is being returned to the client.

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

    if (context.auth && data) {
        return admin.firestore().doc("users/" + context.auth.uid).get()

            .then(function (doc) {
                return { doc.data() };
            })

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

});
2
Sounds like it's time to add some debug logging to figure out exactly what's going on.Doug Stevenson
@Tor Learner have you figured out?B L Λ C K
same problem with me, but i have solved follow this bro, stackoverflow.com/questions/54297558/…im frontend

2 Answers

1
votes

I just reproduced your case connecting from a Cloud Function with a Firestore database and retriving data. As I can see you are trying to access the field in a wrong way when you are using "users/" + context.auth.uid, the method can't find the field so its returning a null value.

I just followed this Quickstart using a server client library documentation to populate a Firestore database and make a Get from it with node.js.

After that i followed this Deploying from GCP Console documentation in order to deploy a HTTP triggered Cloud Function with the following function

exports.helloWorld = (req, res) => {  
  firestore.collection('users').get()
  .then((snapshot) => {
    snapshot.forEach((doc) => {
      console.log(doc.id, '=>', doc.data().born);
      let ans = {
        date : doc.data().born
      };
      res.status(200).send(ans);
    });
  })

And this is returning the desired field.

You can take a look of my entire example code here

0
votes

This is because you are making a query from a database firestore, however the cloud support team has made it very cool to protect your applications from data leakages and so in a callable function as the name suggest you can only return data you passed to the same callable function through the data parameter and nothing else. if you try to access a database i suggest you use an onRequest Function and use the endpoint to get you data. that way you not only protect your database but avoid data and memory leakage. examples of what you can return from a callable function

exports.sayHello = functions.https.onCall((data, context) => {
  const name = data.name;
  console.log(`hello ${name}`);
  return `It was really fun working with you ${name}`;
});

first create a function in your index.js file and accept data through the data parameter but as i said you can only return data you passed through the data parameter.

now call the function this is in the frontend code (attach an event listener to a button or something and trigger it

/* jsut say hello from firebase */
callButton.addEventListener('click', () => {
    const sayHello = firebase.functions().httpsCallable('getAllUsers');
    sayHello().then(resutls => {
        console.log("users >>> ", resutls);
    });
});

you can get your data using an onRequest like so

    /* get users */
exports.getAllUsers = functions.https.onRequest((request, response) => {
  cors(request, response, () => {
    const data = admin.firestore().collection("users");
    const users = [];
    data.get().then((snapshot) => {
      snapshot.docs.forEach((doc) => {
        users.push(doc.data());
      });
      return response.status(200).send(users);
    });
  });
});

using a fetch() in your frontend code to get the response of the new onRequest function you can get the endpoint to the function in your firebase console dashboard.

but not that to hit the endpoint from your frontend code you need to add cors to your firebase cloud functions to allow access to the endpoint. you can do that by just adding this line to the top of your index.js file of the firebase functions directory

const cors = require("cors")({origin: true});