While Pipeline operations offer a rich set of
features, the Rules engine is restricted to recognizing comparison (e.g. >
) and logical (e.g. or
) filters to ensure
constraint satisfiability and security.
Supported Filter Expressions
For Pipeline operations to be constrained to the bounds set by your rules, it must use logical and comparison operators against constants. The following filter types are recognized by the Rules engine:
- Comparisons:
eq,neq,gt,gte,lt,lte,in,arrayContains. - Logical:
and,or.
Here are some examples:
-
where(eq("foo", 2)) -
where(lt("foo", 2)) -
documents("/user/1", "/user/2").where(...)
Request Properties
You can continue to use the request
object to validate authentication and query context, though some properties
available in standard queries are not supported in Pipeline operations.
Supported properties
The new engine continues to support the following properties:
-
request.auth: Access user uid and token data. -
request.method: Identifies the operation (For example,get,list). -
request.path: The path of the resource being accessed. -
request.time: The server-side timestamp of the request.
Unsupported properties
The request.query
properties such as limit
, offset
, and orderBy
are
unsupported for Pipeline operations rule checks due to the complexity of determining these
values in multi-stage queries.
Pipeline stage handling and permissions
There are different pipeline stages that map to specific granular operations in security rules:
-
allow listpermissions: Triggered bycollection(),collectionGroup(), anddatabase()stages. -
allow getpermissions: Triggered by thedocuments()stage, which is treated similarly to a batchgetoperation. - Literals stage: The
literals()stage does not read from the database but can incur costs. To prevent abuse, it must be paired with another stage (likecollection()) that can be verified by rules.
Field modification stages
Rules only operate on stored data and not derived values. If a pipeline includes
stages that modify fields (For example, add_fields(...)
, replace_with(...)
, select(...)
, remove_fields(...)
),
the Rules engine stops applying filter constraints after that stage is
encountered. To ensure that rules works as expected, position your filter stages
(i.e. where
) before any stages that can modify the original stored documents.
For example, take the following security rule:
match
/
databases
/
{
database
}
/
documents
{
match
/cities/{city
}
{
//
Allow
the
user
to
read
data
if
the
document
has
the
'visibility'
//
field
set
to
'public'
allow
read
:
if
resource
.
data
.
visibility
==
'public'
;
}
}
Denied
: This rule rejects the following pipeline because the addFields
stage
occurs before filtering to documents where visibility
is public
:
const
results
=
await
db
.
pipeline
()
.
collection
(
"/cities"
)
// Filters after a modification stage are ignored by Rules.
.
addFields
(
constant
(
1000
).
as
(
"population"
))
.
where
(
eq
(
field
(
"visibility"
),
constant
(
"public"
)))
.
execute
();
Allowed
: This rule allows the following
pipeline because the where(eq(field("visibility"), constant("public")))
stage
occurs before any modification stages:
const
results
=
await
db
.
pipeline
()
.
collection
(
"/cities"
)
.
where
(
eq
(
field
(
"visibility"
),
constant
(
"public"
)))
.
addFields
(
constant
(
1000
).
as
(
"population"
))
.
execute
();

