Tutorial: Using rules for validation

Step by stepSecurity Using rules for validation

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()"
            }
        }
    }
}