The syntax for specifying the syntax of a rule that you might want to declare in order to protect documents in a Firestore collection are specified at https://firebase.google.com/docs/reference/security/storage. But this describes the wider context of Google Cloud storage and consequently, when you're trying to use these specifically for Firestore applications, the documentation seems a bit opaque.
The match
statement used to specify the subset of documents in a collection myCollection to which the rule is to be applied typically takes the form:
match myCollection/{wildcard}
My question is "what variables are available for use as wildcards?". According to the Google document referenced above "A wildcard variable is declared in a path by wrapping a variable in curly braces: {variable}. This variable is accessible within the match statement as a string."
I now understand that if myCollection
contains a field called email
for example, a match statement of the form
match myCollection/{email}
will allow me to specify a rule to be applied to a document whose documentId is the value specified by the email field. In this case, a rule to allow only logged-in users to read their own record in myCollection
would take the form:
match myCollection/{email}
allow read : if request.auth != null && request.auth.token.email == email;
where email is the user's email address filed in myCollection
But supposing that email isn't being used as the unique key to identify a myCollection
record - ie that other fields identify documents and a user may have many records tagged with their email within myCollection? This is surely the more likely case but the Google documentation doesn't seem to give any clues to how you would specify a match to cover this situation.
A previous stackoverflow question at How write Firestore rule to match email field in document has directed me towards the keyword doc
. This has allowed me to specify a more general rule that can be applied to all the records in a collection with a particular email value:
match /myCollection/{doc} {
allow read : if request.auth != null &&
request.auth.token.email == resource.data.email;
}
There are two concepts here that are new to me (at least in the context of Firestore rules): first the keyword doc
and second the resource.data.email
construct that gives my rule access to document fields. Can anybody tell me where these constructs are documented, and also if there are any more "wrinkles" to the "wildcard" concept (I already know about the documents=** one).
CodePudding user response:
match myCollection/{wildcard}
- This rule tells firebase to match all documents in the myCollection collection. Essentially, it says match all documents that match this path myCollection/*
wildcard
above is simply a variable that holds the document path (the asterisks path). This variable can be anything (apart from the reserved strings). If this is your path:
- 'myCollection/tests', then wildcard variable is holds 'tests';
- 'myCollection/[email protected]', then wildcard variable holds '[email protected]'
wildcard
is simply a place holder for anything that matches this path: myCollection/*
. Instead of wildcard, you can use anything e.g email (myCollection/{email}
and email here becomes the variable that holds the document path).
resource.data
is the data being fetched. So if your data has an 'email' field, then resource.data.email
always holds the email field data (regardless of what the wildcard variable is). Do not use reserved strings e.g 'resource' as the wildcard variable.
what variables are available for use as wildcards?
Any variable you put in curly braces becomes the wildcard variable. It simply holds the document path. It is not a special string.
UPDATE @MartinJ.
For autogenerated ids. Lets assume this is your doc path myCollection/1s6SUqi8M6sC6DZdTKjt
, (1s6SUqi8M6sC6DZdTKjt is autogenerated)
match /myCollection/{email} {
allow read : if email == '1s6SUqi8M6sC6DZdTKjt'; // true because
// email variable holds the value '1s6SUqi8M6sC6DZdTKjt'
}
match /myCollection/{doc} {
allow read : if doc == '1s6SUqi8M6sC6DZdTKjt'; // true because
// doc variable holds the value '1s6SUqi8M6sC6DZdTKjt'
}
match /myCollection/{stackoverflow} {
allow read : if stackoverflow == '1s6SUqi8M6sC6DZdTKjt'; // true
// because stackoverflow variable holds the value '1s6SUqi8M6sC6DZdTKjt'
}
// It does not matter what we use as wildcard variable (we can even
// use MartinJ), it will always hold the value of '1s6SUqi8M6sC6DZdTKjt'
// (doc id if the path matches).
// As @Frank said, these are simply variables, not keywords. You
// can call it anything and it will have the value of doc path.
}
if this is your document path sales/2K5CwGU9ZWwNoO9efyuv/payments/40ciObsicEntBZParkon
(autogenerated document ids)
match /sales/{doc=**} {
allow write: if doc == '2K5CwGU9ZWwNoO9efyuv/payments/40ciObsicEntBZParkon';
// this will be true because doc=** (**with asterisks**) matches
// everything after sales
}
match /sales/{saleId} {
match /payment/{paymentId} {
allow write: if saleId == '2K5CwGU9ZWwNoO9efyuv' && paymentId == '40ciObsicEntBZParkon';
// this will be true because saleId holds the value
// '2K5CwGU9ZWwNoO9efyuv' and paymentId holds this value '40ciObsicEntBZParkon'
}
}
CodePudding user response:
The answer to "where (are) these constructs are documented?" is "at Basic Security Rules". Here, at "Attribute-based and Role-based access", this describes the use of a {document} "wildcard" that represents any document that matches the rule that follows.