I'm trying write rules for my firebase firestore. But it's not working and return 'Simulated write denied'. What sholud i do. I add screenshots below;
You have your location to create document set to /Users/{KullaniciId} and the UID is XnLOSW..... so that if statement is actually 'KullaniciId' == 'XnLOSW...'. Change your location to:
/Users/XnLOSW...
Now {KullaniciId} will have the value from your location and should pass the rule.
Related
In my Firestore database, I have a document with a Map called 'Videos'.
In it, I add another Map into it that includes my video data.
So it looks like this:
Videos (Map) :
2022-Oct-03-14:24 (Map):
Title: Hi
Now what I want to do is, add another Map to the Videos with a different date.
How do I do this in Flutter?
Currently, I am doing:
db.collection('Collection').doc('Document').update({
'Videos': {
'2022-Oct-03-14:55': {
'Title': 'Ok'
}
}
});
But what this does is, it overrides the entire Videos map and assigns this new map I give, so the old Map with the Title Hi gets deleted. How do I insert new maps?
While Alex's answer is correct if you had an array field, you only have map fields. In that case, you can use . notation to updates/write only the nested field:
db.collection('Collection').doc('Document').update({
'Videos.2022-Oct-03-14:55.Title': 'Ok'
});
Also see the Firebase documentation on updating a field in a nested object.
For adding a new object inside the Videos map, you have two options available. The first one would be to use the . (dot) notation, as #FrankvanPuffelen mentioned in his answer, which will work perfectly fine. This means that it will indeed create the Videos field if it doesn't exist, and it will add the 2022-Oct-03-14:55 subfield inside it if that doesn't exist, and then the Title you put in there. However, since it's an update operation, this solution will work only if the document already exists, otherwise, it will fail.
If you need to create the Videos field inside a document that doesn't already exist, then you should consider using the set() function with merge true. However, this solution doesn't work using the . notation. So for that, I recommend you check my answer in the following post:
Problem with the initial creation of a map structure within a document in firestore
The second solution would be to read the document/map first. It's not mandatory but it will help you check the existence of an existing object. Why, because those objects are maps, and when it comes to maps, if you add a record that has the same key, then it replaces the old value with the new one. So I recommend you have to check that first.
So in order to perform the addition operation, you have to:
Read to read the document.
Get the Videos map in memory.
Check if a video already exists.
Add the new map inside the Videos.
Write the document back to Firestore.
If you'll have a map with the exact same key as a previous key, then the data will be overwritten, meaning that you'll don't see any change in the key, but only in the value if it's different.
I'm still learning about Flutter with firebase.
So, I want to make a to-do-list (TDL) app, that can shows TDL item in the home page.
TDL can have 1 of these 3 status (selesai [finished], belum [not yet], telat [late]),
and i wanted to show the ones which status is belum and telat, or simply the ones which status is not equal to selesai, and has the idProject equal to "0".
Simply i need to show TDL which has idProject = "0" and status!="selesai".
So i wrote this:
static Stream<QuerySnapshot> getDataTDL() {
return CToDoList
.where("status",isNotEqualTo:"selesai")
.where("idProject",isEqualTo: "0")
.snapshots();
}
here's a quick look on my data at firebase.. So, basically it should at least return this one -actually there's few more datas it can return- because it matched my where-clause requirements, but in fact it returns nothing at all.
So what can i do now?
As your query contains both a not equal and an is equal comparison, you will have to create a composite index for the query. If you check the error logs of the flutter process, Firestore should give you a link you could use to create the index. If you can't find the link you would have to manually create it in the Firebase console for the project. More info is here.
Here are my firestore rules:
match /databases/{database}/documents {
match /customers/{customerId} {
allow write: if exists(/databases/$(database)/documents/$(request.resource.data.referred_by));
allow read: if true;
}
}
The following data does not pass this rule(I was able to create the data from client app by removing the exists(/databases/$(database)/documents/$(request.resource.data.referred_by)):
So how do we deal with the reference field so that I can validate whether this reference exists already or not?
EDIT:
The type of the referred_by field is reference.
It seems that its a limitation of firestore at this stage. We are not able to validate whether a reference exists or not.
I further did some digging using the rules playground. The request.resource.data.referred_by has a path child. So I used $(request.resource.data.referred_by.path). Still that did not work because the $(request.resource.data.referred_by.path) resolves to customers%2FB85CSuRJQZWUKt2jgxOy (url-encoded).
I don't know of a way to url decode this in firestore rules.
So at this time I am changing my data models to use referred_by as a 'string' instead of a reference.
I hope this thing is resolved in future by firestore team.
Firebase Database
I tried using this bit of code but it doesn't seem to work. I take the name the user selects and store it in nameList.
Lets say I store Blake Wodruff in nameList[0].
How do I remove only that name?
var nameList = [String](repeating: "", count:100)
func remove() {
print(nameList[countAddNames])
let usernameRef = Database.database().reference().child("Candidate 1").child("alton").child(nameList[countAddNames]);
usernameRef.removeValue();
}
To write to or delete a node, you must specify its entire path. So to delete node 0 from your JSON, you'd do:
let usernameRef = Database.database().reference().child("Candidate 1").child("alton").child("0");
usernameRef.removeValue();
Or a bit shorter:
let usernameRef = Database.database().reference().child("Candidate 1/alton/0");
usernameRef.removeValue();
If you only know the name of the user you want to remove, you'll need to first look up its index/full path before you can remove it. If you have the data in your application already, you can do it in that code. Otherwise you may have to use a database query (specifically .queryOrderedByValue and .queryEqualToValue) to determine where the value exists in the database.
Also see: Delete a specific child node in Firebase swift
Once you remove a value from your JSON structure, Firebase may no longer recognize it as an array. For this reason it is highly recommended to not use arrays for the structure that you have. In fact, I'd model your data as a set, which in JSON would look like:
"alton": {
"Jake Jugg": true,
"Blake Wodruff": true,
"Alissa Sanchez": true
}
This would automatically:
Prevent duplicates, as each name can by definition only appear once.
Make removing a candidate by their name as easy as Database.database().reference().child("Candidate 1/alton/Jake Jugg").removeValue()
For more on this, also see my answer to Firebase query if child of child contains a value
I'm trying to write a security rule for firestore DB and I'm having trouble for some reason. Does the syntax in the following code look wrong to anyone?
match /posts/{postType} {
allow read: if true;
allow write: if get(/databases/$(database)/documents/posts/$(postType)).data.creator_id ==
request.auth.uid;
}
I attached a screenshot of the path and the data structure. The problem I am getting is "get" is returning null.
Data & Path:
error:
You must change the rule.
Instead of:
allow write: if get(/databases/$(database)/documents/posts/$(postType)).data.creator_id == request.auth.uid;
You must write:
allow write: resource.data.creator_id == request.auth.uid;
request.resource.data.creator_id == request.auth.uid was the solution!
You're not using the simulator correctly. When asked to enter the path of the document to get, you must provide a path to an actual document. Do not type the wildcard from the match. The rules will determine the actual value of the wildcard at the time the rule is evaluated. If you enter "/posts/{postType}", you are telling it to literally load a document with the ID "{postType}", which doesn't exist.