Use Predefined Variables
There are a number of helpful, predefined variables that can be accessed inside a security rule definition. Here is a brief summary of each:
Variable Description now
The current time in milliseconds since Linux epoch. This works particularly well for validating timestamps created with the SDK's Webcom.ServerValue.TIMESTAMP. root
A RuleDataSnapshot representing the root path in Webcom as it exists before the attempted operation. newData
A RuleDataSnapshot representing the data as it would exist after the attempted operation. It includes the new data being written and existing data. data
A RuleDataSnapshot representing the data as it existed before the attempted operation. $variables
A wildcard path used to represent ids and dynamic child keys. auth
Represents an authenticated user's token payload.
These variables can be used anywhere in your Security and [[service]] Rules. For example, the security rules below ensure that data written to the /foo/
node must be a string less than 100 characters:
{
"rules": {
"foo": {
// /foo is readable by the world
".read": true,
// /foo is writable by the world
".write": true,
// data written to /foo must be a string less than 100 characters
".validate": "newData.isString() && newData.val().length < 100"
}
}
}
Make Your Rules Dynamic
Your Security and [[service]] Rules should follow the structure of the data you have stored in your [[service]]. For example, say you are keeping track of a list of messages and that your data looks like this:
{
"messages": {
"message0": {
"content": "Hello",
"timestamp": 1405704370369
},
"message1": {
"content": "Goodbye",
"date": 1405704395231
},
...
}
}
Your rules should be structured in a similar manner. We can make use of $
variables in rules which represent dynamic child keys. In addition, we can use .validate
rules to ensure our data is properly structured. For example, the $message
variable below represents each of the /messages/
node's children:
{
"rules": {
"messages": {
"$message": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// new messages must have a string content and a number timestamp
".validate": "newData.hasChildren(['content', 'timestamp']) && newData.child('content').isString() && newData.child('timestamp').isNumber()"
}
}
}
}