Ruben
Ruben

Reputation: 1859

Firebase indexOn security & rules not working

I'm getting this error in xcode:

Using an unspecified index. Consider adding ".indexOn": "members/rsenov" at /groups to your security rules for better performance

This is my JSON data structure:

{
"groups" : {
  "-KB422VV21cPzpgi1wF1" : {
    "author" : "rsenov",
    "members" : {
      "rsenov" : true
    },
    "name" : "Item 1"
  },
  "-KB423lni1Iptn2fGwi1" : {
    "author" : "rsenov",
    "members" : {
      "rsenov" : true
    },
    "name" : "Item 2"
  },
  "-KB48kVOz4yTfdE86Ub7" : {
    "author" : "senovi",
    "members" : {
      "senovi" : true
    },
    "name" : "Asd"
  }
},
"users" : {
  "rsenov" : {
    "email" : "rsenov",
    "groups" : {
      "-KB422VV21cPzpgi1wF1" : true,
      "-KB423lni1Iptn2fGwi1" : true
    },
    "name" : "Ruben",
  },
  "senovi" : {
    "email" : "senovi",
    "groups" : {
      "-KB48kVOz4yTfdE86Ub7" : true
    },
    "name" : "Rubén ",
  }
 }
}

and this is what I've done so far in my security rules:

{
"rules": {
  ".read": true,
  ".write": true,
  "groups": {
    "$group_id": {
      ".indexOn": "members"
    }
  }
 }
}

This is the code that triggers the error:

DataService.dataService.GROUPS_REF.queryOrderedByChild("members/\(DataService.dataService.CURRENT_USER_ID)").queryEqualToValue(true).observeEventType(.Value, withBlock: { snapshot in
    //some code 
})

Upvotes: 3

Views: 3073

Answers (2)

Edison
Edison

Reputation: 11987

For anyone getting a similar security warning with JSQMessages / Firebase you can use this.

{
"rules": {
    ".read": true,
    ".write": true,
    "typingIndicator": {
    ".indexOn": ".value"
  }
}
}

Upvotes: 1

Frank van Puffelen
Frank van Puffelen

Reputation: 598728

You're trying to add an index on an array, which is not possible in Firebase.

As the error message tells you (it's surprisingly accurate), you need to add an index for members/rsenov:

{
  "rules": {
    ".read": true,
    ".write": true,
    "groups": {
      "$group_id": {
        ".indexOn": "members/rsenov"
      }
    }
  }
}

But this means you'll need to add an index for each user, which is very inefficient. That's why denormalization is recommended.

As an alternative (that I recommended in answer to your last question) you can create an customized index yourself, a process known as denormalizing.

{
  "groups" : {
    "-KB422VV21cPzpgi1wF1" : {
      "author" : "rsenov",
      "members" : {
        "rsenov" : true
      },
      "name" : "Item 1"
    },
    "-KB423lni1Iptn2fGwi1" : {
      "author" : "rsenov",
      "members" : {
        "rsenov" : true
      },
      "name" : "Item 2"
    }
  },
  "users": {
    "rsenov": {
      "groups": {
        "-KB422VV21cPzpgi1wF1": true,
        "-KB423lni1Iptn2fGwi1": true
      }
    }
  }
}

With this data structure, you can look up the groups for a user without even needing a query:

ref.childByAppendingPath("users/rsenov/groups")
   .observeEventType(.Value, withBlock: { snapshot in

Or if you want to use the currently authenticated user:

ref.childByAppendingPath("users")
   .childByAppendingPath(ref.authData.uid)
   .childByAppendingPath("groups")
   .observeEventType(.Value, withBlock: { snapshot in

Upvotes: 4

Related Questions