sparkletown/sparkle

View on GitHub
firestore.rules

Summary

Maintainability
Test Coverage
rules_version = '2';

function isUpdateRestrictedToField(request, field) {
  return request.resource.data.diff(resource.data).affectedKeys().hasOnly([field]);
}

function role(name) {
  return get(/databases/$(database)/documents/roles/$(name)).data;
}

service cloud.firestore {
  match /databases/{database}/documents {
    function worldFromResource() {
      return get(/databases/$(database)/documents/worlds/$(resource.data.worldId)).data;
    }

    function worldFromRequest() {
      return get(/databases/$(database)/documents/worlds/$(request.resource.data.worldId)).data;
    }

    match /authConfigs/{authConfigId} {
      allow read, write: if false;
    }
    match /users/{userId} {
      allow get: if request.auth.uid != null;
      allow list: if true;
      allow write: if request.auth.uid == userId;

      match /visits/{venueId} {
        allow read: if true;
        allow write: if request.auth.uid == userId;
      }
    }
    match /userprivate/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
    match /privatechats/{userId}/{restOfPath=**} {
      allow create: if request.auth.uid != null && request.resource.data.fromUser.id == request.auth.uid;
      allow read: if request.auth.uid != null && userId == request.auth.uid;
      allow update: if request.auth.uid != null && isUpdateRestrictedToField(request, 'isRead');
    }
    match /experiences/{experienceId}/{restOfPath=**} {
      allow read, write: if request.auth.uid != null;
    }
    match /venues/{venue} {
      allow read: if true;

      function venueData() {
        return get(/databases/$(database)/documents/venues/$(venue)).data;
      }

      function world() {
        return get(/databases/$(database)/documents/worlds/$(venueData().worldId)).data;
      }

      function checkIfSpaceOrWorldOwner() {
        return request.auth.uid in role('admin').users || request.auth.uid in venueData().owners || request.auth.uid in world().owners
      }

      match /events/{event} {
        allow read: if true;
        allow write: if checkIfSpaceOrWorldOwner();
      }

      match /chatMessagesCounter/{shardId} {
        allow read, write: if request.auth.uid != null;
        allow delete: if false;
      }
      match /chats/{messageId} {
        allow read, create: if request.auth.uid != null && !world().isHidden;
        allow delete: if checkIfSpaceOrWorldOwner();
        allow update: if request.auth.uid != null && isUpdateRestrictedToField(request, 'repliesCount');

        match /thread/{messageId} {
          allow read, create: if request.auth.uid != null;
          allow delete: if checkIfSpaceOrWorldOwner();
          allow update: if false;
        }
      }

      match /jukeboxMessages/{restOfPath=**} {
        allow read, create: if request.auth.uid != null;
        allow update: if checkIfSpaceOrWorldOwner() && isUpdateRestrictedToField(request, 'deleted');
      }
      match /access/{method} {
        allow read, write: if false;
      }
      match /accessgranted/{userId} {
        allow read, write: if false;
      }
      match /recentSeatedUsers/{userId} {
        allow read: if request.auth.uid != null;
        allow write: if request.auth.uid == userId;
      }
      match /seatedTableUsers/{userId} {
        allow read: if request.auth.uid != null;
        allow write: if request.auth.uid == userId;
      }
      match /sections/{sectionId} {
        allow read: if request.auth.uid != null;
        allow write: if checkIfSpaceOrWorldOwner();
        match /seatedSectionUsers/{userId} {
          allow read: if request.auth.uid != null;
          allow write: if request.auth.uid == userId;
        }
      }
      match /screeningRoomVideos/{screeningRoomVideoId} {
        allow read: if request.auth.uid != null;
        allow write: if false;
      }
      match /firebarrels/{firebarrelId} {
        allow read: if request.auth.uid != null;
        // @debt any user can set an empty arr
        allow create, update: if request.auth.uid != null && (request.resource.data.diff(resource.data).affectedKeys().hasOnly(['connectedUsers']));
        allow delete: if false;
      }
      match /artcars/{artcarId} {
        allow read: if request.auth.uid != null;
        allow write: if false;
      }
    }
    match /roles/{roleId} {
      allow read: if request.auth.uid != null;
      allow write: if false;
    }
    match /settings/{settingId} {
      allow read: if request.auth.uid != null;
      allow write: if false;
    }
    match /sounds/{soundId} {
      allow read: if request.auth.uid != null;
      allow write: if false;
    }
    match /worlds/{worldId} {
      allow create: if request.auth.uid in role('admin').users;

      function world() {
        return get(/databases/$(database)/documents/worlds/$(worldId)).data;
      }

      allow get: if !resource.data.isHidden;
      allow list: if !resource.data.isHidden;
      allow update, delete: if request.auth.uid in role('admin').users && request.auth.uid in world().owners;
    }
    match /worldEvents/{eventId} {
      allow update, delete: if request.auth.uid in worldFromResource().owners;
      allow create: if request.auth.uid in worldFromRequest().owners;
      allow read: if true
    }
  }
}