Last active
August 29, 2015 14:10
-
-
Save calendee/2125fa951bc004159c34 to your computer and use it in GitHub Desktop.
Firebase : Unique Mobiles with Security Restrictions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"rules": { | |
".read": false, | |
".write": false, | |
"users" : { | |
"$userId" : { | |
".write" : "$userId === auth.uid && !data.exists() && newData.exists() && auth.uid !== 'anonymous'", | |
// Can only read if the node is the same as the uid | |
".read" : "$userId === auth.uid", | |
// Only allow these properties | |
".validate": "newData.hasChildren(['mobile'])", | |
// no other properties can be included in this sample profile - real world would have others | |
"$other": { ".validate": false }, | |
"mobile" : { | |
// Ensure the mobile number was the last one checked | |
".validate": "root.child('checkMobileInUseStep2').child(auth.uid).child('mobile').val() === newData.val()" | |
} | |
} | |
}, | |
"checkMobileInUseStep1" : { | |
// Allows user to check mobile number up to 3 times. | |
// If they are allowed to add the mobile number here, then they are allowed to try to write to mobileInUseChecksStep2 | |
// Used in conjunction with checkMobileInUseStep2 to allow user to check if mobile number is not already registered | |
"$userId": { | |
// Only authenticated users can write here. Can't be anonymous users | |
".write": "$userId === auth.uid && newData.exists() && auth.uid !== 'anonymous'", | |
// No one is allowed to read this table | |
".read" : false, | |
// Counts the number of times user has written here. | |
"attemptsCounter" : { | |
// attemptsCounter can only be incremented by 1 each time | |
".validate": "newData.isNumber() && newData.val() > 0 && newData.val() <= 3 && ((!data.exists() && newData.val() === 1) || (newData.val() === data.val() + 1))" | |
}, | |
// Collection of each individual attempt to check if a mobile number is in use. | |
"attempts" : { | |
"$attemptId" : { | |
// The attemptId must match the attemptsCounter counter above | |
// The attempt must have a valid 'mobile' entry | |
// The record cannot already exist. This prevents the user from just changing the mobile number over and over. | |
".validate": "newData.hasChildren(['mobile']) && !data.exists() && root.child('checkMobileInUseStep1').child($userId).child('/attemptsCounter').exists() && root.child('checkMobileInUseStep1').child($userId).child('/attemptsCounter').val() + '' == $attemptId", | |
"$other": { ".validate": false }, | |
"mobile" : { | |
".validate": "newData.isString() && newData.val().length > 1 && newData.val().length < 25" | |
} | |
} | |
} | |
} | |
}, | |
// Used in conjunction with checkMobileInUseStep1 | |
"checkMobileInUseStep2" : { | |
"$userId": { | |
// Again, only authenticated users can write here | |
".write": "$userId === auth.uid && newData.exists() && auth.uid !== 'anonymous'", | |
// No one can read this table | |
".read" : false, | |
// Make sre the entry has only a mobile record and nothing else | |
".validate": "newData.hasChildren(['mobile'])", | |
"$other": { ".validate": false }, | |
// The mobile number must NOT exist in the 'registedMobiles' table. | |
// The mobile number must exist in one of the attempts recorded in the 'checkMobileInUseStep1' table. | |
"mobile" : { | |
".validate": "!root.child('registeredNumbers').child(newData.val()).exists() && ( root.child('checkMobileInUseStep1').child($userId).child('attempts').child('1').child('mobile').val() === newData.val() || root.child('checkMobileInUseStep1').child($userId).child('attempts').child('2').child('mobile').val() === newData.val() || root.child('checkMobileInUseStep1').child($userId).child('attempts').child('3').child('mobile').val() === newData.val() )" | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment