fireward
fireward copied to clipboard
Compile errors
Here is a very basic rules file. I ran your tool and it generates the rules file. When I deploy it, I see these errors. I'm not too worried about the unused variable warning, though it would be nice if that went away. But the invalid type warnings are concerning. I'm using firebase tools version 9.19.0
! [W] 4:31 - Unused variable: prev.
! [W] 23:35 - Unused variable: prev.
! [W] 32:53 - Invalid type. Received one of [null]. Expected one of [list, map].
! [W] 35:89 - Invalid type. Received one of [null]. Expected one of [list, map].
type Name = { first: string, last?: string }
type User = { name: Name | string }
type IceCream = { flavor: string, isFavorite: bool }
match /users/{id} is User {
allow read: true;
allow create, update: request.auth!=null;
allow delete: false;
}
match /icecream/{id} is IceCream {
allow read: if request.time < timestamp.date(2021, 12, 1);
allow write: if request.time < timestamp.date(2021, 12, 1);
}
There are no errors on the IceCream
path. The errors have to do with User
.
I don't understand the underlying rules language. But I was able to get it to upload without errors as follows...
I changed resource==null ? null : resource.data
to simply resource.data
. Second I changed prev!=null ? prev : null
to just prev
. I don't know if this changed the behavior/intent of the rules but it made the compiler happy.
Are you still maintaining this repo?
Thank you for reporting. I've experienced the same warnings, but they have not caused any problems in production. Nonetheless I should post this minimal case as an issue to the firebase repo.
you mean this is a problem on their end? the docs say "resource" is non-null so resource==null ? null : resource.data
might be incorrect. https://firebase.google.com/docs/reference/rules/rules.firestore#.resource
doesn't work for me. can't read or delete any items in the icecream collection...
type Name = { first: string, last?: string }
type User = { name: Name }
type IceCream = { flavor: string, isFavorite: bool }
match /icecream/{id} is IceCream {
allow read, write, delete: if request.time < timestamp.date(2021, 12, 1);
}
match /users/{id} is User {
allow read: true;
allow create, update: request.auth!=null;
allow delete: false;
}
This is the rules that were built...
match /icecream/{id} {
function is______PathType(data, prev) {
return is____IceCream(data, prev!=null ? prev : null);
}
allow read, write, delete: if is______PathType(request.resource.data, resource==null ? null : resource.data) && (request.time < timestamp.date(2021, 12, 1));
}
If I delete the whole is______PathType(request.resource.
condition then I can delete items.
(edited - posted wrong rules file before)
Most likely you can't delete items because you have read, write and delete directives on the same line. That's an anti-pattern and will in most cases generate errors.
you mean this is a problem on their end? the docs say "resource" is non-null so
resource==null ? null : resource.data
might be incorrect. https://firebase.google.com/docs/reference/rules/rules.firestore#.resource
The syntax shouldn't cause any errors. In any case, these warnings don't give any useful information.
I hope you'll take a closer look at this. I changed the rules so just read and write are on the line. Without trying to delete anything, I see an error in the browser dev tools when trying to read from the ice cream table, which has a few documents in it. The error is Uncaught Error in snapshot listener: FirebaseError: Missing or insufficient permissions.
Then I simply take out the is______PathType(request.resource.data...
clause using the Firestore console and my app works. So something in that clause is probably not working. Here are the details.
The original rules...
type Name = { first: string, last?: string }
type User = { name: Name }
type IceCream = { flavor: string, isFavorite: bool }
match /icecream/{id} is IceCream {
allow read, write: if request.time < timestamp.date(2021, 12, 1);
}
match /users/{id} is User {
allow read: true;
allow create, update: request.auth!=null;
allow delete: false;
}
The generated rules...
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function is____Name(data, prev) {
return data.keys().hasAll(['first'])
&& data.size() >= 1 && data.size() <= 2
&& data.keys().hasOnly(['first', 'last'])
&& data['first'] is string
&& (
!data.keys().hasAny(['last'])
|| data['last'] is string
);
}
function is____User(data, prev) {
return data.keys().hasAll(['name'])
&& data.size() >= 1 && data.size() <= 1
&& data.keys().hasOnly(['name'])
&& is____Name(data['name'], prev!=null && 'name' in prev ? prev['name'] : null);
}
function is____IceCream(data, prev) {
return data.keys().hasAll(['flavor', 'isFavorite'])
&& data.size() >= 2 && data.size() <= 2
&& data.keys().hasOnly(['flavor', 'isFavorite'])
&& data['flavor'] is string
&& data['isFavorite'] is bool;
}
match /icecream/{id} {
function is______PathType(data, prev) {
return is____IceCream(data, prev!=null ? prev : null);
}
allow read, write: if is______PathType(request.resource.data, resource==null ? null : resource.data) && (request.time < timestamp.date(2021, 12, 1));
}
match /users/{id} {
function is______PathType(data, prev) {
return is____User(data, prev!=null ? prev : null);
}
allow read: if true;
allow create, update: if is______PathType(request.resource.data, resource==null ? null : resource.data) && (request.auth != null);
allow delete: if false;
}
}
}
In the console I changed the ice cream section to this, and it works...
match /icecream/{id} {
function is______PathType(data, prev) {
return is____IceCream(data, prev!=null ? prev : null);
}
allow read, write: if (request.time < timestamp.date(2021, 12, 1));
}
I am investigating further. Writing seems to work. Maybe my error on the reading?
Ok making progress...these rules seem to work. Separating just read
and write
wasn't good enough. I didn't realize you need to separate create
, update
, and delete
. Hmmm...is this my error? I thought you could combine rules, and definitely use write
without breaking it up into separate categories.
match /icecream/{id} is IceCream {
allow read: if request.time < timestamp.date(2021, 12, 1);
allow create: if request.time < timestamp.date(2021, 12, 1);
allow update: if request.time < timestamp.date(2021, 12, 1);
allow delete: if request.time < timestamp.date(2021, 12, 1);
}
You technically can. However, Fireward does not do any extra magic to rewrite your conditions depending on their kind. So if you have them all combined, the type check (isPathType) will be performed on reads and deletes, which will fail.
Usually creates and updates can be combined without problems, because what matters here is the incoming data, but you should do so consciously, knowing that it is a source of possible errors.
In the future Fireward may add some checks, this being a common issue, but we have to be careful, because we are very limited on the size of the rules file as well as the number of operations per execution, so we have to watch our bloat.
Ok you can close this. Maybe Fireward should give a warning if delete and reads are combined, or do something different. It sure looks like my original rule - you can do anything prior to December - should work.
I seem to recall to have added the warning to the beta version, now that you mention it. I'm planning to release it as 2.0 asap.