Created
March 9, 2018 01:46
-
-
Save roalcantara/d710de0131976aea753bbb981f5f0d11 to your computer and use it in GitHub Desktop.
Cloud Firestore Security Rules Helper Functions
This file contains hidden or 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
service cloud.firestore { | |
match /databases/{database}/documents { | |
// USERS // | |
function isAuthenticated() { | |
return request.auth != null; | |
} | |
function userExists(uid) { | |
return exists(/databases/$(database)/documents/users/$(uid)); | |
} | |
function getUserData(uid) { | |
return get(/databases/$(database)/documents/users/$(uid)).data | |
} | |
function getCurrentUser() { | |
return getUserData(request.auth.uid) | |
} | |
// ROLES // | |
function userHasRole(uid, role) { | |
return getUserData(uid).roles[role]; | |
} | |
function userHasAnyRole(uid, roles) { | |
return getUserData(uid).roles.keys().hasAny(roles); | |
} | |
function userHasAllRoles(uid, roles) { | |
return getUserData(uid).roles.keys().hasAll(roles); | |
} | |
function getCurrentUserHasRole(role) { | |
return userHasRole(request.auth.uid, role) | |
} | |
function getCurrentUserHasAnyRole(roles) { | |
return userHasAnyRole(request.auth.uid, roles) | |
} | |
function getCurrentUserHasAllRoles(roles) { | |
return userHasAllRoles(request.auth.uid, roles) | |
} | |
function isCurrentUserAdmin() { | |
return getCurrentUserHasRole('admin'); | |
} | |
// HELPERS // | |
function isNull(value) { | |
return value == null; | |
} | |
function isTimestamp(value) { | |
return isNull(value) || value is timestamp; | |
} | |
function isString(value) { | |
return isNull(value) || value is string; | |
} | |
function isNumber(value) { | |
return isNull(value) || value is number; | |
} | |
function isInt(value) { | |
return value is int; | |
} | |
function isPresent(resource, field) { | |
return !isNull(resource.data[field]) && | |
( !isString(resource.data[field]) || resource.data[field].trim() != '' ); | |
} | |
function isRequired(resource, field, required) { | |
return !required || isPresent(resource, field); | |
} | |
function atLeast(value, min) { | |
return isNull(min) || value.trim().size() >= min; | |
} | |
function atMost(value, max) { | |
return isNull(max) || value.trim().size() <= max; | |
} | |
// VALIDATIONS // | |
function validateIncludeItems(resource, field, items) { | |
return isNull(items) || | |
isNull(resource.data[field]) || | |
resource.data[field].trim() in items; | |
} | |
function validateLength(resource, field, min, max) { | |
return isNull(min) && isNull(max) || ( | |
atLeast(resource.data[field], min) && | |
atMost(resource.data[field], max) | |
); | |
} | |
function validatePositiveNumber(resource, field, required) { | |
return isRequired(resource, field, required) && | |
isInt(resource.data[field]) && | |
resource.data[field] >= 0; | |
} | |
function validateString(resource, field, required, min, max, items) { | |
return isRequired(resource, field, required) && | |
isString(resource.data[field]) && | |
validateLength(resource, field, min, max) && | |
validateIncludeItems(resource, field, items); | |
} | |
function validateTimestamp(resource, field, required) { | |
return isRequired(resource, field, required) && | |
isTimestamp(resource.data[field]); | |
} | |
function validateUser(resource, field, required, role) { | |
return isRequired(resource, field, required) && | |
( isNull(resource.data[field]) || userExists(resource.data[field]) ) && | |
( isNull(role) || ( isNull(resource.data[field]) || userHasRole(resource.data[field], role) ) ); | |
} | |
// DOCUMENT VALIDATIONS // | |
function validateNinja(resource) { | |
return ( | |
validateString(resource, 'name', true, 4, 100, null) && | |
validatePositiveNumber(resource, 'code', true) && | |
validateUser(resource, 'created_by', true, 'admin') && | |
validateUser(resource, 'updated_by', true, 'admin') && | |
validateTimestamp(resource, 'created_at', true) && | |
validateTimestamp(resource, 'updated_at', true) | |
) | |
} | |
// MATCHERS // | |
match /ninjas/{document=**} { | |
allow read, delete: if isAuthenticated(); | |
allow create: if isAuthenticated() && validateNinja(request.resource); | |
allow update: if isAuthenticated() && validateNinja(request.resource); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
amazing.....