functions:
  - userExists(id): root.user_private[id].exists()
  - itemExists(id): root.item[id].exists()
  - groupExists(id): root.group[id].exists()
  - commentExists(itemId, commId): root.comment[itemId][commId].exists()
  - voteExists(itemId, voteId): root.vote[itemId][voteId].exists()
  - userHasVotedOn(id): root.user_private[auth.uid].votes.exists() && root.user_private[auth.uid].votes[id].exists()
  - userHasCommentedOn(id): root.user_private[auth.uid].comments.exists() && root.user_private[auth.uid].comments[id].exists()
  - itemOrCommentExists(id): root.item[id].exists() || root.comment[id].exists()
  - isSuperuser: auth != null && root.user_private[auth.uid].superuser == true
  - isCurrentUser(id): auth != null && auth.uid == id
  - isGroupOwner(id): auth != null && root.group[id].owner == auth.uid

root:
  user:
    .read: true
    $id:
      .write: isSuperuser() || isCurrentUser($id) || (data.admin != null && isCurrentUser(data.admin))
      firstName: required string
      lastName: required string
      icon: string
      admin: string
      groups:
        $groupId:
          role: string
          district: string


  user_private:
    .read: isSuperuser()
    $id:
      .read/write: auth != null && auth.uid == $id #superuser has auth because of
      isVerified: boolean
      email: indexed string
      superuser: isSuperuser()
      address:
        line1: string
        line2: string
        state: string
        city: string
        zip: string

      votes:
        $itemId:
          $voteId: itemOrCommentExists($itemId) && voteExists($itemId, $voteId)
      comments:
        $targetId:
          $commentId: itemOrCommentExists($targetId) && commentExists($targetId, $commentId)
#
  item:
    .read: true
    .write: isSuperuser()
    $id:
      .write: (!data.exists()) || data.owner == auth.uid

      text: string
      owner: string
      resourceLinks:
        $id:
          url: string

      onAgendas:
        $meetingId:
          groupId: string
          meetingId: string
          itemNumber: number
          closedSession: boolean
          feedbackDeadline: string

  group:
    .read: true
    $id:
      #allow anonymous users
      .write: (!prev.exists()) || isSuperuser() || isGroupOwner($id)
      name: string
      owner: string
      editors:
        $idx: string
      icon: string

      representatives:
        $repId:
          firstName: required string
          lastName: required string
          icon: string
          title: string
          district: string
          email: string

      districts:
        $districtId:
          name: string
          representative: string
      meetings:
        $meetingId:
          .value: boolean

  following:
    .read: true
    meeting:
      $meetingId:
        .write: true
        $userId:
          .value: isCurrentUser($userId)
    group:
      $groupId:
        .write: true
        $userId:
          .value: isCurrentUser($userId)

    item:
      $itemId:
        .write: true
        $userId:
          .value: isCurrentUser($userId)

  meeting:
    .read: true
    .write: isSuperuser()

    $id:
      .write: isSuperuser() || isGroupOwner(next.groupId)
      owner: userExists(next)
      startTime: required string
      endTime: required string
      groupId: groupExists(next)

      title: required string
      published: boolean
      feedbackDeadline: required string

      agenda:
        $itemId:
          .value: boolean

  comment:
    .read: true
    $targetId:
      #allow if: user is authenticated, AND
        #they're posting a new comment and have not yet commented on this item, OR
        #they're editing an existing comment and are the owner of that comment

      .write: isSuperuser()
      $commentId:
        .write: auth != null && ((!data.exists() && !userHasCommentedOn($targetId)) || (data.exists() && data.owner == auth.uid))
        role: required string
        text: required string
        owner: newData.isString() && newData == auth.uid
        posted: required string
        userDistrict: string


  vote:
    .read: true

    $itemId:
      #allow if: user is authenticated, AND
        #they're casting a new vote and have not yet voted on this item, OR
        #they're changing an existing vote and are the owner of that vote
      .write: isSuperuser()
      $voteId:
        .write: auth != null && ((!data.exists() && !userHasVotedOn($itemId)) || (data.exists() && data.owner == auth.uid))
        value: oneOf(1, -1)
        owner: next.isString() && next == auth.uid
        posted: required string
        userDistrict: string

#
#  follow:
#    $targetId:
