Skip to content

Part 3: Firebase

KYY edited this page Aug 15, 2018 · 3 revisions

Q: What is Firebase doing in this app?

Firebase is Backend as a Service(BaaS). It can do analytics, adwords, authentication, NOSQL database, hosting via globally distributed CDNs. It is on the cloud with stability, security and scalability issues taken care of by the cloud provider -- Google.

It provides a realtime database, based on JSON/NOSQL. The values can be changed with simple functions from doc:

You can reference the root or child location in your Database by calling firebase.database().ref() or firebase.database().ref("child/path").

Writing is done with the set() method and reading can be done with the on() method

this.state = {speed: 10};

componentDidMount() {
  const rootRef = firebase.database().ref().child('react');
  const speedRef = rootRef.child('speed');
  speedRef.on("value", snapshot => {
    this.setState({
      speed: snapshot.val(),
    });
  );
}

.on('value', () => {}) creates a realtime listener and allows us to synchronize date objects in realtime, and we always attach it onto a reference that points at a spot in our database (from this Firecast video).

For eg in our app:

let ref = firebase.database().ref(`/problems/${uid}`);
let ref = firebase.database().ref(`/problems/${uid}/${key}`);

It can also integrate with authentication methods:

firebase.auth().signOut()
firebase.auth().currentUser.uid
const user = firebase.auth().currentUser;
const currentUserId =
  firebase.auth().currentUser && firebase.auth().currentUser.uid;

Q: How to get started with Firebase on the web?

Firecast video + Firebase Doc

Add Firebase to your app

To add Firebase to your app, you'll need a Firebase project and a short snippet of initialization code that has a few details about your project.

Firebase console is at https://console.firebase.google.com. From that web page, go to or create a new Firebase project, and click Add Firebase to your web app. And it will display all the initialization code you need to get started, for example:

<script src="https://www.gstatic.com/firebasejs/5.2.0/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "AIzaSyA232bBlzWT0fl3ST_KVC3Aay41yTMz5vM",
    authDomain: "achievements-dev.firebaseapp.com",
    databaseURL: "https://achievements-dev.firebaseio.com",
    projectId: "achievements-dev",
    storageBucket: "achievements-dev.appspot.com",
    messagingSenderId: "479020625755"
  };
  firebase.initializeApp(config);
</script>

you can retrieve and data from the Firebase Realtime Database by firebase.database().ref(). You can synchronize any changes using the .on() function (reading can be done with the on() method).

To use the Realtime Database, go to the console's Database tab, and edit the rules. To use the database in real-time, the rules can be set to (only during development):

{
  "rules": {
    ".read": true,
    ".write": true,
  },
}

In fact, the /database.rules.json is a copy of the Firebase Realtime Database rules.

A simple example of how to use plain javascript to read data from our dev-database is:

  <body>
	<h1 id="getData"></h1>

	<script src="https://www.gstatic.com/firebasejs/5.2.0/firebase.js"></script>
	<script>
	  // Initialize Firebase
	  var config = {
		apiKey: "AIzaSyA232bBlzWT0fl3ST_KVC3Aay41yTMz5vM",
		authDomain: "achievements-dev.firebaseapp.com",
		databaseURL: "https://achievements-dev.firebaseio.com",
		projectId: "achievements-dev",
		storageBucket: "achievements-dev.appspot.com",
		messagingSenderId: "479020625755"
	  };
	  firebase.initializeApp(config);

	  var DataDisplay = document.getElementById('getData');
	  var dbRef = firebase.database().ref().child("cohorts").child("-L61ooCve_FATtCwJd9O").child("description");
	  console.log("dbRef is: ", dbRef);
	  // .on() to read data from Firebase database
	  dbRef.on('value', data => (
		DataDisplay.innerText = data.val()
	  ));
	</script>
  </body>

The Firebase SDK is also available on npm, which is used in this react-app. Install the firebase npm package and save it to package.json:

$ npm install firebase --save

To use the module in your application, require it from any JavaScript file:

var firebase = require("firebase");

If you are using ES2015, you can import the module instead:

import firebase from "firebase";

Then, initialize the Firebase SDK using the code snippet from above:

// Initialize Firebase
const config = {
  apiKey: "AIzaSyA232bBlzWT0fl3ST_KVC3Aay41yTMz5vM",
  authDomain: "achievements-dev.firebaseapp.com",
  databaseURL: "https://achievements-dev.firebaseio.com",
  projectId: "achievements-dev",
  storageBucket: "achievements-dev.appspot.com",
  messagingSenderId: "479020625755"
};

firebase.initializeApp(config);

Q: Is it safe to expose our app's Firebase API key to the public?

Very helpful Stackoverflow answer:

So this API key locates the Firebase project on the Google server, and it is in fact required for clients to access your Firebase project information. The important security consideration here should be some thoughtful Firebase Realtime Database rules (a JSON file) and configuration.

Q: How do we understand the Firebase Realtime Database Rules?

https://firebase.google.com/docs/database/security/ and https://www.youtube.com/watch?time_continue=381&v=PUBnlbjZFAI

Q: How can we read/control the Firebase Realtime Datbase from our app?

Firecast video:

// Create references
dbRefObject = firebase.database().ref().child('object');

Essentially, the .ref() method gets you to the root of the database, and calling .child() creates a child key.

The very useful method is .on(): calling .on() on the database reference pointing to the .child('object'). EventType allows you to control the level of synchronization from the realtime databse. "value" is an EventType. In "value" EventType, the callback function will be invoked whenever the data at the ref is changed.

dbRefObject.on(EventType, snap => console.log(snap.val()));

The snap here is a data snapshot. The data snapshot is NOT JUST THE DATA. Tt has many methods like .val() or to return key names.

"value" EventType is a catch-all kind of way to synchronize the database to your app. It is good for sync object changes.

Besides "value" event, there are also child event types for sync list changes with Firebase Realtime Database, such as:

.on("child_added", callback());
.on("child_changed", callback());
.on("child_removed", callback());

Q: How do we use Firebase authentication?

Firecast Video:

Under this firebase.auth(); namespace, it will have all the auth methods to log users in.

To log users in with Email and passwords, we can use:

auth.signInWithEmailAndPassword(email, pass);

To create new account using email and password:

auth.createUserWithEmailAndPassword(email, pass);

If you want to monitor authentication state:

auth.onAuthStateChanged(firebaseUser => {});

NOTE: when signing in, the console can raise sign-in error such as "The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console..." So let's go to the Firebase console, and enable the appropriate sign-in method. Go to Firebase console's Authentication tab's Sign-In Methods, and enable/disable the Sign-In providers.

In our app:

const authProvider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(authProvider);
firebase.auth().signOut();

Q: What is Firebase hosting?

According to Google Firebase firebase hosting docs:

"You can now build an entire application purely with static files like HTML, CSS, and JS. Firebase hosting is tailored for frontend applications. Firebase hosting is a developer-focused, static web hosting provider that is fast, secure, and reliable. No matter where the user, the content is delivered fast. Files deployed to Firebase hosting are cached on SSDs at CDN edges around the world... Your users get a reliable low-latency experience. And every site is served over secure connection. Firebase hosting automatically provisions and configures an SSL certificate for each site deployed. Deploying your app from a local directory to the web only takes one command."

"Hosting gives your project a subdomain on the firebaseapp.com domain. Using the Firebase CLI, you can deploy files from local directories on your computer to your Hosting server."

For example, the domains we have for this project are https://achievements-prod.firebaseapp.com/ and https://achievements-dev.firebaseapp.com/.

Note: SSL only:

Firebase Hosting is SSL-only, meaning that content is only served over HTTPS. As you are developing your application, make sure that all external resources that are not hosted on Firebase Hosting are loaded over SSL (HTTPS), including any external scripts. Most browsers do not allow users to load "mixed content" (SSL and non-SSL traffic).

Q: Where does /src/firebase.json and /src/.firebaserc come from?

Firebase Youtube Tutorial and official doc:

To get your app deployed using Firebase, you can use Firebase CLI.

The Firebase CLI makes it easy to set up a new Hosting project, run a local development server, and deploy content.

With Node.js, you can install the Firebase CLI using npm (the Node Package Manager) by running the following command: npm install -g firebase-tools

After you have installed the Firebase CLI, and you are in the local Firebase directory, you can initiate a new Firebase project with firebase init.

Note: The firebase init command does not create a new directory. If you're starting a new app, you must first make a directory, then run firebase init from within that directory.

The firebase init command creates a firebase.json configuration file in the root of your project directory. And project alias definitions are written to a .firebaserc file, for project information, inside your project directory.

For the /src/firebase.json file, you can configure the Realtime Database of Firebase rules, and Firebase Hosting rules.

Q: Where are I find the gateway URLs to different firebase database?

Firebase db configured at /src/achievementsApp/config.js.

Q: In the /public/lti.html, the firebase database config is initialized to be the dev-version. But this has no effect for the built after ‘npm run build’ for prod branch. In fact, if we change the config in /src/achievementsApp/config.js to be prod-version, neither the /public/lti.html nor the /.firebaserc’s projects object has any effect on the firebase db location. Any comments on this?

It’s task organization task. If you firebase project then you have to change all related files. I’ll add that note to README

Q: what role does the .firebaserc file play in determining the firebase database?

firebase deploy without project option takes this value from .firebaserc (https://firebase.google.com/docs/cli/#source_control_and_project_aliases). “Project aliases for firebase projects are defined in the .firebaserc file. While using an alias, all project-specific commands (like firebase deploy or firebase data:get) will run against the currently used project. If only one alias is defined in your project directory it will be used automatically.”

Q: Is ‘firebase deploy’ command necessary to run the project locally, or is yarn install + yarn start sufficient to develop this project locally?

If you use existing firebase project then you need only npm|yarn start

Q: What is the /scripts folder's “prepare-deployment.sh” shell script doing in this app?

This is related to the .travis.yml’s workflow to do stuff before deploy. The functions require a separate npm install. The functions folder is handled as a separate node project with its own modules. I believe Google deploys these functions separately to Google Cloud.

Q: Is Firebase implementing a socket connection under the hood? If so, how do we disconnect/connect to the socket?

Yes. Firebase uses socket connection with the .on() function. You can choose to use other functions to switch to getting all the data once when load. But .on() listens for the real-time changes in the app.

Q: What is the serviceAccountKey?

serviceAccountKey file - it still should be generated by a developer - https://github.com/NUS-ALSET/achievements/tree/master/functions#local-launch This file contains secret data so it shouldn’t be at git

In achievements/functions/, npm start - launches localTrigger file. Make sure that you have ./config/serviceAccountKey.json. It can be obtained at https://console.firebase.google.com/project/<your-project>/settings/serviceaccounts/adminsdk. More details at https://firebase.google.com/docs/admin/setup

Clone this wiki locally