{
  "rules": {
    "appConfig": {
      "notificationBridge": {
        ".read": "auth != null",
        ".write": false,
        "enabled": {
          ".validate": "newData.isBoolean()"
        },
        "url": {
          ".validate": "newData.isString() && newData.val().matches(/^https:\\/\\/.+/)"
        }
      }
    },
    "users": {
      "$uid": {
        ".read": "auth != null",
        ".write": "auth != null && auth.uid === $uid"
      },
      ".read": "auth != null"
    },
    "following": {
      "$uid": {
        "$targetUid": {
          ".read": "auth != null && auth.uid === $uid",
          ".write": "auth != null && auth.uid === $uid",
          ".validate": "newData.hasChildren(['uid', 'displayName', 'followedAt']) && newData.child('uid').val() === $targetUid && newData.child('displayName').isString() && newData.child('displayName').val().length >= 2 && newData.child('displayName').val().length <= 30 && newData.child('followedAt').isNumber() && (!newData.child('photoData').exists() || (newData.child('photoData').isString() && newData.child('photoData').val().length <= 300000))"
        },
        ".read": "auth != null && auth.uid === $uid",
        ".write": "auth != null && auth.uid === $uid"
      }
    },
    "followers": {
      "$targetUid": {
        "$uid": {
          ".read": "auth != null && (auth.uid === $targetUid || auth.uid === $uid)",
          ".write": "auth != null && auth.uid === $uid",
          ".validate": "newData.hasChildren(['uid', 'displayName', 'followedAt']) && newData.child('uid').val() === $uid && newData.child('displayName').isString() && newData.child('displayName').val().length >= 2 && newData.child('displayName').val().length <= 30 && newData.child('followedAt').isNumber() && (!newData.child('photoData').exists() || (newData.child('photoData').isString() && newData.child('photoData').val().length <= 300000))"
        },
        ".read": "auth != null && auth.uid === $targetUid"
      }
    },
    "privateChatMembers": {
      "$chatId": {
        ".read": "auth != null && data.child(auth.uid).val() === true",
        "$uid": {
          ".write": "auth != null && (auth.uid === $uid || data.parent().child(auth.uid).val() === true)",
          ".validate": "newData.isBoolean() && newData.val() === true"
        }
      }
    },
    "privateChatInfo": {
      "$chatId": {
        ".read": "auth != null && root.child('privateChatMembers').child($chatId).child(auth.uid).val() === true",
        ".write": "auth != null && root.child('privateChatMembers').child($chatId).child(auth.uid).val() === true"
      }
    },
    "rooms": {
      "$roomId": {
        "messages": {
          ".read": "auth != null",
          "$messageId": {
            ".write": "auth != null && ((!newData.exists() && data.child('uid').val() === auth.uid) || (!data.exists() && newData.exists() && newData.child('uid').val() === auth.uid) || (data.exists() && newData.exists() && data.child('uid').val() === auth.uid && newData.child('uid').val() === auth.uid))",
            ".validate": "newData.hasChildren(['uid', 'displayName', 'type', 'text', 'imageData', 'roomName', 'createdAt']) && newData.child('uid').isString() && newData.child('displayName').isString() && newData.child('displayName').val().length >= 2 && newData.child('displayName').val().length <= 30 && newData.child('type').isString() && (newData.child('type').val() === 'text' || newData.child('type').val() === 'image' || newData.child('type').val() === 'gift') && newData.child('text').isString() && newData.child('text').val().length <= 500 && newData.child('imageData').isString() && newData.child('imageData').val().length <= 700000 && ((newData.child('type').val() === 'text' && newData.child('text').val().length > 0) || (newData.child('type').val() === 'image' && newData.child('imageData').val().length > 0) || (newData.child('type').val() === 'gift' && newData.child('text').val().length > 0)) && newData.child('roomName').isString() && newData.child('createdAt').isNumber() && (!newData.child('photoData').exists() || (newData.child('photoData').isString() && newData.child('photoData').val().length <= 300000))",
            "reactions": {
              "$reaction": {
                "$reactorUid": {
                  ".write": "auth != null && auth.uid === $reactorUid",
                  ".validate": "newData.isBoolean() && newData.val() === true"
                }
              }
            }
          },
          ".indexOn": [
            "createdAt"
          ]
        }
      }
    },
    "privateChats": {
      "$chatId": {
        "messages": {
          ".read": "auth != null && root.child('privateChatMembers').child($chatId).child(auth.uid).val() === true",
          "$messageId": {
            ".write": "auth != null && root.child('privateChatMembers').child($chatId).child(auth.uid).val() === true && ((!newData.exists() && data.child('uid').val() === auth.uid) || (!data.exists() && newData.exists() && newData.child('uid').val() === auth.uid) || (data.exists() && newData.exists() && data.child('uid').val() === auth.uid && newData.child('uid').val() === auth.uid))",
            ".validate": "newData.hasChildren(['uid', 'displayName', 'type', 'text', 'imageData', 'roomName', 'createdAt']) && newData.child('uid').isString() && newData.child('displayName').isString() && newData.child('displayName').val().length >= 2 && newData.child('displayName').val().length <= 30 && newData.child('type').isString() && (newData.child('type').val() === 'text' || newData.child('type').val() === 'image' || newData.child('type').val() === 'gift') && newData.child('text').isString() && newData.child('text').val().length <= 500 && newData.child('imageData').isString() && newData.child('imageData').val().length <= 700000 && ((newData.child('type').val() === 'text' && newData.child('text').val().length > 0) || (newData.child('type').val() === 'image' && newData.child('imageData').val().length > 0) || (newData.child('type').val() === 'gift' && newData.child('text').val().length > 0)) && newData.child('roomName').isString() && newData.child('createdAt').isNumber() && (!newData.child('photoData').exists() || (newData.child('photoData').isString() && newData.child('photoData').val().length <= 300000))",
            "reactions": {
              "$reaction": {
                "$reactorUid": {
                  ".write": "auth != null && auth.uid === $reactorUid && root.child('privateChatMembers').child($chatId).child(auth.uid).val() === true",
                  ".validate": "newData.isBoolean() && newData.val() === true"
                }
              }
            }
          },
          ".indexOn": [
            "createdAt"
          ]
        }
      }
    },
    "reports": {
      "$roomId": {
        "$reportId": {
          ".read": false,
          ".write": "auth != null && newData.child('reporterUid').val() === auth.uid",
          ".validate": "newData.hasChildren(['reporterUid', 'messageId', 'messageUid', 'text', 'reason', 'createdAt']) && newData.child('reporterUid').isString() && newData.child('reporterUid').val() === auth.uid && newData.child('messageId').isString() && newData.child('messageUid').isString() && newData.child('text').isString() && newData.child('text').val().length <= 500 && newData.child('reason').isString() && newData.child('createdAt').isNumber()"
        }
      }
    },
    "status": {
      "$uid": {
        ".read": "auth != null",
        ".write": "auth != null && auth.uid === $uid",
        ".validate": "newData.hasChildren(['state','online','lastChanged']) && (newData.child('state').val() === 'online' || newData.child('state').val() === 'offline') && newData.child('online').isBoolean() && newData.child('lastChanged').isNumber()"
      }
    },
    "fcmTokens": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        ".write": "auth != null && auth.uid === $uid",
        "$tokenId": {
          ".write": "auth != null && auth.uid === $uid",
          ".validate": "newData.hasChildren(['token','platform','updatedAt']) && newData.child('token').isString() && newData.child('token').val().length > 20 && newData.child('token').val().length < 4096 && newData.child('platform').val() === 'android' && newData.child('updatedAt').isNumber()"
        }
      }
    },
    "userSettings": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        ".write": "auth != null && auth.uid === $uid",
        "notifications": {
          "$key": {
            ".validate": "newData.isBoolean()"
          }
        }
      }
    },
    "joinedRooms": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        "$roomId": {
          ".write": "auth != null && auth.uid === $uid",
          ".validate": "newData.hasChildren(['roomId','roomName','joinedAt']) && newData.child('roomId').val() === $roomId && newData.child('roomName').isString() && newData.child('roomName').val().length <= 60 && newData.child('joinedAt').isNumber()"
        }
      }
    },
    "roomMembers": {
      "$roomId": {
        ".read": "auth != null",
        "$uid": {
          ".write": "auth != null && auth.uid === $uid",
          ".validate": "newData.hasChildren(['uid','displayName','joinedAt','online']) && newData.child('uid').val() === $uid && newData.child('displayName').isString() && newData.child('displayName').val().length >= 2 && newData.child('displayName').val().length <= 30 && newData.child('joinedAt').isNumber() && newData.child('online').isBoolean() && (!newData.child('photoData').exists() || (newData.child('photoData').isString() && newData.child('photoData').val().length <= 300000))"
        }
      }
    },
    "unreadCounts": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        "private": {
          "$chatId": {
            ".write": "auth != null && (auth.uid === $uid || root.child('privateChatMembers').child($chatId).child(auth.uid).val() === true)"
          }
        }
      }
    },
    "notificationsInbox": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        ".write": "auth != null && auth.uid === $uid"
      }
    },
    "worldCupMatches": {
      ".read": "auth != null",
      ".indexOn": ["sortOrder", "updatedAt"],
      "$matchId": {
        "comments": {
          ".read": "auth != null",
          "$commentId": {
            ".write": "auth != null && newData.child('uid').val() === auth.uid",
            ".validate": "newData.hasChildren(['uid','displayName','text','createdAt']) && newData.child('uid').isString() && newData.child('uid').val() === auth.uid && newData.child('displayName').isString() && newData.child('displayName').val().length >= 2 && newData.child('displayName').val().length <= 30 && newData.child('text').isString() && newData.child('text').val().length > 0 && newData.child('text').val().length <= 300 && newData.child('createdAt').isNumber()"
          },
          ".indexOn": ["createdAt"]
        }
      }
    },
    "blocks": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        "$targetUid": {
          ".write": "auth != null && auth.uid === $uid"
        }
      }
    },
    "lastOnlineNotification": {
      "$targetUid": {
        "$receiverUid": {
          ".read": false,
          ".write": false
        }
      }
    },
    "adminBans": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        ".write": false
      }
    },
    "privateChatList": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        ".indexOn": ["updatedAt"],
        "$chatId": {
          ".write": "auth != null && (auth.uid === $uid || root.child('privateChatMembers').child($chatId).child(auth.uid).val() === true)"
        }
      }
    }
  }
}
