Firebase Rules Parser

2.0.1 · maintenance · verified Tue Apr 21

The `firebase-rules-parser` library provides a parser and emulator for Firebase security rules, allowing developers to programmatically load and test Firebase rule files. Its primary use case is facilitating unit testing for Firebase projects, particularly as a companion to `ts-mock-firebase`. The current stable version is 2.0.1, released in May 2019. While it aims to support nearly all Firebase rules language functionality, it explicitly notes limitations with duration, latlong, and timestamp functions. The project's release cadence appears to be slow or inactive since 2019, and it differentiates itself by offering an off-platform rule emulation capability without requiring a live Firebase instance, making it suitable for local development and CI/CD pipelines. It ships with TypeScript types, enhancing developer experience for TypeScript users.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates initializing the Firebase rules parser with a rules string and then using it to check read and write access for different paths and authentication contexts.

import createFirebaseRulesIntepreter, { createFirebaseRulesContext } from 'firebase-rules-parser';

const rulesSource = `
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth.uid == userId;
      allow write: if request.auth.uid == userId && resource.data.name is string;
    }
    match /public/{documentId} {
      allow read: if true;
    }
  }
}
`;

// Create an instance of the interpreter
const rules = createFirebaseRulesIntepreter();
// Load your rules source string
rules.init(rulesSource);

// Create a context object for the access check
const context = createFirebaseRulesContext({
  auth: {
    uid: 'testUserId123',
    email: 'test@example.com'
  },
  resource: {
    id: 'testUserId123',
    data: {
      name: 'John Doe',
      value: 123
    }
  },
  // Define triggers for `exists()` and `get()` calls within rules
  onExistsCall: (path) => {
    return path === '/databases/DEFAULT/documents/users/testUserId123'; 
  },
  onGetCall: (path) => {
    if (path === '/databases/DEFAULT/documents/users/testUserId123') {
      return {
        uid: 'testUserId123',
        name: 'Test User'
      };
    }
    return null;
  }
});

// Check access for a specific path and operation
const hasReadAccess = rules.hasAccess('/databases/DEFAULT/documents/users/testUserId123', context);
console.log('Read access:', hasReadAccess.read); // Should be true

const hasWriteAccess = rules.hasAccess('/databases/DEFAULT/documents/users/testUserId123', context);
console.log('Write access:', hasWriteAccess.write); // Should be true

const noAccessContext = createFirebaseRulesContext({
  auth: { uid: 'anotherUser' },
  resource: { id: 'testUserId123', data: { name: 'Another Name' } }
});
const noReadAccess = rules.hasAccess('/databases/DEFAULT/documents/users/testUserId123', noAccessContext);
console.log('No read access:', noReadAccess.read); // Should be false or undefined

const publicReadAccess = rules.hasAccess('/databases/DEFAULT/documents/public/someDoc', noAccessContext);
console.log('Public read access:', publicReadAccess.read); // Should be true

view raw JSON →