Update Firestore rules for new database structure
This commit is contained in:
@@ -7,7 +7,7 @@ service cloud.firestore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isAdmin() {
|
function isAdmin() {
|
||||||
return request.auth.token.admin;
|
return request.auth.token.admin == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGroupRole(groupId) {
|
function getGroupRole(groupId) {
|
||||||
@@ -43,19 +43,22 @@ service cloud.firestore {
|
|||||||
return getRequestField(field, "") is string;
|
return getRequestField(field, "") is string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function verifyNullType(field) {
|
||||||
|
return getRequestField(field, null) == null;
|
||||||
|
}
|
||||||
|
|
||||||
match /users/{userId} {
|
match /users/{userId} {
|
||||||
function isSignedInUser() {
|
function isSignedInUser() {
|
||||||
return request.auth.uid == userId;
|
return request.auth.uid == userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyFieldTypes() {
|
function verifyFieldTypes() {
|
||||||
return verifyStringType("display_name") &&
|
return verifyBoolType("sound") &&
|
||||||
verifyBoolType("sound") &&
|
|
||||||
verifyStringType("theme");
|
verifyStringType("theme");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPossibleFields() {
|
function getPossibleFields() {
|
||||||
let requiredFields = ["display_name", "sound", "theme"];
|
let requiredFields = ["sound", "theme"];
|
||||||
let optionalFields = [];
|
let optionalFields = [];
|
||||||
let allFields = requiredFields.concat(optionalFields);
|
let allFields = requiredFields.concat(optionalFields);
|
||||||
return [requiredFields, allFields];
|
return [requiredFields, allFields];
|
||||||
@@ -63,7 +66,6 @@ service cloud.firestore {
|
|||||||
|
|
||||||
allow read: if isSignedIn() && isSignedInUser(); // is current user's data
|
allow read: if isSignedIn() && isSignedInUser(); // is current user's data
|
||||||
allow update: if isSignedIn() && isSignedInUser() && verifyUpdateFields(getPossibleFields()) && verifyFieldTypes();
|
allow update: if isSignedIn() && isSignedInUser() && verifyUpdateFields(getPossibleFields()) && verifyFieldTypes();
|
||||||
allow delete: if isSignedIn() && (isSignedInUser() || isAdmin());
|
|
||||||
|
|
||||||
match /groups/{groupId} {
|
match /groups/{groupId} {
|
||||||
function verifyGroupFieldTypes() {
|
function verifyGroupFieldTypes() {
|
||||||
@@ -80,8 +82,8 @@ service cloud.firestore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
allow read, delete: if isSignedIn() && (isSignedInUser() || getGroupRole(groupId) == "owner" || isAdmin()); // is current user's data or is owner of group or is admin
|
allow read, delete: if isSignedIn() && (isSignedInUser() || getGroupRole(groupId) == "owner" || isAdmin()); // is current user's data or is owner of group or is admin
|
||||||
allow create: if isSignedIn() && ((isSignedInUser() && getRequestField("role", "") == "member") || ((getGroupRole(groupId) == "owner" || isAdmin()) && verifyGroupFieldTypes())) && verifyCreateFields(getPossibleGroupFields());
|
allow create: if isSignedIn() && isSignedInUser() && (getRequestField("role", "") == "member" || (isAdmin() && verifyGroupFieldTypes())) && verifyCreateFields(getPossibleGroupFields());
|
||||||
allow update: if isSignedIn() && ((isSignedInUser() && getRequestField("role", "") == "member") || ((getGroupRole(groupId) == "owner" || isAdmin()) && verifyGroupFieldTypes())) && verifyUpdateFields(getPossibleGroupFields());
|
allow update: if isSignedIn() && ((getGroupRole(groupId) == "owner" || isAdmin()) && verifyGroupFieldTypes()) && verifyUpdateFields(getPossibleGroupFields());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,54 +93,21 @@ service cloud.firestore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getPossibleFields() {
|
function getPossibleFields() {
|
||||||
let requiredFields = ["display_name"];
|
let nonStaticFields = ["display_name"];
|
||||||
let optionalFields = [];
|
let staticFields = ["join_code", "sets", "users"];
|
||||||
let allFields = requiredFields.concat(optionalFields);
|
|
||||||
return [requiredFields, allFields];
|
let allFields = staticFields.concat(nonStaticFields);
|
||||||
|
return [nonStaticFields, allFields];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPossibleUpdateFields() {
|
||||||
|
let fields = getPossibleFields();
|
||||||
|
return [[], fields[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
allow read: if isSignedIn() && (getGroupRole(groupId) != null || isAdmin());
|
allow read: if isSignedIn() && (getGroupRole(groupId) != null || isAdmin());
|
||||||
allow create: if isSignedIn() && getGroupRole(groupId) == "owner" && verifyCreateFields(getPossibleFields()) && verifyFieldTypes();
|
allow update: if isSignedIn() && (getGroupRole(groupId) == "owner" || isAdmin()) && verifyUpdateFields(getPossibleUpdateFields()) && verifyFieldTypes();
|
||||||
allow update: if isSignedIn() && (getGroupRole(groupId) == "owner" || isAdmin()) && verifyUpdateFields(getPossibleFields()) && verifyFieldTypes();
|
|
||||||
allow delete: if isSignedIn() && (getGroupRole(groupId) == "owner" || isAdmin());
|
allow delete: if isSignedIn() && (getGroupRole(groupId) == "owner" || isAdmin());
|
||||||
|
|
||||||
match /sets/{setId} {
|
|
||||||
function isSetVisibleToUser(setId) {
|
|
||||||
return (isPublicSet(setId) || isSetOwner(setId));
|
|
||||||
}
|
|
||||||
|
|
||||||
function verifySetFieldTypes() {
|
|
||||||
return getRequestField("exists", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPossibleSetFields() {
|
|
||||||
let requiredFields = ["exists"];
|
|
||||||
let optionalFields = [];
|
|
||||||
let allFields = requiredFields.concat(optionalFields);
|
|
||||||
return [requiredFields, allFields];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
allow read: if isSignedIn() && ((getGroupRole(groupId) != null) || isAdmin());
|
|
||||||
allow create: if isSignedIn() && isSetVisibleToUser(setId) && (getGroupRole(groupId) == "contributor" || getGroupRole(groupId) == "owner" || isAdmin()) && verifyCreateFields(getPossibleSetFields()) && verifySetFieldTypes();
|
|
||||||
allow delete: if isSignedIn() && (getGroupRole(groupId) == "owner" || isAdmin());
|
|
||||||
}
|
|
||||||
|
|
||||||
match /static/data {
|
|
||||||
function verifyStaticFieldTypes() {
|
|
||||||
return verifyStringType("join_code");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPossibleStaticFields() {
|
|
||||||
let requiredFields = ["join_code"];
|
|
||||||
let optionalFields = [];
|
|
||||||
let allFields = requiredFields.concat(optionalFields);
|
|
||||||
return [requiredFields, allFields];
|
|
||||||
}
|
|
||||||
|
|
||||||
allow read, delete: if isSignedIn() && (getGroupRole(groupId) == "owner" || isAdmin());
|
|
||||||
allow create: if isSignedIn() && (getGroupRole(groupId) == "owner" || isAdmin()) && verifyCreateFields(getPossibleStaticFields()) && verifyStaticFieldTypes();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -146,29 +115,28 @@ service cloud.firestore {
|
|||||||
function verifyFieldTypes() {
|
function verifyFieldTypes() {
|
||||||
return verifyBoolType("public") &&
|
return verifyBoolType("public") &&
|
||||||
verifyStringType("title") &&
|
verifyStringType("title") &&
|
||||||
verifyStringType("owner");
|
verifyStringType("owner") &&
|
||||||
|
verifyNullType("groups");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPossibleFields() {
|
function getPossibleFields() {
|
||||||
let nonStaticFields = ["public", "title"];
|
let nonStaticFields = ["public", "title"];
|
||||||
let staticFields = ["owner"];
|
let staticFields = ["owner", "groups"];
|
||||||
let requiredFields = staticFields.concat(nonStaticFields);
|
|
||||||
let optionalFields = [];
|
let allFields = staticFields.concat(nonStaticFields);
|
||||||
let allFields = requiredFields.concat(optionalFields);
|
return [nonStaticFields, allFields];
|
||||||
return [requiredFields, allFields, nonStaticFields];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPossibleCreateFields() {
|
function getPossibleCreateFields() {
|
||||||
let fields = getPossibleFields();
|
let fields = getPossibleFields();
|
||||||
return [fields[0], fields[1]];
|
return [fields[1], fields[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPossibleUpdateFields() {
|
function getPossibleUpdateFields() {
|
||||||
let fields = getPossibleFields();
|
let fields = getPossibleFields();
|
||||||
return [[], fields[2]];
|
return [[], fields[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
allow read, delete: if isSignedIn() && request.auth.uid == resource.data.owner;
|
allow read, delete: if isSignedIn() && request.auth.uid == resource.data.owner;
|
||||||
allow read: if isSignedIn() && resource.data.public;
|
allow read: if isSignedIn() && resource.data.public;
|
||||||
allow create: if isSignedIn() && request.auth.uid == request.resource.data.owner && verifyCreateFields(getPossibleCreateFields()) && verifyFieldTypes();
|
allow create: if isSignedIn() && request.auth.uid == request.resource.data.owner && verifyCreateFields(getPossibleCreateFields()) && verifyFieldTypes();
|
||||||
@@ -210,19 +178,17 @@ service cloud.firestore {
|
|||||||
|
|
||||||
allow read: if isSignedIn() && isProgressUser();
|
allow read: if isSignedIn() && isProgressUser();
|
||||||
allow delete: if isSignedIn() && isProgressUser() && isNotComplete();
|
allow delete: if isSignedIn() && isProgressUser() && isNotComplete();
|
||||||
// TODO: update and create disallowed as these are handled by Cloud Functions to ensure sound file Ids aren't altered to illegally access other files
|
// NOTE: update and create disallowed as these are handled by Cloud Functions to ensure sound file Ids aren't altered to illegally access other files
|
||||||
// TODO: disallow start_time update
|
// NOTE: disallow start_time update
|
||||||
|
|
||||||
match /terms/{vocabId} {
|
match /terms/{vocabId} {
|
||||||
allow read: if isSignedIn() && isProgressUser() && !(isLanguageSwitched());
|
allow read: if isSignedIn() && isProgressUser() && !(isLanguageSwitched());
|
||||||
// TODO: create handled by Cloud Functions
|
// NOTE: create handled by Cloud Functions
|
||||||
allow delete: if isSignedIn() && isProgressUser() && isNotComplete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match /definitions/{vocabId} {
|
match /definitions/{vocabId} {
|
||||||
allow read: if isSignedIn() && isProgressUser() && isLanguageSwitched();
|
allow read: if isSignedIn() && isProgressUser() && isLanguageSwitched();
|
||||||
// TODO: create handled by Cloud Functions
|
// NOTE: create handled by Cloud Functions
|
||||||
allow delete: if isSignedIn() && isProgressUser() && isNotComplete();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user