I have application which have multiple users, one of the major thing left is to block and report users in firebase.
I am trying to look for the solution for the same by googling for it, but till now not any particular success.
I would like to know how I can achieve that. Please guide me for that,
and how the firestore security rules should be to achieve the same?
The typical approach is to have a collection that contains the blocked users, with one document for each blocked user and with the ID of that document being the UID of that user.
With that structure in place, your security rules can check for the existence of such a document and then block the user.
There's a great example of this in the blog post 7 tips on Firebase security rules and the Admin SDK (it's tip 7). The rules from there:
service cloud.firestore {
match /databases/{database}/documents {
function isBlackListed() {
return exists(/databases/$(database)/documents/blacklist/$(request.auth.uid))
}
// Collections are closed for reads and writes by default. This match block
// is included for clarity.
match /blacklist/{entry} {
allow read: if false;
allow write: if false;
}
match /posts/{postId} {
allow write: if !isBlackListed()
}
}
}
Related
I'm new developer working on my first Firestore app. I've changed the rules on Firestore to make the data more secure for user, but it's not allowing read/write.
This is the key line and I don't know how to configure it specific to my app -
match /some_collection/{userId}/{documents=**} {
I don't know if I change the "some_collection" to my collection name or if some_collection in that sense is an actual wildcard type of parameter itself.
Also, do I need to pass in the userID somehow from my swift application to Firestore? where is userID coming from in this line? I'd prefer to make the rule such that only the user who created the data can read/write. I believe this block is to allow any authenticated user, so I'm just trying to explore each step.
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /some_collection/{userId}/{documents=**} {
allow read, write: if request.auth != null && request.auth.uid == userId
}
}
}
Addressing your questions:
This is the key line and I don't know how to configure it specific to my app.
match /some_collection/{userId}/{documents=**}
I don't know if I change the "some_collection" to my collection name or if some_collection in that sense is an actual wildcard type of parameter itself.
In the line above "some_collection" is not a firestore wildcard and you need to replace some_collection with the actual value of your collection.
Also, do I need to pass in the userID somehow from my swift application to Firestore?
Yes and it is expected that before reading or writing to/from firestore:
You had already created and configured the firebase object.
firebase.initializeApp({
apiKey: '### FIREBASE API KEY ###',
authDomain: '### FIREBASE AUTH DOMAIN ###',
projectId: '### CLOUD FIRESTORE PROJECT ID ###'
});
You had already authenticated your users with firebase auth.
firebase.auth().signInWithCustomToken(token)
.then((user) => {
// Signed in
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
Passing the userId is done by the firebase object when you call db. collection(“col123”).add or any other method. If you look at how firestore is initialized:
var db = firebase.firestore();
You will see its dependency with the firebase object.
where is userID coming from in this line?
The userID is coming from the firebase object.
I believe this block is to allow any authenticated user, so I'm just trying to explore each step.
Yes, the last rules allow any authenticated user to read and write from/to the subcollections/documents wildcard {userId}.
Lastly it is also expected that there is some naming consistency in the ids of your firestore documents or subcollections.
This means when you create firestore documents, use the firebase.auth.uid as the document id.
Otherwise, the rule from above will fail because the value behind {userId} is not equal to firebase.auth.uid of the logged user.
To achieve the latter, you can refer to this answer.
I highly recommend you have a look at this video(from the firebase channel) since it elaborates more on the core concepts of firestore security rules.
I hope you find this useful.
I’ve seen all around the documentation that Query-based sync is deprecated, so I’m wondering how should I got about my situation:
In my app (using Realm Cloud), I have a list of User objects with some information about each user, like their username. Upon user login (using Firebase), I need to check the whole User database to see if their username is unique. If I make this common realm using Full Sync, then all the users would synchronize and cache the whole database for each change right? How can I prevent that, if I only want the users to get a list of other users’ information at a certain point, without caching or re-synchronizing anything?
I know it's a possible duplicate of this question, but things have probably changed in four years.
The new MongoDB Realm gives you access to server level functions. This feature would allow you to query the list of existing users (for example) for a specific user name and return true if found or false if not (there are other options as well).
Check out the Functions documentation and there are some examples of how to call it from macOS/iOS in the Call a function section
I don't know the use case or what your objects look like but an example function to calculate a sum would like something like this. This sums the first two elements in the array and returns their result;
your_realm_app.functions.sum([1, 2]) { sum, error in
if let err = error {
print(err.localizedDescription)
return
}
if case let .double(x) = result {
print(x)
}
}
I am trying to set a firebase security rules for all collections in one collection with Firebase Firestore. I have a collection named Chats inside of it I have two collection one is thread and the other is users. All the documents ids are random.
This is how my Firebase Data Looks Like:
I am trying to set the security for all the chats & thread & users. Because chats includes the thread collection and the user collection but when setting the rule below: it does not work properly: Missing or insufficient permissions.
// Chats can be read & written by all users
match /Chats/{document} {
allow read, create, update, delete, write: if true
}
I also tried:
match /Chats/{document}/thread/{document1} {
allow read, create, update, delete, write: if true
}
match /Chats/{document}/users/{document2} {
allow read, create, update, delete, write: if true
}
But it did not work, so if someone can please help me with it.
Your current rules only matches documents in the /Chats collection:
match /Chats/{userId}
To make it also match the subcollections , it'd have to be:
match /Chats/{document=**} {
Also see the Firebase documentation on securing hierarchical data, specifically the section on recursive wildcards.
I am working on a Forum-like structure using Firebase Store / Firebase Rules. My structure is something like this:
Collection --- Document ------ Collection --- Document
Topic1 CreationDate UsersJoined UserUID1
Topic2 Title UserUID2
Topic3 UpdatedDate UserUID3
... ... ...
Basically, each Topic has a Collection of Users. My goal is to be able to write a security rule where only Users in the 'UsersJoined' can read/write to the corresponding Topic. This is what I have right now as my rules:
service cloud.firestore {
match /databases/{database}/documents {
match /Topics/{topicUID} {
allow read, create, update, delete: if exists(/databases/$(database)/documents/Topics/$(topicUID)/UsersJoined/$(request.auth.uid));
match /UsersJoined/{userUID=**} {
allow read, create, update, delete;
}
}
}
}
So when I use the built in Simulator, the read works just fine; however, when I request to read it via my code for IOS, it tells me that I don't have sufficient permission.
I've tried just doing allow read: if request.auth.uid != null;, and I am able to read. I am confident that the UserUID does exist within the UsersJoined collection.
I've also tried creating a "sister" collection where I store my User IDs in, so my structure looks like this:
Collection ----------- Document
MyTestUserCollection UserUID1
Topic1 UserUID2
Topic2 ...
...
I then used this rule: if exists(/databases/$(database)/documents/MyTestUserCollection/$(request.auth.uid)); and the read works as well, both on the simulator and IOS codes.
My problem is not being able to read when the User List is nested within the Topic. So my question is... by writing a rule that checks ("reads") data in a nested collection, am I violating the "allow read" rule (since technically it hasn't determined whether I can read yet)? Or am I over complicating things a bit and there is a better way to structure my Collections/Documents? Or am I just not writing the rule correctly?
I don't believe my code on IOS is the issue, but just in case this is what I'm doing to request to read from my database: (the user is logged in via Firebase Auth)
[[myFirestore collectionWithPath:#"Topics"]
getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) {
if (error != nil) {
NSLog(#"Error getting documents: %#", error);
} else {
NSLog(#"Read it");
}
}];
Any help is greatly appreciated!
Your security rules allow a user to read a specific topic, if they are following that topic. Your code tries to read all topics, which your rules don't allow. So that explains why the server rejects the read operation.
This is easiest to remember by realizing that rules themselves don't filter data. They instead either allow a listener or not. And since your rules don't allow a listener on all of /Topics, that listener gets rejected.
One solution is to only read the specific topic that you are a follower of. To determine the topic(s), you might need to store a document with the user's list of topics, such as in a /Profiles collection. This is quite common on NoSQL databases: you're essentially storing both sides of the many-to-many relationship.
Alternatively you can try to validate the query, but I'm not quite sure if that can be made to work for your situation.
The childByAutoId would be useful if you want to save in a node multiple children of the same type, that way each child will have its own unique identifier.
List:{
KJHBJJHB:{
name:List-1,
owner:John Doe,
user_id:<Fire base generated User_id>
},
KhBHJBJjJ:{
name:List-2,
owner:Jane Lannister,
user_id:<Fire base generated User_id>
},
KhBHJZJjZ:{
name:List-3,
owner:John Doe,
user_id:<Fire base generated User_id>
}
}
I am trying to access the List with the help of the following code:
let ref = FIRDatabase.database().reference(withPath: "/List")
The current user logged into the app is John Doe. When the user accesses the list, I want all the List child whose owner is John Doe(i.e. List-1 & List-3) and ignore the other child values.
Do I have to do this in my application or can this be achieved via Firebase Security rules?
My current rule definition is:
"List":{
".read": "root.child('List/'+root.child('List').val()+'/user_id').val() === auth.uid" }
But this rule is not giving me any success. Any idea how to achieve the desired result?
You're trying to use security rules to filter the list. This is not possible and one of the common pitfalls for developers coming to Firebase from a SQL background. We commonly refer to it as "rules are not filters" and you can learn more about it in:
the Firebase documentation
this answer
our new video series Firebase for SQL developers
and many previous questions mentioning "rules are not filters"
The solution is almost always the same: keep a separate list of the keys of posts that each user has access to.
UserLists:{
JohnUid: {
KJHBJJHB: true,
KhBHJZJjZ: true
},
JaneUid: {
KhBHJBJjJ: true
}
}
This type of list is often referred to as an index, since it contains references to the actual post. You can also find more about this structure in the Firebase documentation on structuring data.