DOUG STEVENSON: Hey, gang.
Welcome back to the series on Firebase security rules.
Last time, I gave you an overview of some of the things
you can do.
This time, we'll get into some of the syntax that
helps you match objects in your Cloud Firestore database.
Matching documents is the first step
in writing a rule to protect data
when it's accessed using the Firebase web and mobile SDKs.
The first thing to know is that every document in your database
has a unique path.
You've probably already used these paths in your app
in order to read and write documents.
This code over here is building a reference
to a document with ID Sparky in a collection called users.
In case you didn't know, the name of the Firebase mascot
is Sparky.
How's it going over there, Sparky?
Anyway, in terms of this document's path,
you might think of it like this string.
This is pretty straightforward, and you can even
use this string directly to build the document
reference like this.
Now, if you want to control access
to this document using security rules,
you will need to use this path.
Let's take a look at the required boilerplate
for Firestore rules.
Here, we have the Cloud Firestore service identified
at the top level, and nested under that
we have a match clause, which is followed by something
that looks like a path.
It starts with the component databases followed
by the word database in curly braces
and another component, documents.
What this match directive is saying
is that the stuff nested inside it
is going to be used to match documents
anywhere within your database.
The database in curly braces there is a wild card,
and it matches your project's database.
Currently, there is only one value that it will match
and that's default in parentheses,
as each project can only have one Firestore database.
But it's a standard practice to use a wildcard here.
Again, this is all boilerplate so far.
But I'll nest another match that calls out
the path of the document to protect,
and the nested allow statement gives everyone
read access to it.
Now, it's super important to note here
that all documents in the database
are by default denied access by security rules
when accessed from a mobile or web client.
What security rules let you do it selectively allow access
to documents based on the criteria you define.
Now I find it unlikely that anyone
would need to write a rule for one particular user's
document, like this.
Typically what you need to do is write
rules that apply to all users in your app,
and you typically sign them in using Firebase authentication.
To match all users' documents in the user's collection,
you want to use another wildcard,
just like with the database in the line above.
The organization for most user based collections
makes use of the Firebase authentication user ID
as the ID of the document that belongs to that user.
A Firebase authentication user ID is called a UID for short,
so I'll name the wildcard as such and put it in curly braces
to make it a wildcard match.
So now all documents in the user's collection
are readable by everyone, but no one can write anything yet.
The useful thing about wildcards is
that they become string variables
that you can use in the expression
that you write to allow access.
I'll take advantage of this to indicate
who can specifically read and write
each document in this collection.
So I'll add another line here, which
says that the only user that can write the match document
is the Firebase Auth account with the UID
that's the same as the UID wildcard string value.
Now everyone can read everyone else's user document,
but only the currently authenticated user
can write their own document.
I'll say a lot more about how authentication
works with security roles in a future video.
It's important to note here that these wildcards can only
match an entire path segment between the nearest
slashes in the path.
There are no substring matches and there are
no regular expressions, either.
But there is a glob type of wildcard,
which I'll talk about later and I
will say that you can perform additional checks
against the wildcard variable string in the allow expression,
including regular expressions.
But that's another topic for another video.
Now you might be wondering, what about subcollections
organized under a document ID?
Well, let's say you're storing references
to photos for each user and you've
decided to do that with a subcollection called
photos organized under each user's document.
You can match those documents in the subcollection
by extending the match path and adding
another wildcard to match all the documents in each
of the user's photos subcollection.
I've removed some of the boilerplate
here to keep things easier to read.
Notice how the user's collection-- the user document
ID, the photo subcollection, and the photo document ID
are all represented in the match path here.
Now, let's say we only want people to read and write
their own photos for now, so we'll add a line here
to allow access on that condition.
Notice here that both read and write access
are given with a single expression.
Now here's one very important thing
to keep in mind about matching documents.
If the path of the document being accessed
doesn't have a full path match with the rule,
that rule will not apply.
So the entire path of the document-- the collection date,
the document ID, the subcollection, and so on--
all must be represented in the match path.
Now let's look at all of the documents and rules shown
so far.
The document referenced by doc ref
is only affected by the first match
since it's not using the photos collection,
and the document referenced by photo ref
is only affected by the second rule.
As you can see, the photos subcollection
is effectively a completely different collection
than users, even though it's nested under users.
This is not always obvious at first
when you're getting started with Cloud Firestore,
but the rules here make that more clear.
Using subcollections like this to change the permissions
of various pieces of data that are associated with the user
is a very good practice.
You should always model your data
in Cloud Firestore with security rules in mind.
Think carefully about which users
you want to be able to access which content.
There's a lot to discuss on this topic,
and I'll cover that in future videos.
But I'll leave you with one trick
for organizing your rules, if you choose to use it.
If you recall before, the boilerplate
for Firestore security rules has a top level match
for all the documents in your database
and all your document rules get nested underneath it.
Sometimes doing your own nesting can save you
some space and typing.
Since the photos subcollection is effectively
nested under documents in the user's collection,
we can nest the match for photo documents
inside the match for users, like this.
See how the prefix of users and the wildcard UID
are now implied by the outer match,
and you can also use the UID variable from the outer match
just fine in the inner match.
Of course, this nesting is optional,
but you might prefer it.
Oh, and just one more little thing--
I've been using the word variable
to refer to the UID and photo ID wildcard strings.
Well, that's not really the best word
because these variables can't be changed.
The values are constant at the time of evaluation
when a specific document is being read or written.
There are no true variables in security rules.
You can only use their values as is.
Before we wrap up here, take a look at this rule.
I'm sure you might recognize it.
It's the rule that your database probably
started with when you created your project if you
chose the initial test mode for your database.
There is an equal star star in the document wildcard here.
This is a special kind of wildcard,
and this rule is actually matching every single document
in your entire database and granting full read and write
access to each of them.
This rule is OK to get started playing around with Firestore
in a new app, but if the rule sounds problematic,
that's because it is.
It's actually very problematic when it comes time
to write effective rules.
So when you start writing rules, first get rid of this one
and I'll say more about why in the next episode of the series.
So stay tuned right here to the Firebase channel on YouTube,
and I'll see you then.
[MUSIC PLAYING]