Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
87 lines (72 sloc) 4.19 KB
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow create: if isValidUserCreation(userId);
allow read: if isOwner(userId);
allow update, delete: if isValidUserUpdate(userId);
}
function isValidUserUpdate(userId) {
// Needs to be owner
return (isOwner(userId) && (!(request.writeFields.hasAny(['schoolAdmin','uid', 'email']))));
}
function isValidUserCreation(userId) {
// Needs to be owner
return (isSignedIn() && (!(request.writeFields.hasAny(['schoolAdmin']))));
}
match /schools/{schoolId} {
allow read: if isSignedIn();
allow update: if signedInWithSchool(schoolId) && getUserData().schoolAdmin;
}
match /schools/{schoolId}/events/{eventsId} {
allow read: if signedInWithSchool(schoolId);
allow create, delete: if signedInWithSchool(schoolId) && getUserData().schoolAdmin;
allow update: if signedInWithSchool(schoolId) && (isValidNonAdminEventUpdate() || getUserData().schoolAdmin);
}
match /schools/{schoolId}/user-details/{userDetailsId} {
allow read: if (signedInWithSchool(schoolId) && ((getUserData().userDetails == userDetailsId) || getUserData().schoolAdmin)) || (getUserData().email == resource.data.email);
allow create, delete: if signedInWithSchool(schoolId) && getUserData().schoolAdmin;
allow update: if signedInWithSchool(schoolId) && (isValidNonAdminUserDetailsUpdate(userDetailsId) || getUserData().schoolAdmin)
}
function isValidNonAdminEventUpdate() {
// pre: can only change participants
// 1st: no change, 2nd: user has added themselves, 3rd: user has removed themselves
// 2nd: User not in existing, all existing still there, user in incoming & incoming is only larger by one
// 3rd: User in existing, existing has all incoming, not in incoming, incoming is smaller by one
return ((request.writeFields.hasAll(['participants']) && (request.writeFields.size() == 1)) && incomingData().participants.size() <= existingData().capacity )
&& ((incomingData().participants.hasAll(existingData().participants) && (incomingData().size() == existingData().size()))
|| (!(getUserData().userDetails in existingData().participants) && incomingData().participants.hasAll(existingData().participants) && (getUserData().userDetails in incomingData().participants) && (incomingData().participants.size() == (existingData().participants.size() + 1)))
|| ((getUserData().userDetails in existingData().participants) && (existingData().participants.hasAll(incomingData().participants)) && (!(getUserData().userDetails in incomingData().participants)) && ((incomingData().participants.size() + 1) == existingData().participants.size())));
}
function isValidNonAdminUserDetailsUpdate(userDetailsId) {
// pre: can only change participants
// 1st: no change, 2nd: user has added themselves, 3rd: user has removed themselves
// 2nd: all existing still there, incoming is only larger by one
// 3rd: existing has all incoming, incoming is smaller by one
return (getUserData().userDetails == userDetailsId) && ((request.writeFields.hasAll(['events']) && (request.writeFields.size() == 1)))
&& ((incomingData().events.hasAll(existingData().events) && (incomingData().events.size() == existingData().events.size()))
|| (incomingData().events.hasAll(existingData().events) && (incomingData().events.size() == (existingData().events.size() + 1)))
|| ((existingData().events.hasAll(incomingData().events)) && ((incomingData().events.size() + 1) == existingData().events.size())));
}
function signedInWithSchool(schoolId) {
return isSignedIn() && (getUserData().school == schoolId);
}
function isOwner(userId) {
return request.auth.uid == userId;
}
function getUserData() {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
}
function isSignedIn() {
return request.auth != null;
}
function existingData() {
return resource.data;
}
function incomingData() {
return request.resource.data;
}
function currentUserId() {
return request.auth.uid;
}
}
}