1

I'm trying to have a Firebase cloud function that returns whether a user has permissions to content. I think it'll be clear how I want it to function based on the code.

Essentially, I'd like to check to make sure the user exists and the content exists before doing the compound query. This is because when I do the double query, it will return the 'this user does not have access to this content' even if the real issue is that the request has the incorrect contentId or userId.

function checkUser(userId) {
  db.collection("users")
    .where("userId", "==", userId)
    .get()
    .then(snapshot => {
      if (snapshot.empty) {
        return true;
      } else {
        return false;
      }
    })
    .catch(err => console.error(err));
}

function checkContent(contentId) {
  db.collection("content")
    .doc(contentId)
    .get()
    .then(snapshot => {
      if (!snapshot.exists) {
        return true;
      } else {
        return false;
      }
    })
    .catch(err => console.error(err));
}

app.get("/access", (req, res) => {
  db.collection("access")
    .where("userId", "==", req.body.userId)
    .where("contentId", "==", req.body.contentId)
    .get()
    .then(snapshot => {
      if (checkContent(req.body.contentId)) {
        return res.status(404);
      }
      if (checkUser(req.body.userId)) {
        return res.status(404);
      }
      if (snapshot.empty) {
        return res.status(401).json({
          message: "The requested user does not have access to this content"
        });
      } else {
        return res.status(200).json({
          message: "The requested user has access to this content"
        });
      }
    })
    .catch(err => {
      console.error(err);
      return res
        .status(500)
        .json({ message: "something went wrong on our end" });
    });
});

I'm assuming this has something to do with the async code going on, but I'm not sure how to fix it.

Thanks for the help!

EDIT for @Chris G

const checkUser =  async function(userId){
  return db.collection("users")
    .where("userId", "==", userId)
    .get()
    .then(snapshot => {
      if (snapshot.empty) {
        return true;
      } else {
        return false;
      }
    })
    .catch(err => console.error(err));
}

const checkContent = async function(contentId){
  return db.collection("access")
    .where('contentId', '==', contentId)
    .get()
    .then(snapshot => {
      if (snapshot.empty) {
        return true;
      } else {
        return false;
      }
    })
    .catch(err => console.error(err));
}

app.get("/access", (req, res) => {

  db.collection("access")
    .where("userId", "==", req.body.userId)
    .where("contentId", "==", req.body.contentId)
    .get()
    .then(snapshot => {

      const contentCheck = await checkContent(req.body.contentId);
      const userCheck = await checkUser(req.body.userId);
.....
Carson P
  • 313
  • 3
  • 13
  • Please see [How do I return the response from an aynchronous call](https://stackoverflow.com/q/14220321/438992), which this duplicates. There's nothing here that deals with the async nature of the "intervening" calls, besides that you'd want to check that the user exists *first*, *then* check to see if they have access. Also, notice what `checkUser` actually returns: `undefined`. The *inner* function returns `true`/`false`, which has nothing to do with `checkUser`'s return value. – Dave Newton Jul 30 '19 at 22:17
  • `return true;` deep inside your `checkUser` function won't return from that function but from the callback function you're passing to `.then()`. You need to look into using `await`. –  Jul 30 '19 at 22:17
  • @ChrisG Is there any way you can give me any details on how to restructure the function to return true/false – Carson P Jul 30 '19 at 22:20
  • 1
    If you add `return` before `db.collection(...`, the function will return the Promise. Which means you can do `var result = await checkUser(...);` elsewhere. –  Jul 30 '19 at 22:22
  • @ChrisG Hey Chris I made your changes (as shown in the OP) and I'm now getting the error `SyntaxError: await is only valid in async function` in the compiler. Is there something I'm missing here? I have NodeJS version 11 if that matters. – Carson P Jul 30 '19 at 23:11
  • 1
    Every function that has `await` inside needs to be declared `async`, exactly like the error suggests. Basic example: https://jsfiddle.net/khrismuc/cvrua79t/ –  Jul 30 '19 at 23:47
  • @CarsonP You'd be better served by either reading some docs/examples/tutorials than poking at the same question bit by bit on SO, which isn't really a tutorial site. – Dave Newton Aug 01 '19 at 21:15
  • The answer to your "specific" question revolves around the use of asynchronous calls, which has been pointed out, and linked to, yesterday. That's what to search for and understand--almost nothing in modern JS will make much sense without wrapping your head around the basic concepts of async programming. – Dave Newton Aug 01 '19 at 22:05

0 Answers0