Setup AppGyver and Firebase REST API

Thanks @vereggen when you pass the id_token through as an auth parameter is that as a query, header or url paramater in the AppGyver Data Resource rest API setup?

I haven’t secured the data yet as I’m having difficulty getting records to write to firestore. Things are working fine in the manual test but when I use the preview app the records don’t write. Once I overcome that the next step is to secure everything.

Hey @William_Glass … I knew that this question was coming :slight_smile: and I’ve been working on a response. Here goes …

Step 1) Confirm Firebase database type

Everything we’ve done to this point is setting up the authority (login, refresh token, etc). Now we need to set up the database.

The first thing you need to check is that you are using the correct database type in Firebase.

There are two database types in Firebase … Could Firestore and Realtime Database.

What we’ve set up ONLY works with the Firebase Realtime Database.

There’s a great tutorial that was released using Cloud Firestore. Unfortunately, I haven’t found a way to secure the data using the Cloud Firestore via the AppGyver REST API. (If anyone finds a solution to this … please let me know).

Once you’ve confirmed that you’re using the Firebase Realtime Database, you can move to step 2.

Step 2) Setup the Firebase Realtime Database

In this example, I’m storing settings for a specific user.

Whenever possible, try to store your data this way.

We are using an exposed API and if anyone hacks your app, only that specific user’s data would be compromised.

Here’s the Firebase Realtime Database screenshot of the data setup …

Step 3) Setup AppGyver REST API

Here’s what the setup looks like in AppGyver

Base …

Get Record …

Get Record Schema …

Update Record …

Step 4) Secure your data

When testing your connection, change your database rules to this …

// WARNING: Your database is wide open with these rules. Anyone can read, write, delete your data. 
{
  "rules": {
    ".read": true,
    ".write": true
  }
}

Once you’ve confirmed that you have a connection. Test that you have a valid auth …

// BETTER: Only logged in users have access (can read, write, delete) to this data 
// This will only allow users with a valid id token to access the data. 
{
  "rules": {
    ".read": "auth.uid != null",
    ".write": "auth.uid != null"
  }
}

Once you know your Auth Id Token works. Secure your data even further by setting these rules …

// BEST: Only the specific logged in user can read and write their own data.
// Notice that I've now specified the table within the database. So you need an entry each table.
{ 
  "rules": {
    "user-settings": {
      "$user_id": {
        ".read": "$user_id === auth.uid",
        ".write": "$user_id === auth.uid"
      }
    }
  }
}

Hope this helps :sunglasses:

2 Likes

Thanks so much @vereggen this is fantastic! Currently, I have Firestore setup based on @Eduardo_Jaramillo 's explainer post but for some reason, the create record only seems to be working on the web.

I’m going to have a play around with the Real-Time database and see if it’ll work on mobile properly.

Extremely helpful!

@vereggen this works great thank you!

I set up a POST request to write records to store additional data on users and Firebase Real-Time database autogenerates a record level UID.

How did you override that autogenerated UID to use the user_id from the auth response?

Or do you have to first create those manually and then only use put requests to update?

Just use UPDATE (PUT).

CREATE (POST) is not required. As you discovered, POST will auto generate a record UID.

In the update, make sure to set user-id and auth params to non-static and required.

And then in the update flow function pass the params.

1 Like

The only 3 database calls you need are GET, POST, and DELETE.

GET Collection doesn’t work properly as it doesn’t return an array as I covered here.

I discovered a workaround using a regular GET in place of a GET collection. If you need to retrieve multiple records, let me know and I will post an example.

1 Like

Also, make sure to delete the delay for the GET otherwise your traffic usage will be through the roof and you may exceed your free plan limits.

1 Like

Thanks so much @vereggen

It is working great and I think I figured out how to use the Get Record to retrieve multiple records. I just cloned the data resource and removed the user_id URL placeholder and it calls all the records.

You got it buddy! Well done :slight_smile:

1 Like

@vereggen I thought I had it sorted but maybe not :sweat_smile:

I’m struggling to actually display the collection of records, I can’t figure out the workaround given we are using Get a single record to return the list.

After I set up the 2nd data resource for getting all the records, I can’t figure out how to repeat them (or maybe it’s not possible with our little workaround).

When setting up the data variable, I’ve tried using the Get a single record logic but then AppGyver doesn’t show currently repeated as an option. I’ve also tried copying the logic node for a single Get Record onto the “Get Collection” and hardwiring the logic nodes that way. It allows me to use the currently repeated formatting but then it doesn’t actually display any data in the preview apps (debugger shows the HTTP request returns the right data).

I’m wondering if it is because it is expecting a list and I was using a unique ID within the once the user accesses their data set.

Let me know if you’ve solved this problem yet!

Hi @William_Glass … Yes, I’ve gotten this to work.

I use a couple of lines of javascript to convert the output (see below).

The map statement adds the key value as a text element and the sort statement sorts the output by name (change the a.name and b.name to the field you want to sort).

Note how the output is a list / array.

1 Like

Hi @William_Glass … Here are steps to take the data from Firebase and populate a list.

Step 1: Use the Get Record hack to pull an array of data from Firebase. You’ve already done this above.

Step 2: Assign the results from the Get Record to a data variable. Steps 1 and 2 already done for you when you add a Data Variable to a page.

Step 3: Transform the results via Javascript. Here’s the code from the previous screenshot to cut and paste.

return { result: Object.entries(inputs.input1 || {}) 
      .map( ( [key,value] ) => ( { ...value,uid: key } ) )
      .sort(function(a, b) {
          var nameA = a.name.toUpperCase(); // ignore upper and lowercase
          var nameB = b.name.toUpperCase(); // ignore upper and lowercase
          if (nameA < nameB) {
            return -1;
          }
          if (nameA > nameB) {
            return 1;
          }
          // names must be equal
          return 0;
        })
 };

Step 4: Assign the result to an object. Override the binding by using a formula. Once again, make sure to click the result, don’t type the formula in manually.

Step 5: Add a list function to your page. Once again, use the formula as the repeating value. For the values that you want to display, use current.[dbfieldname], also as a formula.

image

This should get you going. Good luck :slight_smile:

1 Like

Thanks @vereggen you’ve been super helpful! I got it to work yesterday thanks to your walk through :slight_smile:

But now the HTTP request from the auth isn’t returning any response so there’s no user_id being returned. I think this latest update on the HTTP Request logic node just messed up authentication for us.

I’ve tried redoing the entire flow but still nothing despite seeing new accounts being created in Firebase and existing accounts allowed to log in. There’s just no data coming back into AppGyver.

Are you experiencing this same problem now?

Glad you finally got the list working.

Regarding the HTTP Request. I haven’t applied the update yet to my project. If you think there is an issue, document it and submit a bug report here.

I will avoid updating for now.

1 Like

They’ve fixed the bug so it should be working fine now!

@vereggen So I overlooked resetting a password when a user forgets. I can’t quite get the URL right for the post call to firebase.

Did you ever implement this or run into this issue for resetting user’s passwords?

Hey @William_Glass … Happy New Year!

Yes … I’ve got the reset password to work.

Here’s the URL that I’m using …

https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=[API_KEY]

Here’s the Firebase documentation …

Here’s the json object (request body) …

image

And the HTTP flow function setup …

image

@vereggen Happy new year to you too! Thanks for the speedy response. I’ll give this a shot now and see if I can get it working.

Thanks for sharing where to find those urls. I always seem to only see the function calls for when you have the SDK inputted which we can’t do with AppGyver just yet.

Works great! Thanks for the help!

No worries buddy … anytime!

1 Like