Skip to content

Instantly share code, notes, and snippets.

@katowulf
Last active April 10, 2023 06:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save katowulf/01d4d0792fc6a3e4fa0af465e7c5030f to your computer and use it in GitHub Desktop.
Save katowulf/01d4d0792fc6a3e4fa0af465e7c5030f to your computer and use it in GitHub Desktop.
Psuedo rules examples for role based document sharing in Firestore.
// docs/{docId}/users is an array of user ids allowed to access the doc
match /docs/{docId} {
allow read if request.auth.uid in getData('docs/$(docId)').users;
}
/**
* Shortcut to simplify pathing
*/
function getPath(childPath) {
return path('/databases/'+database+'/documents/'+childPath)
}
/**
* Fetch data from a given Firestore document
*/
function getData(docPath) {
return get(getPath(docPath)).data
}
// Assumes that group members are stored in a subcollection under /groups/{groupId}/members/{userId}
const memberPath = '/groups/{groupId}/members/{userId}';
// Trigger updates to our generated maps if group membership changes
exports.memberAdded = functions.firestore.document(memberPath).onCreate(memberAdded);
exports.memberDeleted = functions.firestore.document(memberPath).onDelete(memberDeleted);
function memberAdded(snap, context) {
const [groupId, userId] = context.params;
const data = {
groups: admin.firestore.FieldValue.arrayUnion(groupId)
}
return admin.firestore().doc(`membershipList/${userId}`).update(data);
}
function memberDeleted(snap, context) {
const [groupId, userId] = context.params;
const data = {
groups: admin.firestore.FieldValue.arrayRemove(groupId)
};
return admin.firestore().doc(`membershipList/${userId}`).update(data);
}
// docs/{docId}/groups is an array of group ids allowed to access this doc
// membershipList/{userId}/groups is an array of groups this user is a member of (populated by a Function)
match /docs/{docId} {
allow read if getData('membershipList/' + request.auth.uid).groups.hasAny( getData('docs/$(docId)').groups );
}
/**
* Shortcut to simplify pathing
*/
function getPath(childPath) {
return path('/databases/'+database+'/documents/'+childPath)
}
/**
* Fetch data from a given Firestore document
*/
function getData(docPath) {
return get(getPath(docPath)).data
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment