I have a collection UserActivity
, where each docId
is the id of the user. Under different docId
s I have subcollection profileVisit
where I want to put some data My firebase rule, should allow only create operation. That is, user can create subcollection under Useractivity/{userId}/profileVisit
only if they are logged in and they own this resource. So my firebase rule is the following:
match /UsersActivity/{userId} {
match /profileVisit {
allow create: if userIsAuthenticated() && userOwnsResource(userId);
}
}
function userIsAuthenticated () {
return request.auth.uid != null;
}
function userOwnsResource (userId) {
return request.auth.uid == userId
}
That is, thefollowing operation should be allowed:
firebase
.firestore()
.collection("UserActivity")
.doc(uid)
.collection("profileVisit")
.add({
data: "some data",
});
The test which I wrote is the following:
it("Users can create subcollection profileVisit under their own UsersActivity document if they are signed in", async () => {
const db = getFirestore(auth);
const userDoc = db
.collection("UsersActivity")
.doc(myId)
.collection("profileVisit");
await firebase.assertSucceeds(userDoc.add({ data: "data" }));
});
This test fails with: FirebaseError: 7 PERMISSION_DENIED: false for 'create'
Can someone explain to me why does my test fail? Have I written my rule correctly or is it the test written in the wrong way?
EDIT
Seems that changing the rule to:
match /UsersActivity/{userId} {
match /profileVisit/{id} {
allow create: if userIsAuthenticated() && userOwnsResource(userId);
}
}
allows my test to pass. That is I changed match /profileVisit
to match /profileVisit/{id} {
Can someone explain me why there is a difference and why I need to add {id}
in the end?
CodePudding user response:
As you discovered yourself in your edit, this doesn't do anything:
match /UsersActivity/{userId} {
match /profileVisit {
allow create: if userIsAuthenticated() && userOwnsResource(userId);
}
}
The match /profileVisit
matches the profileVisit
collection, but no documents in that, so it's a noop.
To make it match any document, use:
match /UsersActivity/{userId} {
match /profileVisit/{docId} {
allow create: if userIsAuthenticated() && userOwnsResource(userId);
}
}