Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save shivkumarsingh7/0e561cce69ec2ca8ed6dd510b2740af9 to your computer and use it in GitHub Desktop.
Save shivkumarsingh7/0e561cce69ec2ca8ed6dd510b2740af9 to your computer and use it in GitHub Desktop.

Revisions

  1. @roalcantara roalcantara created this gist Mar 9, 2018.
    151 changes: 151 additions & 0 deletions cloud_firestore_security_rules_helper_functions.rules
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,151 @@
    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);
    }
    }
    }