blaze_compiler
Advanced tools
Comparing version 0.0.30 to 0.0.33
{ | ||
"name": "blaze_compiler", | ||
"version": "0.0.30", | ||
"version": "0.0.33", | ||
"description": "Transpiles extendable, schema orientated definitions into Firebase security rules", | ||
@@ -22,5 +22,5 @@ "author": "Tom Larkworthy", | ||
"source-processor": "0.0.6", | ||
"tv4": "1.0.16", | ||
"tv4": "1.1.12", | ||
"falafel": "0.3.1", | ||
"source-map-support": "0.2.7" | ||
"source-map-support": "0.3.2" | ||
}, | ||
@@ -27,0 +27,0 @@ "devDependencies": { |
# Blaze Security Compiler for Firebase | ||
The blaze compiler simplifies building security rules for Firebase. It drastically reduces the amount of copy and pasting involved. Blaze compiler security rules are shorter, and the syntax is less fussy. | ||
The blaze compiler simplifies building security rules for your Firebase database. It drastically reduces the amount of copy and pasting involved. Blaze compiler security rules are shorter, and the syntax is less fussy. | ||
@@ -17,3 +17,3 @@ | ||
- isLoggedIn(): auth.uid !== null | ||
schema: {} | ||
@@ -100,3 +100,3 @@ | ||
A Firebase schema node is either a leaf type (*string*, *number*, *boolean*) or an *object* which contains more child schema nodes. The type is specified with "type". Children of objects are specified as a map under "properties" | ||
A Firebase database schema node is either a leaf type (*string*, *number*, *boolean*) or an *object* which contains more child schema nodes. The type is specified with "type". Children of objects are specified as a map under "properties" | ||
@@ -113,9 +113,9 @@ ```YAML | ||
In the above example you could set `{string_child: "blah"}` at the root of the Firebase but not `{string_child: true}` | ||
In the above example you could set `{string_child: "blah"}` at the root of your database but not `{string_child: true}` | ||
You can leave a schema unspecified with {} or with type: "any". | ||
You can leave a schema unspecified with {} or with type: "any". | ||
#### required | ||
The required keyword states which children **must** be present. The required keyword is only valid for schema nodes with object types. | ||
The required keyword states which children **must** be present. The required keyword is only valid for schema nodes with the object or any types. | ||
@@ -175,3 +175,3 @@ ```YAML | ||
exclusiveMaximum: true | ||
examples: | ||
@@ -234,3 +234,3 @@ - 0 | ||
You can be sure all constraints above and below evaluate to true for a write to be allowed. The only quirk is related to wildchilds. You can't write anything above a wildchild that includes the wildchild as a descendant. They do inherit their parents constraints though, as do their siblings, so the use of wildchilds **never** makes the Firebase less constrained accidentally. | ||
You can be sure all constraints above and below evaluate to true for a write to be allowed. The only quirk is related to wildchilds. You can't write anything above a wildchild that includes the wildchild as a descendant. They do inherit their parents constraints though, as do their siblings, so the use of wildchilds **never** makes the database less constrained accidentally. | ||
@@ -389,2 +389,7 @@ #### Model reuse | ||
## Changelog | ||
- 10th Aug 2015: | ||
- Allowed repeat examples and non-example, as the error message can be unclearly attached to something unrelated (see repeatExample.yaml) | ||
- upgrade source-map-repository so blaze_compiler continues to fix issue with io.js | ||
- Allowed any type to have the required keyword | ||
- 19th May 2015: | ||
@@ -414,6 +419,6 @@ - Improved optimization use a less verbose object detection notation and spurious parent is an object checks | ||
- bugfix: functions in ACL resolved properly | ||
- 3rd November 2014: | ||
- bugfix: wilderchild matching fix in ACL | ||
- 1st November 2014: | ||
@@ -423,10 +428,10 @@ - bugfix: wilderchild overwriting parent constraints bug fixed | ||
- bugfix: regex detection firing erroneously on strings starting with '/' fixed | ||
- 20th October 2014: | ||
- optimizations added to reduce code bloat | ||
- sensitization bug regarding regexes fixed | ||
- 28th August 2014:ß | ||
- range constraints for number type added | ||
- 26th August 2014: | ||
@@ -438,3 +443,3 @@ - wilderchilds introduced, ~$ allows nullable wildchilds whose parents can be written to. | ||
- predicates renamed to functions | ||
- 14th July 2014: | ||
@@ -450,2 +455,1 @@ - improved error reporting | ||
- allowed untyped schema if type is not specified | ||
@@ -5,54 +5,12 @@ { | ||
".read":"false", | ||
"users": { | ||
"$workspace_id": { | ||
".write":"false", | ||
".read":"false", | ||
"$userid": { | ||
".write":"(false)", | ||
".read":"($userid===auth.username)", | ||
"inbox": { | ||
".write":"(false)", | ||
".read":"(($userid===auth.username))", | ||
"$message": { | ||
".write":"((((!newData.exists()||newData.hasChildren())&&(newData.val()==null||newData.child('from').exists()&&newData.child('to').exists()&&newData.child('message').exists())&&(auth.username==newData.child('from').val()&&newData.child('from').exists()&&!data.child('from').exists()||$userid===auth.username&&data.child('from').exists()&&!newData.child('from').exists())&&(!newData.child('from').exists()||newData.child('from').isString())&&(newData.child('to').exists()&&!data.child('to').exists()||data.child('to').exists()&&!newData.child('to').exists())&&(!newData.child('to').exists()||newData.child('to').isString())&&(newData.child('message').exists()&&!data.child('message').exists()||data.child('message').exists()&&!newData.child('message').exists())&&(!newData.child('message').exists()||newData.child('message').isString())&&(newData.parent().exists()&&!data.parent().exists()&&auth.username!==null||data.parent().exists()&&!newData.parent().exists()&&$userid===auth.username))))", | ||
".read":"(($userid===auth.username))", | ||
"from": { | ||
".write":"((((newData.parent().val()==null||newData.parent().child('from').exists()&&newData.parent().child('to').exists()&&newData.parent().child('message').exists())&&(auth.username==newData.val()&&newData.exists()&&!data.exists()||$userid===auth.username&&data.exists()&&!newData.exists())&&(!newData.exists()||newData.isString())&&(newData.parent().parent().exists()&&!data.parent().parent().exists()&&auth.username!==null||data.parent().parent().exists()&&!newData.parent().parent().exists()&&$userid===auth.username))))", | ||
".read":"(($userid===auth.username))" | ||
}, | ||
"to": { | ||
".write":"((((newData.parent().val()==null||newData.parent().child('from').exists()&&newData.parent().child('to').exists()&&newData.parent().child('message').exists())&&(newData.exists()&&!data.exists()||data.exists()&&!newData.exists())&&(!newData.exists()||newData.isString())&&(newData.parent().parent().exists()&&!data.parent().parent().exists()&&auth.username!==null||data.parent().parent().exists()&&!newData.parent().parent().exists()&&$userid===auth.username))))", | ||
".read":"(($userid===auth.username))" | ||
}, | ||
"message": { | ||
".write":"((((newData.parent().val()==null||newData.parent().child('from').exists()&&newData.parent().child('to').exists()&&newData.parent().child('message').exists())&&(newData.exists()&&!data.exists()||data.exists()&&!newData.exists())&&(!newData.exists()||newData.isString())&&(newData.parent().parent().exists()&&!data.parent().parent().exists()&&auth.username!==null||data.parent().parent().exists()&&!newData.parent().parent().exists()&&$userid===auth.username))))", | ||
".read":"(($userid===auth.username))" | ||
}, | ||
"$other":{".validate":"false"} | ||
} | ||
}, | ||
"outbox": { | ||
".write":"(false)", | ||
".read":"(($userid===auth.username))", | ||
"$message": { | ||
".write":"((((!newData.exists()||newData.hasChildren())&&(newData.val()==null||newData.child('from').exists()&&newData.child('to').exists()&&newData.child('message').exists())&&(auth.username==newData.child('from').val()&&newData.child('from').exists()&&!data.child('from').exists()||$userid===auth.username&&data.child('from').exists()&&!newData.child('from').exists())&&(!newData.child('from').exists()||newData.child('from').isString())&&(newData.child('to').exists()&&!data.child('to').exists()||data.child('to').exists()&&!newData.child('to').exists())&&(!newData.child('to').exists()||newData.child('to').isString())&&(newData.child('message').exists()&&!data.child('message').exists()||data.child('message').exists()&&!newData.child('message').exists())&&(!newData.child('message').exists()||newData.child('message').isString()))))", | ||
".read":"(($userid===auth.username))", | ||
"from": { | ||
".write":"((((newData.parent().val()==null||newData.parent().child('from').exists()&&newData.parent().child('to').exists()&&newData.parent().child('message').exists())&&(auth.username==newData.val()&&newData.exists()&&!data.exists()||$userid===auth.username&&data.exists()&&!newData.exists())&&(!newData.exists()||newData.isString()))))", | ||
".read":"(($userid===auth.username))" | ||
}, | ||
"to": { | ||
".write":"((((newData.parent().val()==null||newData.parent().child('from').exists()&&newData.parent().child('to').exists()&&newData.parent().child('message').exists())&&(newData.exists()&&!data.exists()||data.exists()&&!newData.exists())&&(!newData.exists()||newData.isString()))))", | ||
".read":"(($userid===auth.username))" | ||
}, | ||
"message": { | ||
".write":"((((newData.parent().val()==null||newData.parent().child('from').exists()&&newData.parent().child('to').exists()&&newData.parent().child('message').exists())&&(newData.exists()&&!data.exists()||data.exists()&&!newData.exists())&&(!newData.exists()||newData.isString()))))", | ||
".read":"(($userid===auth.username))" | ||
}, | ||
"$other":{".validate":"false"} | ||
} | ||
} | ||
"$user_id": { | ||
".write":"((root.child('/rels/workspaces/users/').child($workspace_id).child(auth.id).child('role').val()=='administrator'))", | ||
".validate":"((root.child('/rels/workspaces/users/').child($workspace_id).child(auth.id).child('role').val()=='administrator'))", | ||
".read":"false" | ||
} | ||
}, | ||
"$other":{".validate":"false"} | ||
} | ||
} | ||
} |
@@ -62,4 +62,6 @@ require('source-map-support').install(); | ||
SchemaRoot.parse = function (json) { | ||
var schema = new SchemaRoot(json); | ||
return schema; | ||
if (json == null) { | ||
json = new Json.JObject(); | ||
} | ||
return new SchemaRoot(json); | ||
}; | ||
@@ -162,3 +164,3 @@ return SchemaRoot; | ||
rules.functions = expression.Functions.parse(json.getOrNull("functions")); | ||
rules.schema = SchemaRoot.parse(json.getOrThrow("schema", "no schema defined")); | ||
rules.schema = SchemaRoot.parse(json.getOrNull("schema")); | ||
rules.access = Access.parse(json.getOrWarn("access", "no access list defined, this Firebase will be inactive")); | ||
@@ -165,0 +167,0 @@ return rules; |
@@ -77,5 +77,7 @@ /// <reference path="../types/js-yaml.d.ts" /> | ||
} | ||
static parse(json: Json.JValue): SchemaRoot{ | ||
var schema = new SchemaRoot(json); | ||
return schema | ||
static parse(json: Json.JValue): SchemaRoot { | ||
if (json == null) { | ||
json = new Json.JObject() | ||
} | ||
return new SchemaRoot(json); | ||
} | ||
@@ -187,3 +189,3 @@ } | ||
rules.functions = expression.Functions.parse(json.getOrNull("functions")); | ||
rules.schema = SchemaRoot.parse(json.getOrThrow("schema", "no schema defined")); | ||
rules.schema = SchemaRoot.parse(json.getOrNull("schema")); | ||
rules.access = Access.parse(json.getOrWarn("access", "no access list defined, this Firebase will be inactive")); | ||
@@ -190,0 +192,0 @@ return rules |
@@ -9,2 +9,3 @@ /// <reference path="../types/nodeunit.d.ts" /> | ||
export function testString(test:nodeunit.Test):void{ | ||
@@ -270,1 +271,25 @@ async.series([ | ||
} | ||
/*TODO | ||
export function testWilderChildMixedAccess(test:nodeunit.Test):void{ | ||
async.series([ | ||
firebase_io.assertSetValidationRules.bind(null, compiler.compile("test/cases/wilderchildHierarchicalAccess.yaml", true).code, test), | ||
test_utils.assert_admin_can_write.bind(null, "/",{}, test), | ||
//root can write anywhere | ||
test_utils.assert_can_write.bind(null, "root","/", "payload", test), | ||
test_utils.assert_can_write.bind(null, "root","/a", "payload", test), | ||
test_utils.assert_can_write.bind(null, "root","/a/a", "payload", test), | ||
//child can write first two level | ||
test_utils.assert_cant_write.bind(null, "child","/", "payload", test), | ||
test_utils.assert_can_write.bind(null, "child","/a", "payload", test), | ||
test_utils.assert_can_write.bind(null, "child","/a/a", "payload", test), | ||
//grandchild can write only last level | ||
test_utils.assert_cant_write.bind(null, "grandchild","/", "payload", test), | ||
test_utils.assert_cant_write.bind(null, "grandchild","/a", "payload", test), | ||
test_utils.assert_can_write.bind(null, "grandchild","/a/a", "payload", test), | ||
], test.done.bind(null)); | ||
}*/ |
@@ -11,3 +11,3 @@ var fs = require("fs"); | ||
console.log("working?", checkScenario("./test/scenarios/parent3.yaml")); | ||
console.log("working?", checkScenario("./test/scenarios/schemaless.yaml")); | ||
} | ||
@@ -18,9 +18,17 @@ | ||
var source = scenario.getOrThrow("source", "scenario has no 'source' attached " + path); | ||
var expected = scenario.getOrThrow("expected", "scenario has no 'expected' outcome " + path); | ||
var result = compiler.compileJSON(source); | ||
var expectedNormalised = JSON.stringify((expected.toJSON())); | ||
var resultNormalised = JSON.stringify(JSON.parse(result.code)); | ||
console.log("expectedNormalised", expectedNormalised); | ||
console.log("resultNormalised ", resultNormalised); | ||
return expectedNormalised == resultNormalised; | ||
if (scenario.has("expectedError")) { | ||
var expectedError = scenario.getOrThrow("expectedError", "scenario has no 'expected' outcome " + path); | ||
var result = compiler.compileJSON(source); | ||
return false; | ||
} else { | ||
var expected = scenario.getOrThrow("expected", "scenario has no 'expected' outcome " + path); | ||
var result = compiler.compileJSON(source); | ||
var expectedNormalised = JSON.stringify((expected.toJSON())); | ||
var resultNormalised = JSON.stringify(JSON.parse(result.code)); | ||
console.log("expectedNormalised", expectedNormalised); | ||
console.log("resultNormalised ", resultNormalised); | ||
return expectedNormalised == resultNormalised; | ||
} | ||
}; | ||
@@ -27,0 +35,0 @@ |
@@ -16,3 +16,3 @@ /// <reference path="../types/nodeunit.d.ts" /> | ||
//called if this file is run, used to enable runtime debugging | ||
console.log("working?", checkScenario("./test/scenarios/parent3.yaml")) | ||
console.log("working?", checkScenario("./test/scenarios/schemaless.yaml")) | ||
} | ||
@@ -23,9 +23,18 @@ | ||
var source = scenario.getOrThrow("source", "scenario has no 'source' attached " + path); | ||
var expected = scenario.getOrThrow("expected", "scenario has no 'expected' outcome " + path); | ||
var result = compiler.compileJSON(source); | ||
var expectedNormalised = JSON.stringify((expected.toJSON())); | ||
var resultNormalised = JSON.stringify(JSON.parse(result.code)); | ||
console.log("expectedNormalised", expectedNormalised); | ||
console.log("resultNormalised ", resultNormalised); | ||
return expectedNormalised == resultNormalised; | ||
if (scenario.has("expectedError")) { | ||
var expectedError = scenario.getOrThrow("expectedError", "scenario has no 'expected' outcome " + path); | ||
var result = compiler.compileJSON(source); | ||
return false; //todo we need to grab stderr | ||
} else { | ||
var expected = scenario.getOrThrow("expected", "scenario has no 'expected' outcome " + path); | ||
var result = compiler.compileJSON(source); | ||
var expectedNormalised = JSON.stringify((expected.toJSON())); | ||
var resultNormalised = JSON.stringify(JSON.parse(result.code)); | ||
console.log("expectedNormalised", expectedNormalised); | ||
console.log("resultNormalised ", resultNormalised); | ||
return expectedNormalised == resultNormalised; | ||
} | ||
}; | ||
@@ -32,0 +41,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
606004
150
446
6776
+ Addedsource-map-support@0.3.2(transitive)
+ Addedtv4@1.1.12(transitive)
- Removedsource-map-support@0.2.7(transitive)
- Removedtv4@1.0.16(transitive)
Updatedsource-map-support@0.3.2
Updatedtv4@1.1.12