fake_firebase_security_rules
This project simulates Firebase Security Rules. It is meant to be used by Fake Cloud Firestore and Firebase Storage Mocks. Given these request inputs:
- Firebase security rules such as:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
- Concrete path, access method, eg an
update
on/databases/some-db/users/abcd
, - Variables, eg a
Map
such as{'request': { 'auth': { 'uid': 'efgh' } } }
,
the library computes whether the request should be allowed or not.
Usage
import 'package:fake_firebase_security_rules/fake_firebase_security_rules.dart';
// https://firebase.google.com/docs/rules/rules-and-auth#leverage_user_information_in_rules
final authUidDescription = '''
service cloud.firestore {
match /databases/{database}/documents {
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}''';
void main(List<String> args) async {
final securityRules = FakeFirebaseSecurityRules(authUidDescription);
final uid = 'a57293b';
final variables = {
'request': {
'auth': {'uid': uid}
}
};
// Prints out `true`.
print(securityRules.isAllowed(
'databases/some-database/documents/users/$uid', Method.read,
variables: variables));
// Prints out `false`.
print(securityRules.isAllowed(
'databases/some-database/documents/users/someone-elses-id', Method.read,
variables: variables));
// Prints out `false`.
print(securityRules.isAllowed(
'databases/some-database/documents/somewhere-else/someone-doc',
Method.read,
variables: variables));
}
See the Unit tests for more advanced examples of usage.
Features
Supports:
- rules declarations used in Firestore and Firebase Storage.
- recursive
match
definitions. - exhaustive path matching with path variables and wildcards, eg
/users/{userId}/{documents=**}
. request.auth
object populated with uid, custom claims...- standard CEL types and methods, eg
bool
,int
,double
,String
,Map
,List
,String.match(regexp)
,a in list
... See cel-dart's supported features for an exhaustive list.
Missing:
- timestamps.
- durations.
- custom functions.
resource
object.request.resource
object.exists()
,get()
functions.
Implementation details
Differences between Firebase Rules CEL and standard CEL
- Timestamps. Although not implemented in this project yet, Firebase Rules uses its own Timestamp implementation while CEL uses
google.protobuf.Timestamp
(spec).
How the project works
FirestoreRules.g4
describes a grammar that parses security rules into Matches. A Match contains a path, made up of segments. Some segments might be variables or wildcards. The expression at the right of allow statements is in Common Expression Language (CEL). CEL is a language used by many security projects. See the CEL specs.
- Upon initialization, FakeFirebaseSecurityRules parses security rules into a tree of Matches.
- When a request comes in, FakeFirebaseSecurityRules finds the first Match and allow statement that corresponds to the given path and whose CEL expression evaluates to
true
.
Working on the grammar
The fastest way to get your environment up and running is to create a Codespace on the repository, then pip install antlr4-tools
. Once this is done, you can run antlr4-parse
to try out the rules against some inputs and antlr4
to regenerate the Parser in lib/src/parser/gen
.
cd grammar
# Test the grammar on one file.
antlr4-parse FirestoreRules.g4 rulesDefinition -tree -tokens 9_custom_claims.txt
# Test the grammar on all sample files.
./checkAllDescriptions.sh
Generating the parser
If you modify FirestoreRules.g4
, you may want to regenerate the parser:
cd grammar
./regenerateParser.sh
Libraries
- fake_firebase_security_rules
- Fake for Firebase Security Rules. To be used by fake_cloud_firestore and mock_firebase_storage.