Created
January 26, 2016 08:47
-
-
Save udacityandroid/996c56bf84eec19c53fb to your computer and use it in GitHub Desktop.
Firebase - Lesson 5 - Rules and Datastructure for Account Merge Example
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
{ | |
"acknowledge" : { | |
"merges" : { | |
"accepted" : { | |
"898dac5d-f99d-463a-b82a-54abd5784447" : "google:106385094246122969144" | |
}, | |
"proposed" : { | |
"898dac5d-f99d-463a-b82a-54abd5784447" : "google:106385094246122969144" | |
} | |
}, | |
"messages" : { | |
"-K61_SOkAM3L8U8-DN97" : { | |
"timestamp" : 1450668578467, | |
"uid" : "google:106385094246122969144" | |
}, | |
"-K652RtRKLRH2pjiBw25" : { | |
"timestamp" : 1450726772361, | |
"uid" : "google:106385094246122969144" | |
}, | |
"-K65pKKz5ZwTPurw8fdw" : { | |
"timestamp" : 1450739848629, | |
"uid" : "google:106385094246122969144" | |
}, | |
"-K65rVrEDWQce0oA-SQ3" : { | |
"timestamp" : 1450740420094, | |
"uid" : "google:106385094246122969144" | |
}, | |
"-K65rZfG7TX5ko77Q5eY" : { | |
"timestamp" : 1450740435712, | |
"uid" : "google:106385094246122969144" | |
} | |
}, | |
"users" : { | |
"4c9f4097-fe2d-4d22-8a17-b9480c2dc4e6" : { | |
"email" : "puf@puf.com", | |
"isTemporaryPassword" : false, | |
"profileImageURL" : "https://secure.gravatar.com/avatar/5ad89db23b9e5d5f00ba5548cc9e34ec?d=retro" | |
}, | |
"898dac5d-f99d-463a-b82a-54abd5784447" : { | |
"email" : "frank@puf.com", | |
"isTemporaryPassword" : false, | |
"profileImageURL" : "https://secure.gravatar.com/avatar/4df6cf8a2fa4219b0990c579e3f5cffd?d=retro" | |
}, | |
"google:106385094246122969144" : { | |
"accessToken" : "ya29.VAJtNRocmDS-eoWNpIxzKInpNsp9fIb5vWqINB2PTyizDJBhrPj_yd5BqFyndzuFvNmg3_E", | |
"cachedUserProfile" : { | |
"email" : "frank@puf.com", | |
"family_name" : "van Puffelen", | |
"gender" : "male", | |
"given_name" : "Frank", | |
"id" : "106385094246122969144", | |
"link" : "https://plus.google.com/+FrankvanPuffelen", | |
"locale" : "en", | |
"name" : "Frank van Puffelen", | |
"picture" : "https://lh3.googleusercontent.com/-5w08FC_pwUk/AAAAAAAAAAI/AAAAAAAAGio/aFRsRcln4bg/photo.jpg", | |
"verified_email" : true | |
}, | |
"displayName" : "Frank van Puffelen", | |
"email" : "frank@puf.com", | |
"id" : "106385094246122969144", | |
"profileImageURL" : "https://lh3.googleusercontent.com/-5w08FC_pwUk/AAAAAAAAAAI/AAAAAAAAGio/aFRsRcln4bg/photo.jpg" | |
} | |
} | |
}, | |
"pairing" : { | |
"merges" : { | |
"accepted" : { | |
"898dac5d-f99d-463a-b82a-54abd5784447" : "google:106385094246122969144" | |
} | |
}, | |
"messages" : { | |
"-K6QOckahwR6H0GtOb4W" : { | |
"timestamp" : 1451084909670, | |
"uid" : "898dac5d-f99d-463a-b82a-54abd5784447" | |
}, | |
"-K6W1RC_QpUWb9ASrqqu" : { | |
"timestamp" : 1451179492235, | |
"uid" : "898dac5d-f99d-463a-b82a-54abd5784447" | |
}, | |
"-K6W2ANnHE75uqjtYWND" : { | |
"timestamp" : 1451179685465, | |
"uid" : "google:106385094246122969144" | |
} | |
}, | |
"users" : { | |
"898dac5d-f99d-463a-b82a-54abd5784447" : { | |
"email" : "frank@puf.com", | |
"isTemporaryPassword" : false, | |
"profileImageURL" : "https://secure.gravatar.com/avatar/4df6cf8a2fa4219b0990c579e3f5cffd?d=retro" | |
}, | |
"google:106385094246122969144" : { | |
"accessToken" : "ya29.VwK66CG-nQIJHva5zpi1YxcATWWEDriauAr6eNB_byKooF_k4KHKuykdfxAPw1DtmNsLtLw", | |
"cachedUserProfile" : { | |
"email" : "frank@puf.com", | |
"family_name" : "van Puffelen", | |
"gender" : "male", | |
"given_name" : "Frank", | |
"id" : "106385094246122969144", | |
"link" : "https://plus.google.com/+FrankvanPuffelen", | |
"locale" : "en", | |
"name" : "Frank van Puffelen", | |
"picture" : "https://lh3.googleusercontent.com/-5w08FC_pwUk/AAAAAAAAAAI/AAAAAAAAGio/aFRsRcln4bg/photo.jpg", | |
"verified_email" : true | |
}, | |
"displayName" : "Frank van Puffelen", | |
"email" : "frank@puf.com", | |
"id" : "106385094246122969144", | |
"profileImageURL" : "https://lh3.googleusercontent.com/-5w08FC_pwUk/AAAAAAAAAAI/AAAAAAAAGio/aFRsRcln4bg/photo.jpg" | |
} | |
} | |
} | |
} |
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
{ | |
// This rules file contains two merging strategies: | |
// 1. acknowledge - requires user A to propose a merge and user B to accept it. Once accepted, the user A | |
// can only write messages which have user B as the uid. | |
// 2. pairings - User A generates a secret (that is written into the database) that they send to user B, | |
// user B enters the secret, which then starts the merge process of approach #1 | |
"rules": { | |
"acknowledge": { | |
".read": true, | |
"users": { | |
"$uid": { | |
".write": "auth.uid == $uid" | |
} | |
}, | |
"merges": { | |
// there are two lists here: proposed and accepted merges. Both are a mapping from uid of users A to uid of user B in the first explanation | |
"proposed": { | |
".indexOn": [".value"], | |
"$uid": { | |
// a merge can only be proposed by the current user | |
".write": "$uid == auth.uid" | |
} | |
}, | |
"accepted": { | |
"$uid": { | |
// a merge can only be accepted by the user who is targetted in the merge and only when the merge has been proposed | |
".write": "auth.uid == newData.val() && newData.parent().parent().child('proposed').child($uid).val() == newData.val() " | |
} | |
} | |
}, | |
"messages": { | |
// unmerged users can write messages under their own uid. Merged users can write messages under their merge target's uid. | |
"$messageid": { | |
".write": "(!newData.parent().parent().child('merges/accepted').child(auth.uid).exists() && auth.uid === newData.child('uid').val()) || | |
( newData.parent().parent().child('merges/accepted').child(auth.uid).val() == newData.child('uid').val() ) | |
" | |
} | |
} | |
}, | |
"pairing": { | |
"users": { | |
".read": true, | |
"$uid": { | |
".write": "auth.uid == $uid" | |
} | |
}, | |
"pairingCodes": { | |
// this node contains a list of pairing codes. The list itself is not readable, which prevents people from looking up all pairingCodes | |
"$code": { | |
// a pairing code consists of a uid and a timestamp. The uid identifies the user that generated the code. | |
".validate": "newData.hasChildren(['uid', 'timestamp'])", | |
// you can read a specific pairingCode if you know it and it's less than a minute old | |
".read": "data.child('timestamp').val() + 60000 > now", | |
// you can only write data if nothing exists yet, or delete existing data | |
".write": "(newData.exists() && !data.exists()) || (data.exists() && !newData.exists())", | |
"timestamp": { | |
".validate": "newData.val() == now" | |
} | |
} | |
}, | |
"merges": { | |
// the rules for the merges are the same as in the first approach | |
".read": true, | |
"proposed": { | |
".indexOn": [".value"], | |
"$uid": { | |
".write": "$uid == auth.uid || newData.parent().parent().child('accepted').child($uid).val() == auth.uid" | |
} | |
}, | |
"accepted": { | |
"$uid": { | |
".write": "auth.uid == newData.val() && | |
data.parent().parent().child('proposed').child($uid).val() == newData.val() && | |
!newData.parent().parent().child('proposed').child($uid).exists() | |
" | |
} | |
} | |
}, | |
"messages": { | |
".read": true, | |
"$messageid": { | |
".write": "(!newData.parent().parent().child('merges/accepted').child(auth.uid).exists() && auth.uid === newData.child('uid').val()) || | |
( newData.parent().parent().child('merges/accepted').child(auth.uid).val() == newData.child('uid').val() ) | |
" | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great Job :) ThnQ