News

October 26: Final Team Project Demo: In-class app demos and wrap up discussion.
October 17: Google visit
October 9: Start of weekly coaching meetings and Retrospective reports
September 26: First demo!
September 21: Hybrid setup report and four-panel storyboard.
September 19 Day One -- What each team needs to prepare for the first day of class!

When

TTh 11am - 12:20am

Where

Tech M164

Who

Chris Riesbeck

Resources

Overview

Google's Firebase is a data storage and static web page hosting service. The level of service for free is relatively generous and more than adequate for most prototype projects.

There are several important issues to be aware of:

JSON Data Design

Some readings:

An important thing to remember is:

JSON is not the same as a JavaScript object.

The rules for JSON are stricter. The following is a legal JavaScript object, but not legal JSON:

{ id: "jsmith", email: "john.smith@gmail.com" }

In JSON, keys must strings, so you need to write

{ "id": "jsmith", "email": "john.smith@gmail.com" }

When writing JSON by hand, use a JSON validator to avoid annoying Firebase errors.

An even more important thing to remember is:

Arrays are not first-class citizens.

This may seem unintuitive. Arrays are first-class in JSON. And isn't a database at heart an array of objects? In Firebase, the answer is no.

A Firebase database is key-value pairs, where values are strings, numbers, and nested key-value pair objects. Keys play a prominent role. For example, if you had a list of users, with ids and emails, a common JSON representation would be

{
  "users": [{
    "id": "jsmith",
    "email": "john.smith@gmail.com"
  }, {
    "id": "mjones",
    "email": "mary.jones@.gmail.com"
  }]
}

This is not good Firebase data design. Instead, whereever you have an array of objects, flatten the data using some appropriate object value as a key, e.g.,

{
  "users": {
    "jsmith": { "email": "john.smith@gmail.com" },
    "mjones": { "email": "mary.jones@.gmail.com" }
  }
}

Another example might be if you have a list of messages. Don't make an array of them. Make an object whose keys are the message ID or message timestamp.

You can have an array of primitives, e.g., a list of numbers or a list of email addresses, but think about whether these really should have more contentful keys than just "0", "1", and so on.

When working with JSON structured like the above, the JavaScript method Object.keys() is incredibly helpful. For example, if the variable json contains the flattened user data example above, then this expression would calculate an array of "mailto" links, suitable for inserting into a web page:

Object.keys(json.users).map(function (userid) {
  return '<a href="mailto:' + json.users[userid].email +
    '">' + userid + '</a>';
});

Security rules

Some readings:

Rules are written in a nested tree form that mirrors your JSON data tree. Use specific key strings for fixed parts of your JSON data, and dollar-variables ($name) for dynamic data keys. For example, suppose your data tree looks like this:

{
  "teams": {
    "blue": { "name": "Blue Devils" },
    "green": { "name": "Green Ghosts" },
    "red" { "name": "Red Wings" }
  },
  "users": {
    "jsmith": { "email": "john.smith@gmail.com", "team": "green" },
    "mjones": { "email": "mary.jones@.gmail.com", "team": "blue" }
  }
}

Here, the fixed keys are teams and users, and the specific teams and users are dynamic. So security rules about who can change team names or user data might look like this:

{
  "rules": {
    "teams": {
      "$team": { "name": { "_write": ... } }
    },
    "users": {
      "$user": { "_write": ... }
    }
  }
}

The most important thing to remember is this rule:

...child rules can only grant additional privileges to what parent nodes have already declared. They cannot revoke a read or write privilege.

So don't start with read and write being true at the root!

The default rules are read and write are true for anyone.

Rules are written in JavaScript expressions. There's a few special variables, the most important being auth, which is created by whatever authentication source you use. It will contain a user id (auth.uid), as defined by the source. The user id might be an email address, user name, or some anonymous UUID.

To test and debug your security rules, use the Simulator, available in your app database dashboard. It lets you test read and write operations with and without authentication with no danger of changing any data.

Validation rules

Some readings:

Validation rules are primarily to prevent data corruption from occurring. Data corruption from buggy code is super-easy. All that needs to happen is to call set() with a bad JSON path. If you look at the example, you can see quite a few checks for what must and must not exist when data is sent.