I want to retrieve all persons (people) where city equal Paris from firebase database.
this is my query, is it correct ?
query = Databaseperson.child("persons").orderByValue().equalTo("Paris")
Data Structure:
-Persons
- KeyPerson1 : CKKJDJOCJJ
-name: Peter
-city: Paris
- KeyPerson2 : WGTHKJHHUH
-name: Oliver
-city: Paris
- KeyPerson3 : XVCDFBJJYF
-name: Anne
-city: New York
You must use roles for search. Like this;
{ "rules": { ".read": true, ".write": true, "persons": { ".indexOn": ["name","city"] } } }
after you can use like this:
query = Databaseperson.child("persons").orderByChild("name").equalTo("Paris")
Related
I'm using Firebase Realtime Database as the datastore for an Android app, and right now I'm trying to implement some basic filtering based on user permissions.
Here's my database:
{
"admins" : {
`user1hash` : true
},
"clients" : {
"client1hash" : {
"owner": "user1hash",
"name" : "Client 1"
},
"client2hash" : {
"owner": "user1hash",
"name" : "Client 2"
},
"client3hash" : {
"owner": "user2hash",
"name" : "Client 3"
}
}
}
I followed the examples in the Query-based Rules section here https://firebase.google.com/docs/database/security/securing-data and defined my rules like this:
{
"rules": {
"clients": {
".indexOn": "owner",
".read": "auth.uid != null && (root.child('admins/' + auth.uid).val() == true || query.orderByChild == 'owner' && query.equalTo == auth.uid)",
".write": "auth.uid != null",
".validate": "newData.hasChildren(['owner']) && newData.child('owner').val() == auth.uid"
}
}
}
And this is my client code (Android):
FirebaseDatabase database = FirebaseDatabase.getInstance();
String authUser = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference clientsDatabase = database.getReference("clients").orderByChild("owner").equalTo(authUser).getRef();
clientsDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// handle success
}
#Override
public void onCancelled(DatabaseError databaseError) {
// handle error
}
});
So basically I just want to be able to fetch all clients, but filter the results according to the access rules of the current user. Access rules are pretty simple, an user can only see the clients where he is the owner, except for admin users who can see all clients. For example if this was run by user1 which is an admin he should see all three clients, but if this is run by user2 which is a regular user he should only see client 3.
This implementation is working for admins, but I get a permissions error for regular users.
I tried the rules simulator in Firebase console, but it doesn't provide any documentation on how to use queries. Anyway I tried adding the query as a regular URL query string like /clients?orderByChild=owner&equalTo=user2hash, but this returns an empty error on the simulator with no description of the cause. The error I'm getting on the Android side doesn't have any description either, just a generic permissions error.
The problem is in this statement:
DatabaseReference clientsDatabase =
database.getReference("clients")
.orderByChild("owner")
.equalTo(authUser)
.getRef();
Specifically that last line getRef(), which throws everything away that you've done to build the query. The above statement leaves clientsDatabase exactly the same as:
DatabaseReference clientsDatabase = database.getReference("clients");
Which explains quite well why the statement fails.
You need to keep the Query that you get back and attach your listener on that:
DatabaseReference clientsDatabase = database.getReference("clients");
Query query = clientsDatabase.orderByChild("owner").equalTo(authUser);
query.addListenerForSingleValueEvent(new ValueEventListener() { ...
So I'm using Firebase for my backend on an Android app I'm working on. Currently, my structure looks like this
-root
- users
- email
-email
-firstName
-lastName
-(user_email)AppName
- max
- workouts
- workoutName
- orderNumber
- some push key id
- exercise
- reps
- sets
I'm storing max and workouts under each individual user (user_email + AppName). I want to send workoutName to another user's workouts node. How would I go about this in my rules, and how would I do this programmatically? I also want the user that received the workout to only be able to read it. I was thinking about just copying the workoutName node from a user and inserting it into another user's workouts node.
My rules are currently
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
JSON
"testEmail#gmail?comWorkoutTracker" : {
"workouts" : {
"benchDay" : {
"-KyK9ZTc57vvI7QT_UjC" : {
"childCount" : "0",
"exercise" : "Bench",
"reps" : "4",
"sets" : "3",
"view" : "Exercise row",
"weight" : "2"
}
}
}
}
I have set my firebase rules as follows:
{
"rules": {"users": {
"$uid": {
".read": "auth != null",
".write": "$uid === auth.uid"
}}
}
}
Which allows write only to the node with matching uid and read all child nodes of every uid. But I want it to be like if I query using a child node under uid, only the matching child and it's siblings can be read...
for example this is my json structure:
{
"users" : {
"AJkK4yZJsoseeefrJ7i6KIOUBDghtrhgthrtDi1" : {
"lat" : 20.5001,
"long" : 68.3755,
"number" : "9876543210",
"time" : 1499599788090
}
}
}
I want to query using the number, and set the read rule as can read lat long and time only where the number matches. How to write the rule?
update: my question now is, how to query the database using number and get other siblings if value of number matches in android? I have tried this but not working:}
friend = mDatabase.getReference("users");
friend.keepSynced(true);
Query z = LocationActivity.this.friend.orderByChild("number").equalTo("9876054321");
z.addListenerForSingleValueEvent((new ValueEventListener() {
long lastseen;
public void onDataChange(DataSnapshot dataSnapshot) {
try {
for (DataSnapshot zoneSnapshot: dataSnapshot.getChildren()) {
lastseen = (Long)zoneSnapshot.child("time").getValue();
friendLatitude = (Double) zoneSnapshot.child("lat").getValue();
friendLongitude = (Double) zoneSnapshot.child("long").getValue();
}
} catch (Exception e) {
}}
it returns value null, any help would be appreciated.
Firebase read permissions are enforced when you attach a listener. In order to query a node, you must have read permission on that node (as Bradley also explained). So in order to be able to query users, you must have read permission on /users. And since any user that has read permission to /users can also read any data under that, you cannot use security rules to filter what nodes a user has access to.
This is known as rules are not filters and is one of the common pitfalls for developers new to Firebase security model. I recommend that you read the documentation I linked already and some of the many questions/answer about the topic.
The simplest solution for your use-case seem to be to pull up the .read rule to users:
{
"rules": {
"users": {
".read": "auth != null",
"$uid": {
".write": "$uid === auth.uid"
}
}
}
}
}
In order to query every node, the user needs to have read permission for ALL nodes under the parent.
This is because security rules cannot be used to query data in Firebase.
Not exactly sure if this answers the question, but I found this post looking for the following solution with respect to Firebase Storage .. where I can control which sibling nodes are accessible:
match /uploadRoot/{userId}/{uploadCategory}/{allPaths=**} {
// allow read access for client upload/download
allow read, write:
if request.auth != null
&& request.auth.uid == userId
&& (
uploadCategory == 'userTextFiles'
|| uploadCategory == 'userImages'
);
I have a group of comments for different blog posts.
The problem now is every comment displays on every blog post.
Im calling the data with
myref= FirebaseDatabase.getInstance().getReference().child("comments");
Which returns all comments.
This is the data JSON
{
"comments" : {
"-KgnRe9d5s471yDWVYBk" : {
"_id" : "56e35e39106a750e008c33b5",
"_blogID" : "56ba5f6a894eeb0e008c86c0",
"commentKey" : "-KgnRe9d5s471yDWVYBk",
"detail" : "test comment",
"user" : "john",
"votes" : 0
}
Id like to filter all comments by "_blogID"
Thanks
You can use a Query like this: Query query = myref.child(commentKey).orderByChild("_blogID");
I am new with Firebase. I want to implement ondelete cascade in Firebase.
Here is the problem for which I want solution
I have two table "users" and "groups".
{ "users":{
"user1":{
"username":"john",
"full_name":"John Vincent",
"created_at":"9th Feb 2015",
"groups":{
"group1":true,
"group3":true
}
"last_logins":...
},
"user2": ...,
"user3": ...
}"groups": {
"group1"{
"group_name":"Administrators",
"group_description":"Users who can do anything!",
"no_of_users":2,
"members":{
"user1":true,
"user3":true
}
},
"group2"{
"group_name":"Moderators",
"group_description":"Users who can only moderate!",
"no_of_users":1,
"members":{
"user2":true
}
}
}
}
Please pardon me for above code indentation.
Now if I removed user1 from users table then how it should be automatically removed from groups table using Firebase.
This can easily done using SQL but I don't know how to do this in Firebase. One way to do this in Firebase is to remove user1 from users and then makes group1 and group3 to null and then in groups table make user1 to null under group1/member but this need 2-3 calls. So is there any another best way to do this.
Please help me I am stuck here.
The Firebase Database has no knowledge of relations between values in its JSON tree. In SQL/relations terms: it doesn't have the concept of foreign keys. This means that it also doesn't have an option to delete related objects with a cascading delete. You will need to delete each value separately.
But you can combine all those deletes into a single call by using multi-location updates. If you write null to each of the locations for the user, you can delete all of them with one call to updateChildren():
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Map<String,Object updates = new HashMap<String,Object>();
updates.put("users/user1", null);
updates.put("groups/group1/members/user", null);
// Do a deep-path update
ref.updateChildren(updatedUserData, new Firebase.CompletionListener() {
#Override
public void onComplete(FirebaseError firebaseError, Firebase firebase) {
if (firebaseError != null) {
System.out.println("Error updating data: " + firebaseError.getMessage());
}
}
})
With this in place, you could then write security rules that validate that members of a group must also exist under the /users node:
{
"rules": {
"groups":
"$groupid": {
"users": {
"$uid": {
".validate": "newData.parent().parent().parent().parent().child('users').hasChild($uid)"
}
}
}
}
}
}
The validation rule is a bit easier to understand if you read the multiple .parent() calls as newRoot (which unfortunately doesn't exist). So in pseudo-code it is:
newRoot.child('users').hasChild($uid)
In words: a UID can only be a member of a group if it also exists under /users.