Tutorial: Using rules for validation

Serverless DatabaseSecurity Rules 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 Webcom 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 Webcom Rules should follow the structure of the data you have stored in your Webcom. 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()"
			}
		}
	}
}