Today I Learned

hashrocket A Hashrocket project

Protect Yourself Against Firebase Database Refs!

My worst nightmare is to lose production data, thank God for backups. But my nightmare came to life on a project's Firebase database. This is a noSQL JSON-like document database offered as a service from Google Cloud Platform. You use it like this:

firebase.database.ref('/customers/1')

This is how you get the data at that path. Like a file system.

And when you want to make it dynamic:

firebase.database.ref(`/customers/${customerID}`)

Cool.

But, what if customerID is blank?

cue Nightmare Before Christmas soundtrack

funtion handleDelete(customerID) {
	firebase.database.ref(`/customers/${customerID}`)
	// ...delete()
}

If I ran that function in production with a blank customer ID, well then I just deleted all the customers.

Fear Not!

import protectedRef from './protectedRef.js'

const customerID = ''
protectedRef('customers', customerID) 
// => [ERROR] Bad ref! 1: ""

Use protection kids.

// protectedRef.js

import { sanitize } from './sanitize.js'

function protectedRefReducer(pathSoFar, pathPart, index) {
  const sanitizedPathPart = sanitize(pathPart)


  if (!sanitizedPathPart) {
    throw new Error(`Bad ref! ${index}: "${pathPart}"`)
  }

  return pathSoFar + '/' + sanitizedPathPart
}

export default function protectedRef(...parts) {
	if (!parts.length) {
  	throw new Error('noop')
  }
  return firebase.database().ref(parts.reduce(protectedRefReducer, ''))
}
See More #javascript TILs
Looking for help? At Hashrocket, our JavaScript experts launch scalable, performant apps on the Web, Android and iOS. Contact us and find out how we can help you.