Skip to content

Instantly share code, notes, and snippets.

@samthecodingman
Created November 3, 2017 04:21
Show Gist options
  • Save samthecodingman/54661827f6ceeb2d44afc1c9b2c285b7 to your computer and use it in GitHub Desktop.
Save samthecodingman/54661827f6ceeb2d44afc1c9b2c285b7 to your computer and use it in GitHub Desktop.
Initializes a limited-access Firebase admin worker.
/*! adminWorkerApp.js | Samuel Jones 2017 | MIT License | github.com/samthecodingman */
/**
* @file Initializes a limited-access Firebase admin worker and returns it.
* @author Samuel Jones (github.com/samthecodingman)
*/
// Example Database Security Rules:
// 1. User must have the isAdmin claim:
// - ".read": "auth != null && auth.token.isAdmin == true"
// 2. User must be the admin worker:
// - ".read": "auth != null && auth.uid === 'admin-worker'"
// 3. User can be the admin worker or a have the isAdmin claim (verbose, use option 1 when possible):
// - ".read": "auth != null && (auth.uid === 'admin-worker' || auth.token.isAdmin === true)"
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const ADMIN_WORKER_UID = 'admin-worker';
const AUTH_VARIABLE = {
provider: 'custom',
uid: ADMIN_WORKER_UID,
token: {
isAdmin: true
}
}
const app = admin.initializeApp(Object.assign(
{},
functions.config().firebase,
{ databaseAuthVariableOverride: AUTH_VARIABLE }
), ADMIN_WORKER_UID)
module.exports = app
@samthecodingman
Copy link
Author

The 'admin-worker' App

Purpose

Initialize an limited-access firebase-admin app (named 'admin-worker' by default) without requiring the use of try-catch blocks and repeated code. Separating this file out also allows you to include it only when needed - which is particularly useful if using an on-demand function-loader as discussed in Issue #170 of firebase/functions-samples.

Usage

const adminWorkerApp = require('./adminWorkerApp');

Example

If your database security rules are configured as follows:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && (auth.uid === $uid || auth.token.isAdmin)",
        ".write": "auth != null && auth.uid === $uid"
      }
    }
  }
}

The following operation using adminWorkerApp should always fail.

const adminWorkerApp = require('./adminWorkerApp');

adminWorkerApp.database().ref('users/userId01').remove()
  .then(() => { // never called in this example
    console.log('success');
  })
  .catch((err) => {
    console.log('FAIL: ', err); // logs "FAIL: PERMISSION_DENIED"
  });

But the following operation using adminWorkerApp should succeed.

const adminWorkerApp = require('./adminWorkerApp');

adminWorkerApp.database().ref('users/userId01').once('value')
  .then((snapshot) => { // called with desired DataSnapshot
    console.log('SUCCESS: location contains ' + snapshot.toJSON());
  })
  .catch((err) => { // never called in this example
    console.log('FAIL: ', err);
  });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment