10

I have a Firebase cloud (callable) function which deletes a firestore document and all child entities, including sub-collections. I'm doing this by slightly modifying the function provided my firebase in their docs: https://firebase.google.com/docs/firestore/solutions/delete-collections

The important bit is here:

...
return firebase_tools.firestore
      .delete(path, {
        project: process.env.GCLOUD_PROJECT,
        recursive: true,
        yes: true,
        token: functions.config().fb.token
      })
...

When I call this function from my webpage (after a user has anthenticated), the web client throws an error that the remote function caused an error. In the firebase console, I find this error:

Unhandled error TypeError: Cannot read property 'token' of undefined

This is pointing to the line in the above code snippet: token: functions.config().fb.token. So .fb is null.

What is going on here?

Searching the web tells me something about login:ci at the command line, but although I'm developing this on my laptop, when the app is deployed, there will be no command line. The website will be on firebase hosting. It makes a call to a firebase cloud function. I'm using firebase auth for user authentication (email/password) and storing data in firestore.

Further, I'm already enabled on my command line, since I can do firebase deploy --only functions just fine. How do I make sure functions.config().fb doesn't return a null??

Shahbaz
  • 10,395
  • 21
  • 54
  • 83

2 Answers2

14

If you want, you can just paste the token string directly into the code, replacing functions.config().fb.token. The authors of that page probably figured you didn't want to do that, so they suggested you should create a configuration item for it instead.

If you don't want to paste it in, and you actually want to configure the function to get that value from configuration, you will have to set the config on the command line using functions:config:set like this:

firebase functions:config:set fb.token=<YOUR-TOKEN>

The deploy your function again so it can use that value.

If you found the documentation confusing, I suggest using the "send feedback" link at the top right of the page.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • 6
    Where do I get this token from? Does it remain the same for the life of the project and, if not, when and how often do I have to generate this token? If space allows, _what_ is this token for? I've been able to use auth, firestore, functions, so far, without needing this token. – Shahbaz Apr 24 '20 at 02:57
  • 2
    The instructions are in a comment in the code of the documentation you linked. Look for the part about using the "login:ci" command of the CLI. The Firebase CLI documentation has more detail about it: https://firebase.google.com/docs/cli#cli-ci-systems – Doug Stevenson Apr 24 '20 at 04:03
  • 2
    thanks for all your help. I was trying to avoid following procedure without understanding what it is doing. What is the best place for me to understand FB tokens? Also, I did `login:ci`, it asked for my google account, then asked for permissions, then redirected me to `http://localhost:9005/....`! Obviously I don't have any server on that port so I got an error. (I'm testing my code via `python -m http.serve` on port 8000). Even `firebase serve` seem to serve port 5000. – Shahbaz Apr 24 '20 at 04:33
  • Adding '--no-localhost' seems to solve that problem. Unlike programming, I think I need to read the deployment docs fully before making any headway! – Shahbaz Apr 24 '20 at 04:53
0

The token is a login token used to login to your account on a server to get permission to execute the command as if you were doing it using the Firebase CLI. You only need to generate it once and deploy it.

As of firebase-functions v3.18.0, it's recommended to use the dotenv format to store your variables. https://firebase.google.com/docs/functions/config-env#env-variables

Steps:

  1. Run firebase login:ci in the command line
  2. Create a .env file in functions/
  3. Put the line TOKEN=<your_token_from_step_1>
  4. Use it like so:
await firebase_tools.firestore.delete(path, {
              project: process.env.GCLOUD_PROJECT,
              recursive: true,
              yes: true,
              force: true
              token: process.env.TOKEN, // Like this
            });
  1. Run firebase deploy --only functions

Note: I added force: true because of this error.

Sultan
  • 11
  • 3