You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多用户开放聊天应用的Firestore数据模型与安全规则设计咨询

关联现实活动的多用户聊天应用Firestore数据模型与安全规则探讨

应用核心需求

  • 知晓Chat ID的用户可加入/退出群聊
  • 加入群聊后可发送消息
  • 用户可标记活动参与状态(attendance:参与/待定/拒绝)
  • 用户仅能查看自己有参与状态的群聊

方案1:扁平化数据结构

数据模型

- /chat(collection)
--- creator_id
--- members [Array of userId]
--- attendance [Array of user attendances Objects]
- /messages (sub collection)
--- sender_id

安全规则

match /chat/{chatId} {
     allow create : request.resource.data.creator_id == request.auth.uid;
     allow read : if request.auth != null
     allow list : if request.auth.uid in resource.data.members
     allow update : editingOnlyAllowedFields(["members", "attendance"]) && isCreatorOrMember(chatId);
     
     match /messages/{messageId} {
         // 读取权限与chat一致
         allow create : request.resource.data.sender_id == request.auth.uid;
         allow update : resource.data.sender_id == request.auth.uid;
     }
}

function editingOnlyAllowedFields(allowedFields) {
    let editedKeys = request.resource.data.diff(resource.data).affectedKeys();
    return editedKeys.hasOnly(allowedFields);
}

function isCreatorOrMember(chatId) {
  return resource.data.creator_id == request.auth.uid || request.auth.uid in resource.data.members;
}

存在问题

前端可轻松筛选用户所属群聊,但任意成员都能移除他人或修改他人的参与状态,存在严重权限风险。


方案2:子集合拆分结构

数据模型

- /chat(collection)
--- creator_id
--- /attendance (sub collection)
----- userId (== 文档ID)
----- status
--- /messages (sub collection)
----- sender_id

安全规则

function isChatMember(chatId) {
    return request.auth != null && exists(/databases/$(database)/documents/chats/$(chatId)/attendance/$(request.auth.uid)) 
}

match /chat/{chatId} {
    allow get if request.auth != null
    allow list if isChatMember(chatId) // 此规则会触发子集合读取操作,另一种方案是用云函数在创建/attendance/userId时维护chat文档的成员数组
    allow write if request.resource.data.creator_id == request.auth.uid

    match /attendance/{userId} {
        allow write if userId == request.auth.uid
        // 读取权限与chat一致

        match /messages/{messageId} {
             // 读取权限与chat一致
             allow create : request.resource.data.sender_id == request.auth.uid;
             allow update : resource.data.sender_id == request.auth.uid;
        }
    }
}

存在问题

受Firestore「规则不是过滤器」的限制,前端无法直接通过子集合字段筛选群聊。需探讨可行解决方案,例如:

  • 用Cloud Function维护群聊文档中的成员数组
  • 批量查询用户参与的Chat ID

内容的提问来源于Stack Exchange,提问作者Nicolas Braun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 15:13:29