UNPKG

firebase-rules-parser

Version:
443 lines (442 loc) 37.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const __1 = require(".."); describe('Firebase Rules', () => { describe('Path matching', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if true; } } }`; it('Will give ', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess('/databases/DEFAULT/documents/organizations/mindhive', { auth: undefined, resource: undefined, }).read).toBe(true); expect(rules.hasAccess('/databases/DEFAULT/documents/someother', { auth: undefined, resource: undefined, })).toEqual({}); }); }); describe('Path matching', () => { const ruleFile = (left, rule, right) => `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read, write: if ${left} ${rule} ${right}; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const result = (value) => ({ read: value, write: value, }); describe('Comparization Rules', () => { it('Will support greater than (>)', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(5, '>', 2)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will support greater or equal than (>=)', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(5, '>=', 5)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will support less or equal than (<=)', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(5, '<=', 3)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(false)); }); it('Will support less than (<)', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(3, '<', 4)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will support equality (==)', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(3, '==', 3)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will support inequality (!=)', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile(3, '!=', 2)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); }); describe('Parenthesis', () => { it('Will support parenthesis, (2 + 3) == 5', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(2 + 3)', '==', 5)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will support recuresive parenthesis resolvling, (2 + (4 * 3)) == 14', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(2 + (4 * 3))', '==', 14)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); }); describe('Arithmetics', () => { it('Will do addition, (5 + 2) == 7', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(5 + 2)', '==', 7)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will do subtraction, (3 - 2) == 1', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(3 - 2)', '==', 1)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will do multipication, (3 * 2) == 6', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(3 * 2)', '==', 6)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will do division, (4 / 2) == 2', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(4 / 2)', '==', 2)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); }); describe('Logical operations', () => { it('Will support logical or, (5 == 2) || true', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(5 == 2)', '||', true)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will support logical and, (5 == 2) && true', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(5 == 2)', '&&', true)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(false)); }); it('Will support logical operations withour parenthesis, 5 == 2 || true', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('5 == 2', '||', true)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); }); describe('Unary operations', () => { it('Will support negation, (10+(-5)) == 5', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('(10+(-5))', '==', 5)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); it('Will support exclusion, !true == false', () => { const rules = new __1.FirebaseRulesIntepreter().init(ruleFile('!true', '==', false)); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual(result(true)); }); }); }); describe('Functions', () => { it('will support function calls without arguments', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { function common() { return true; } match /organizations/{doc} { allow read: if common(); } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); it('will support function calls expressions in arguments', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { function common(value1, value2) { return value1 == value2; } match /organizations/{doc} { allow read: if common(2 + 4, 2 * 3); } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); }); describe('Object references', () => { it('will support basic request object reference calls', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if request.auth != null; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); it('will match given auth uid value (double quotes)', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if request.auth.uid == "ABC"; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.request.auth.uid = 'ABC'; expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); it('will match given auth uid value (single quotes)', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if request.auth.uid == 'ABC'; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.request.auth.uid = 'ABC'; expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); it('will match given auth uid value (empty string)', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if request.auth.uid == ''; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.request.auth.uid = ''; expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); it('will support a map in operator', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if 'auth' in request; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); // it('will give a null value error if object member do not exists', () => { // const ruleFile = `service cloud.firestore { // match /databases/{database}/documents { // match /organizations/{doc} { // allow read: if request.auth.daa == ''; // } // } // }`; // const path = '/databases/DEFAULT/documents/organizations/mindhive'; // const rules = new RulesParser().init(ruleFile); // expect(() => rules.hasAccess(path, createFirebaseRulesContext())).toThrow(); // }); }); describe('arrays', () => { it('will read a cell value from an array', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if resource.data.list[1] == 'Joy'; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.resource.data = { list: ['Happy', 'Joy'], }; expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); it('will match arrays to be equal', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if resource.data.list == [1, 2]; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.resource.data = { list: [1, 2], }; expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); it('will support a list in operator', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if 2 in [1, 2]; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, __1.createFirebaseRulesContext())).toEqual({ read: true, }); }); }); describe('exists -function', () => { it('will read a cell value from an array', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if exists(/databases/$(database)/documents/users/$(request.auth.uid)); } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); context.onExistsCall = () => true; const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.request.auth.uid = '123'; expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); }); describe('get -function', () => { it('will call onGet event handler when get is executed on rules code', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.value == 'cool'; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); context.onGetCall = () => ({ data: { value: 'cool', }, id: '123', }); const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.request.auth.uid = '123'; rules.resource.data = { value: 'cool', }; expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); it('will return a get data as a function return and function call can point into its fields', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { function test() { return get(/databases/$(database)/documents/users/$(request.auth.uid)); } allow read: if test().data.value == 'cool'; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); context.onGetCall = () => ({ data: { value: 'cool', }, id: '123', }); const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); rules.request.auth.uid = '123'; rules.resource.data = { value: 'cool', }; expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); }); describe('string member functions', () => { it('will trim input string', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if ' cool '.trim() == 'cool'; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); it('will lowercase input string', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if 'COOL'.lower() == 'cool'; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); it('will uppercase input string', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if 'Cool'.upper() == 'COOL'; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); it('will return a size of input string', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if 'Cool'.size() == 4; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); it('will match regex pattern of input string', () => { const ruleFile = `service cloud.firestore { match /databases/{database}/documents { match /organizations/{doc} { allow read: if 'This is very cool thingie'.matches('.*cool.*') == true; } } }`; const path = '/databases/DEFAULT/documents/organizations/mindhive'; const context = __1.createFirebaseRulesContext(); const rules = new __1.FirebaseRulesIntepreter().init(ruleFile); expect(rules.hasAccess(path, context)).toEqual({ read: true, }); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguc3BlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9pbnRlcHJldGVyL19fc3BlY3NfXy9pbmRleC5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsMEJBQXlFO0FBRXpFLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQUU7SUFDOUIsUUFBUSxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7UUFDN0IsTUFBTSxRQUFRLEdBQUc7Ozs7OztNQU1mLENBQUM7UUFFSCxFQUFFLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtZQUNwQixNQUFNLEtBQUssR0FBRyxJQUFJLDJCQUF1QixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRTNELE1BQU0sQ0FDSixLQUFLLENBQUMsU0FBUyxDQUFDLHFEQUFxRCxFQUFFO2dCQUNyRSxJQUFJLEVBQUUsU0FBUztnQkFDZixRQUFRLEVBQUUsU0FBUzthQUNwQixDQUFDLENBQUMsSUFBSSxDQUNSLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRWIsTUFBTSxDQUNKLEtBQUssQ0FBQyxTQUFTLENBQUMsd0NBQXdDLEVBQUU7Z0JBQ3hELElBQUksRUFBRSxTQUFTO2dCQUNmLFFBQVEsRUFBRSxTQUFTO2FBQ3BCLENBQUMsQ0FDSCxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUU7UUFDN0IsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUErQixFQUFFLElBQVksRUFBRSxLQUFnQyxFQUFFLEVBQUUsQ0FDbkc7OztxQ0FHK0IsSUFBSSxJQUFJLElBQUksSUFBSSxLQUFLOzs7UUFHbEQsQ0FBQztRQUNMLE1BQU0sSUFBSSxHQUFHLHFEQUFxRCxDQUFDO1FBRW5FLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FB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