Firebase authentication with strings - firebase

I am wondering if it's possible to do the firebase authentication on strings? I have seen it being done on keys like -XDhabsuduydvtest <- random test key.
Now i have this structure:
{
"conversations" : {
"person1" : {
"person2" : {
"0" : 0,
"last_read" : 1460377167535
}
},
"person2" : {
"person1" : {
"0" : 0,
"last_read" : 1460377125515
}
}
},
"messages" : {
"eb-uuid-729fc0ac-49b8-48fa-a2ff-f2ada67b9e4c-person1" : {
"body" : "Dit is een test vanuit iOS",
"date" : 1460383996536,
"sender" : "eb-uuid-729fc0ac-49b8-48fa-a2ff-f2ada67b9e4c"
},
"person1-person2" : {
"-KF49xHKqnDawywJ9H0b" : {
"body" : "test message",
"date" : 1460375639190,
"sender" : "person1"
},
"-KF4Fc1KHH31O4_l0QWh" : {
"body" : "new",
"date" : 1460377125013,
"sender" : "person2"
}
}
},
"users" : {
"eb-uuid-729fc0ac-49b8-48fa-a2ff-f2ada67b9e4c" : {
"chat_enabled" : true,
"email" : "test#gmail.com",
"first_name" : "John",
"last_name" : "Smith",
"provider" : "password",
"push_muted" : false,
"push_token" : "some-push-token",
"uid" : "729fc0ac-49b8-48fa-a2ff-f2ada67b9e4c",
"username" : "johnsmith"
},
"person1" : {
"first_name" : "person",
"last_name" : "one"
},
"person2" : {
"first_name" : "person",
"last_name" : "two"
}
}
}
plus some security rule i tried, obviously i'd like to check if the uuid's are the same, and not only if one exists
{
"rules": {
"messages": {
"$conv":{
//Person can only read a conversation he/she is participating in
".write": true,
".read": true,
".indexOn": ["date"]
}
},
"users":{
"$ebuuid":{
".write": "root.child('users').child($ebuuid).hasChild('uid')",
".read": "root.child('users').child($ebuuid).hasChild('uid')"
}
},
"conversations":{
".write": "data.child('uid').val() === auth.uid",
".read": true
}
}
}
(Replaced images with text)
I'm really not sure how to go from here now .. the user has some uid but i'm not sure how to check it with whether he or she can post messages etc ..

Related

How to set .indexOn in firebase?

This is my json structure
{
"books" : {
"sample" : {
"eight" : {
"author" : "eighta",
"name" : "eight",
"sub" : {
"subauthor" : "eightauthor",
"subname" : "general"
}
},
"eleven" : {
"author" : "twelvea",
"name" : "twelve",
"sub" : {
"subauthor" : "elevenauthor",
"subname" : "general"
}
},
"five" : {
"author" : "fivea",
"name" : "five",
"sub" : {
"subauthor" : "fiveauthor",
"subname" : "fivesub"
}
},
"four" : {
"author" : "foura",
"name" : "four",
"sub" : {
"subauthor" : "fourauthor",
"subname" : "general"
}
},
"nine" : {
"author" : "ninea",
"name" : "nine",
"sub" : {
"subauthor" : "nineauthor",
"subname" : "ninesub"
}
},
"one" : {
"author" : "onea",
"name" : "one",
"sub" : {
"subauthor" : "oneauthor",
"subname" : "onesub"
}
},
"seven" : {
"author" : "seven",
"name" : "seven"
},
"six" : {
"author" : "sixa",
"name" : "six"
},
"ten" : {
"author" : "tena",
"name" : "ten"
},
"three" : {
"author" : "threea",
"name" : "three"
},
"two" : {
"author" : "twoa",
"name" : "two"
}
}
}
}
I want to fetch data which are having subname equal to general
My index rules
{
/* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
"rules": {
".read": true,
".write": true,
"books": {
"$user_id": {
".indexOn": ["subname", "subauthor"]
}
}
}
}
}
https://myprojectpath/books/sample/eight.json?orderBy="subname"&equalTo="general"&print=pretty
Above rule is working fine. But I need to pass generic api to fetch the data where subname should be general. I cannot pass eight.json, nine.json, ten.json each time when I call. I should call only one api where it should provide the data where subname should be general.
If I understand you correctly you want to use a single query to search across all authors for their sub/subname property.
In that case you can define an index on books/sample for the sub/subname property of each child node:
"books": {
"sample": {
".indexOn": ["sub/subname", "sub/subauthor"]
}
}
The sample could be a $ variable here (such a $user_id), but the paths in .indexOn have to be known.
This creates an index under sample with the value of sub/subname for each child node, which you can then query with:
https://myprojectpath/books/sample.json?orderBy="sub/subname"&equalTo="general"&print=pretty

Firebase Database Rules - Controlling access to collections

I've been trying to come up with a flat data structure for Firebase Database (as is recommended) and afterwards, a set of rules to control access correctly. My example is trying to demonstrate how you'd lock down/allow access to a db which is multi-tenanted across different organizations.
My first attempt was something like this:
Database structure: https://gist.github.com/peteski22/40b0a79a6854d7bb818919a5262f4a7e
{
"admins" : {
"8UnM6LIiZJYAHVdty6gzdD8oVI42" : true
},
"organizations": {
"-JiGh_31GA20JabpZBfc" : {
"name" : "Comp1 Ltd"
},
"-JiGh_31GA20JabpZBfd" : {
"name" : "company2 PLC"
}
},
"users" : {
"8UnM6LIiZJYAHVdty6gzdD8oVI42": {
"firstName" : "Peter",
"lastName" : "Piper",
"email" : "peter.piper#testtest.com",
"organization" : ""
},
"-JiGh_31GA20JabpZBfe" : {
"firstName" : "Joe",
"lastName" : "Blogs",
"email" : "joe.blogs#co1.com",
"organization" : "-JiGh_31GA20JabpZBfc"
},
"WgnHjk5D8xbuYeA7VDM3ngKwCYV2" : {
"firstName" : "test",
"lastName" : "user",
"email" : "test.user#google.com",
"organization" : "-JiGh_31GA20JabpZBfd"
}
},
"employees" : {
"-JiGh_31GA20JabpZBeb" : {
"organization" : "-JiGh_31GA20JabpZBfc",
"firstName" : "Johnny",
"lastName" : "Baggs",
"email" : "j.baggss#co1.com",
"employeeNumber" : "ASV123456"
},
"-JiGh_31GA20JabpZBec" : {
"organization" : "-JiGh_31GA20JabpZBfc",
"firstName" : "Maheswari",
"lastName" : "Sanjal",
"email" : "mahe.sanjal#co1.com",
"employeeNumber" : "ASV111111"
},
"-JiGh_31GA20JabpZBce" : {
"organization" : "-JiGh_31GA20JabpZBfd",
"firstName" : "Fedde",
"lastName" : "le Grande",
"email" : "fedde.grande#co2.com",
"employeeNumber" : "ASV111111"
}
}
}
Database rules: https://gist.github.com/peteski22/b038d81641c1409cec734d187272eeba
{
"rules" : {
"admins" : {
".read" : "root.child('admins').hasChild(auth.uid)",
".write" : "root.child('admins').hasChild(auth.uid)"
},
"users" : {
"$user" : {
".read" : "data.child('organization').val() === root.child('users').child(auth.uid).child('organization').val()",
".write" : "root.child('admins').hasChild(auth.uid)"
}
},
"organizations" : {
"$organization" : {
".read" : "$organization === root.child('users').child(auth.uid).child('organization').val()",
".write" : "root.child('admins').hasChild(auth.uid)"
}
},
"employees" : {
"$employee" : {
".read" : "data.child('organization').val() === root.child('users').child(auth.uid).child('organization').val()",
".write" : "data.child('organization').val() === root.child('users').child(auth.uid).child('organization').val()"
}
}
}
}
However the problem here seemed to be that I couldn't do something like:
[GET] /employees
to see a collection of employees that belonged to the same organization as the logged in user.
After much faffing, I read this in the docs: https://firebase.google.com/docs/database/security/securing-data#rules_are_not_filters, which I think boils down to 'you're doing it wrong' if you want to get at the data the way I did.
Back to the drawing board, and after reading https://www.firebase.com/docs/web/guide/structuring-data.html / https://firebase.google.com/docs/database/web/structure-data
I made some changes to the db structure and rules:
Attempt #2 structure: https://gist.github.com/peteski22/4593733bf54815393a443dfcd0f34c04
{
"admins" : {
"8UnM6LIiZJYAHVdty6gzdD8oVI42" : true
},
"organizations": {
"-JiGh_31GA20JabpZBfc" : {
"name" : "Comp1 Ltd",
"users" : {
"-JiGh_31GA20JabpZBfe" : true,
"-JiGh_31GA20JabpZBff" : true,
"-JiGh_31GA20JabpZBea" : true
},
"employees" : {
"-JiGh_31GA20JabpZBeb" : true,
"-JiGh_31GA20JabpZBec" : true
}
},
"-JiGh_31GA20JabpZBfd" : {
"name" : "company2 PLC",
"users" :{
"WgnHjk5D8xbuYeA7VDM3ngKwCYV2" : true
},
"employees" :{
"-JiGh_31GA20JabpZBce" : true
}
}
},
"users" : {
"8UnM6LIiZJYAHVdty6gzdD8oVI42": {
"firstName" : "Peter",
"lastName" : "Piper",
"email" : "peter.piper#testtest.com",
"organization" : ""
},
"-JiGh_31GA20JabpZBfe" : {
"firstName" : "Joe",
"lastName" : "Blogs",
"email" : "joe.blogs#co1.com",
"organization" : "-JiGh_31GA20JabpZBfc"
},
"-JiGh_31GA20JabpZBff" : {
"firstName" : "Sally",
"lastName" : "McSwashle",
"email" : "sally.mcswashle#co1.com",
"organization" : "-JiGh_31GA20JabpZBfc"
},
"-JiGh_31GA20JabpZBea" : {
"firstName" : "Eva",
"lastName" : "Rushtock",
"email" : "eva.rushtock#payrollings.com",
"organization" : "-JiGh_31GA20JabpZBfc"
},
"WgnHjk5D8xbuYeA7VDM3ngKwCYV2" : {
"firstName" : "test",
"lastName" : "user",
"email" : "test.user#google.com",
"organization" : "-JiGh_31GA20JabpZBfd"
}
},
"employees" : {
"-JiGh_31GA20JabpZBeb" : {
"organization" : "-JiGh_31GA20JabpZBfc",
"firstName" : "Johnny",
"lastName" : "Baggs",
"email" : "j.baggss#financeco.com",
"employeeNumber" : "ASV123456"
},
"-JiGh_31GA20JabpZBec" : {
"organization" : "-JiGh_31GA20JabpZBfc",
"firstName" : "Maheswari",
"lastName" : "Sanjal",
"email" : "mahe.sanjal#financeco.com",
"employeeNumber" : "ASV111111"
},
"-JiGh_31GA20JabpZBce" : {
"organization" : "-JiGh_31GA20JabpZBfd",
"firstName" : "Fedde",
"lastName" : "le Grande",
"email" : "fedde.grande#payrollings.com",
"employeeNumber" : "ASV111111"
}
}
}
Attempt #2 rules: https://gist.github.com/peteski22/e1be434cd1ea8ec2e630bec6d8aa714f
{
"rules" : {
"admins" : {
".read" : "root.child('admins').hasChild(auth.uid)",
".write" : "root.child('admins').hasChild(auth.uid)"
},
"users" : {
".indexOn": [ "organization" ],
"$user" : {
".read" : "data.child('organization').val() === root.child('users').child(auth.uid).child('organization').val()",
".write" : "root.child('admins').hasChild(auth.uid)"
}
},
"organizations" : {
".indexOn": [ "users", "employees" ],
"$organization" : {
".read" : "$organization === root.child('users').child(auth.uid).child('organization').val()",
".write" : "root.child('admins').hasChild(auth.uid)"
}
},
"employees" : {
".indexOn": [ "organization" ],
"$employee" : {
".read" : "data.child('organization').val() === root.child('users').child(auth.uid).child('organization').val()",
".write" : "data.child('organization').val() === root.child('users').child(auth.uid).child('organization').val()"
}
}
}
}
Now I can keep the data locked down fine in each collection, but the only way to get anything is to know the organization ID, get that organization, then get each and every employee by their ID. Although the docs above for structuring data (section: Joining Flattened Data) seem to suggest that it's fine to do this, coming from an OO and SQL background it feels very weird.. which usually means.. 'I'm doing it wrong'.
If anyone has any advice on whether I'm going down the right track, or what to try instead it would be greatly appreciated.
Thanks
Peter
After reading the docs and chatting with people in the firebase-community slack, I've come to the conclusion that I was on the right track.
I found using a compiler called "Bolt" (firebase-bolt in npm) extremely useful for generating the rules too.
Here's my structure, bolt rules and compiled JSON rules:
Structure
{
"admins" : {
"8UnM6LIiZJYAHVdty6gzdD8oVI42" : true
},
"organizations": {
"-JiGh_31GA20JabpZBfc" : {
"name" : "Comp1 Ltd",
"users" : {
"-JiGh_31GA20JabpZBfe" : true,
"-JiGh_31GA20JabpZBff" : true,
"-JiGh_31GA20JabpZBea" : true
},
"employees" : {
"-JiGh_31GA20JabpZBeb" : true,
"-JiGh_31GA20JabpZBec" : true
}
},
"-JiGh_31GA20JabpZBfd" : {
"name" : "company2 PLC",
"users" :{
"WgnHjk5D8xbuYeA7VDM3ngKwCYV2" : true
},
"employees" :{
"-JiGh_31GA20JabpZBce" : true
}
}
},
"users" : {
"8UnM6LIiZJYAHVdty6gzdD8oVI42": {
"firstName" : "Peter",
"lastName" : "Piper",
"email" : "peter.piper#testtest.com",
"organization" : ""
},
"-JiGh_31GA20JabpZBfe" : {
"firstName" : "Joe",
"lastName" : "Blogs",
"email" : "joe.blogs#co1.com",
"organization" : "-JiGh_31GA20JabpZBfc"
},
"-JiGh_31GA20JabpZBff" : {
"firstName" : "Sally",
"lastName" : "McSwashle",
"email" : "sally.mcswashle#co1.com",
"organization" : "-JiGh_31GA20JabpZBfc"
},
"-JiGh_31GA20JabpZBea" : {
"firstName" : "Eva",
"lastName" : "Rushtock",
"email" : "eva.rushtock#payrollings.com",
"organization" : "-JiGh_31GA20JabpZBfc"
},
"WgnHjk5D8xbuYeA7VDM3ngKwCYV2" : {
"firstName" : "test",
"lastName" : "user",
"email" : "test.user#google.com",
"organization" : "-JiGh_31GA20JabpZBfd"
}
},
"employees" : {
"-JiGh_31GA20JabpZBeb" : {
"organization" : "-JiGh_31GA20JabpZBfc",
"firstName" : "Johnny",
"lastName" : "Baggs",
"email" : "j.baggss#financeco.com",
"employeeNumber" : "ASV123456"
},
"-JiGh_31GA20JabpZBec" : {
"organization" : "-JiGh_31GA20JabpZBfc",
"firstName" : "Maheswari",
"lastName" : "Sanjal",
"email" : "mahe.sanjal#financeco.com",
"employeeNumber" : "ASV111111"
},
"-JiGh_31GA20JabpZBce" : {
"organization" : "-JiGh_31GA20JabpZBfd",
"firstName" : "Fedde",
"lastName" : "le Grande",
"email" : "fedde.grande#payrollings.com",
"employeeNumber" : "ASV111111"
}
}
}
Bolt Rules
// **********
// FUNCTIONS
// **********
function isAdmin (auth) {
return root.admins[auth.uid] != null
}
function isInSameOrganization(auth, orgUid) {
return root.users[auth.uid].organization === orgUid
}
// **********
// PATHS
// **********
path /admins {
read() { isAdmin(auth) }
write() { isAdmin(auth) }
}
path /users {
index() { ["organization"] }
write() { isAdmin(auth) }
}
path /users/{id} is User {
read() { isInSameOrganization(auth, id) || isAdmin(auth) }
}
path /organizations {
write() { isAdmin(auth) }
}
path /organizations/{id} is Organization {
read() { isInSameOrganization(auth, id) }
}
path /employees {
index() { ["organization"] }
write() { isInSameOrganization(auth, this.organization) || isAdmin(auth) }
}
path /employees/{id} is Employee {
read() { isInSameOrganization(auth, id) || isAdmin(auth) }
}
// **********
// TYPES
// **********
type OrganizationID extends String {
validate() { root.organizations[this] != null }
}
type UserID extends String {
validate() { root.users[this] != null }
}
type EmployeeID extends String {
// Validate that the user ID exists in the employees node (read rule access should prevent us reading a employees that isn't in our org)
validate() { root.employees[this] != null }
}
type Email extends String {
validate() {
return this.matches(/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2,4}$/i);
}
}
type User {
firstName: String,
lastName: String
email: Email,
organization: OrganizationID
}
type Employee {
organization: OrganizationID,
firstName: String,
lastName: String,
email: Email,
employeeNumber: String
}
type Organization {
name: String,
users: Map<UserID, Boolean> | Null,
employees: Map<EmployeeID, Boolean> | Null
}
JSON Rules (generated by Bolt)
{
"rules": {
"admins": {
".read": "root.child('admins').child(auth.uid).val() != null",
".write": "newData.parent().child('admins').child(auth.uid).val() != null"
},
"users": {
".write": "newData.parent().child('admins').child(auth.uid).val() != null",
".indexOn": [
"organization"
],
"$id": {
".validate": "newData.hasChildren(['firstName', 'lastName', 'email', 'organization'])",
"firstName": {
".validate": "newData.isString()"
},
"lastName": {
".validate": "newData.isString()"
},
"email": {
".validate": "newData.isString() && newData.val().matches(/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\\\\.[A-Z]{2,4}$/i)"
},
"organization": {
".validate": "newData.isString() && newData.parent().parent().parent().child('organizations').child(newData.val()).val() != null"
},
"$other": {
".validate": "false"
},
".read": "root.child('users').child(auth.uid).child('organization').val() == $id || root.child('admins').child(auth.uid).val() != null"
}
},
"organizations": {
".write": "newData.parent().child('admins').child(auth.uid).val() != null",
"$id": {
".validate": "newData.hasChildren(['name'])",
"name": {
".validate": "newData.isString()"
},
"users": {
"$key1": {
".validate": "newData.parent().parent().parent().parent().child('users').child($key1).val() != null && newData.isBoolean()"
},
".validate": "newData.hasChildren()"
},
"employees": {
"$key2": {
".validate": "newData.parent().parent().parent().parent().child('employees').child($key2).val() != null && newData.isBoolean()"
},
".validate": "newData.hasChildren()"
},
"$other": {
".validate": "false"
},
".read": "root.child('users').child(auth.uid).child('organization').val() == $id"
}
},
"employees": {
".write": "newData.parent().child('users').child(auth.uid).child('organization').val() == newData.child('organization').val() || newData.parent().child('admins').child(auth.uid).val() != null",
".indexOn": [
"organization"
],
"$id": {
".validate": "newData.hasChildren(['organization', 'firstName', 'lastName', 'email', 'employeeNumber'])",
"organization": {
".validate": "newData.isString() && newData.parent().parent().parent().child('organizations').child(newData.val()).val() != null"
},
"firstName": {
".validate": "newData.isString()"
},
"lastName": {
".validate": "newData.isString()"
},
"email": {
".validate": "newData.isString() && newData.val().matches(/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\\\\.[A-Z]{2,4}$/i)"
},
"employeeNumber": {
".validate": "newData.isString()"
},
"$other": {
".validate": "false"
},
".read": "root.child('users').child(auth.uid).child('organization').val() == $id || root.child('admins').child(auth.uid).val() != null"
}
}
}
}
I'm still finding bugs in this, but I think it's showing progress. Just to note that there are some good official & unofficial Firebase videos on Youtube, the docs are fairly decent for the most part, and the firebase-community seems to be friendly. So any new comers like me, you know where to start.

Can't write to Firebase database using rules

I'm trying to create a rule that allows some users to write but not all.
I need that all user can read 'menu' items but only users listed at store data can write.
My data structure:
{
"category" : [ null, "Burger", "Drinks" ],
"menu" : [ null, {
"available" : true,
"category" : "1",
"description" : "item1 description",
"image" : "chicken_maharaja",
"name" : "New Chicken Maharaja",
"price" : 1300,
"store" : 1
}, {
"available" : true,
"category" : "1",
"description" : "item2 description",
"image" : "big_spicy_chicken_wrap",
"name" : "Big Spicy Chicken Wrap",
"price" : 120,
"store" : 1
}, {
"available" : true,
"category" : "2",
"description" : "item3 description",
"image" : "thumsup",
"name" : "Thumsup 100ml",
"price" : 40,
"store" : 1
}, {
"available" : true,
"category" : "2",
"description" : "item4 description",
"image" : "mccafe_ice_coffee",
"name" : "Ice Coffee",
"price" : 140,
"store" : 1
}, {
"available" : true,
"category" : "1",
"description" : "item5 description",
"image" : "mc_chicken",
"name" : "MC Chicken",
"price" : 190,
"store" : 1
}, {
"available" : true,
"category" : "2",
"description" : "item6 description",
"image" : "Smoothie",
"name" : "Smoothie",
"price" : 70,
"store" : 2
}, {
"available" : true,
"category" : "1",
"description" : "item8 description",
"image" : "salad_wrap",
"name" : "Salad Wrap",
"price" : 150,
"store" : 2
} ],
"stores" : [ null, {
"location" : "Campinas - Taquaral",
"name" : "Store 1",
"user" : {
"pyixsRTw9qdiuESt62YnmEYXQt13" : true
}
}, {
"location" : "São Paulo - Perdises",
"name" : "Store 2",
"user" : {
"LBNZ8Dwp2rdJtlSh0NC1ApdtbAl2" : true,
"TLomOgrd3gbjDdpDAqGiwl0lBhn2" : true
}
} ],
"userProfile" : {
"LBNZ8Dwp2rdJtlSh0NC1ApdtbAl2" : {
"birthDate" : "1974-02-10",
"email" : "asd#asd.com",
"firstName" : "João",
"lastName" : "Silva"
},
"pyixsRTw9qdiuESt62YnmEYXQt13" : {
"birthDate" : "1974-02-10",
"email" : "leandro.garcias#gmail.com",
"firstName" : "Leandro",
"lastName" : "Garcia"
}
}
}
My rule:
{
"rules": {
"menu": {
"$items": {
".read": "true",
".write": "root.child('stores').child('1').child(data.child('user').val()).hasChild(auth.uid)"
}
},
"stores": {
"$store": {
".read": "true",
".write": "root.child('stores').child('$store').child(data.child('user').val()).hasChild(auth.uid)"
}
}
}
}
The read is ok. :-) But I can't write.
Your newData doesn't have a child user so that check always fails. You probably mean:
"43268522": {
"menu": {
"$items": {
".read": "true",
".write": "root.child('stores').child('1').child('user').hasChild(auth.uid)"
}
}
You're probably looking for this rule:
".write": "
root.child('stores')
.child(newData.child('store').val())
.child('user')
.hasChild(auth.uid)"
So this uses the store property from the new data to look up if the current user is in the store they're trying to modify.
Unfortunately this rule won't work with your current data structure, since the value of store is a number, while the key of a store is a string: "1" !== 1.
The simplest solution is to store the store as a string, e.g.:
"store": "1"
You might want to consider that anyway, since you're now getting Firebase's array coercion, which is not helpful. For more on this see our blog post on Best Practices: Arrays in Firebase. I'd recommend storing stores using either push IDs, or simply prefixing them, e.g.
"stores": {
"store1": {
...
}
}

Need to add a rule in Firebase DB

I want to add a rule to limit the max int that could be saved in the no_of_orders field to 2. The OrderSchedule document data is pre-populated via the app I'm developing.
Here is the jsonExport data.
{
"OrderSchedule" : {
"13-Oct-2016" : {
"13:00 - 14:00" : {
"no_of_orders" : 4
}
}
},
"Orders" : {
"-KTpIn4HeuDBDliCnTSA" : {
"car_Model" : "Van",
"date_Created" : 1476212105,
"date_Scheduled" : "13-Oct-2016",
"service_Type" : "Shine",
"status" : "Scheduled",
"time_Scheduled" : "13:00 - 14:00",
"uid" : "sms|57f7b267e618d33da23e65ce"
},
"-KTpJ6BREc695pv4Ue6s" : {
"car_Model" : "SUV",
"date_Created" : 1476212188,
"date_Scheduled" : "13-Oct-2016",
"service_Type" : "Detailed",
"status" : "Scheduled",
"time_Scheduled" : "13:00 - 14:00",
"uid" : "sms|57f7b267e618d33da23e65ce"
},
"users" : {
"sms|57f7b267e618d33da23e65ce" : {
"created_at" : 1475868493,
"email" : "balouza#hotmail.com",
"phone" : "+0000000000",
"username" : "balouza"
},
"sms|57fa9701e618d33da240efa5" : {
"created_at" : 1476040501,
"email" : "look#hotmail.com",
"phone" : "+00000000000",
"username" : "bolzo"
}
}
}
Security rules:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"max": {
".write": "auth != null"
},
".OrderSchedule": {
"$date": {
"$timeSlot": {
"no_of_orders": {
".validate": "newData.val() <= root.child('max').val()"
}
}
}
}
}
}
Save a parent node key-value pair in your Database.
{
max : 2,
"OrderSchedule" : {
"13-Oct-2016" : {
"13:00 - 14:00" : {
"no_of_orders" : 4
}
}
},
"Orders" : {
"-KTpIn4HeuDBDliCnTSA" : {
"car_Model" : "Van",
"date_Created" : 1476212105,
"date_Scheduled" : "13-Oct-2016",
"service_Type" : "Shine",
"status" : "Scheduled",
"time_Scheduled" : "13:00 - 14:00",
"uid" : "sms|57f7b267e618d33da23e65ce"
},
...
}
In your security rules just add :-
{
"rules": {
"max" : {
".write" : "false"
},
"OrderSchedule": {
"$date":{
"$timeInterval":{
"no_of_orders":{
".validate": "newData.val() <= root.child('max').val()"
}
}
}
}
}
}
And if you want only the authenticated users to read and write in your database , use these :-
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"max" : {
".write" : "false"
},
"OrderSchedule": {
"$date":{
"$timeInterval":{
"no_of_orders":{
".validate": "newData.val() <= root.child('max').val()"
}
}
}
}
}
}

Firebase .indexOn, how can i make sure this index is unique

I have the following data structure:
{"applicants":[
{
"-KNbKoNzPGsz2TAQp-j9" : {
"email" : "zahavi#post.tau.ac.il",
"id" : "056042344",
"name" : "Jacob",
"prefix" : "Prof.",
"surname" : "Zahavi"
},
"-KNbWPpsrFGJBDaWK2EN" : {
"email" : "chamud#gmail.com",
"id" : "314965211",
"name" : "Ilay",
"prefix" : "Mr.",
"surname" : "Shvo"
},
"-KNd8HvkzAYi0LtG9qNj" : {
"email" : "zahavi#zpost.tau.ac.il",
"id" : "056042344",
"name" : "Jacob",
"prefix" : "Prof.",
"surname" : "Zahavi"
}]
}
}
I would like to enforce uniqueness rule on the field id, so it will not be possible to create two entries in applicants collection that has the same id value.
currently my rules are:
{
"rules": {
".read": true,
".write": true,
"Tables":{"applicants":{"id":{".indexOn":".value"}}}
}
}
I explored two possible solutions that are:
1. transaction. unfortunately i did not find a way to run transaction from a query.
2. rules. but failed to find something suitable.
Edit (from comments):
I tried the following rules:
{
"rules": {
".read": true,
".write": true,
"Tables": {
"applicants": {
"$app": {
"id": {
".indexOn": ".value",
".validate": "!root.child('Tables').child('applicants').child(newData.child('id').val()).exis‌​ts()"
},
}
}
}
}
}
and I always got creation failed permission denied even for values that were not exist

Resources