使用arrayUnion更新Firestore用户decks列表遇权限拒绝错误
问题原因与解决方案
核心问题
你遇到的权限拒绝错误,根源在于arrayUnion的特性和Firestore规则的冲突:
arrayUnion仅当元素不存在于目标数组时,才会添加元素并使数组长度+1;如果元素已存在,数组长度不会变化。- 你的规则强制要求
request.resource.data.decks.size() == resource.data.decks.size() + 1,当元素已存在时,这个条件不满足,直接触发权限拒绝。
排查与解决步骤
1. 检查待添加元素是否已存在
先查询目标用户的decks数组,确认fake-deck-id是否已经存在:
const userDoc = await getDoc(doc(db, 'users', userId)); console.log(userDoc.data()?.decks);
如果该ID已在数组中,arrayUnion不会修改数组,规则校验自然失败。
2. 调整Firestore规则以兼容arrayUnion
修改规则,允许数组长度不变(元素已存在时的无操作)或增加(新元素添加),同时确保新数组包含原数组的所有元素(防止恶意删除):
// Allow updates only to the "decks" and "votes" lists allow update: if request.auth != null && request.auth.uid == userId && ( ( // Allow updates to "decks" using array operations request.resource.data.keys().hasOnly(['decks']) && request.resource.data.decks is list && // 允许长度不变(元素已存在)或+1(新元素添加) request.resource.data.decks.size() >= resource.data.decks.size() && // 确保新数组包含原数组所有元素,避免恶意删除 request.resource.data.decks.hasAll(resource.data.decks) ) || ( // Allow updates to "votes" using array operations request.resource.data.keys().hasOnly(['votes']) && request.resource.data.votes is list && request.resource.data.votes.size() >= resource.data.votes.size() && request.resource.data.votes.hasAll(resource.data.votes) ) );
3. 其他排查点
- 确认
userId正确性:检查代码中userId变量是否与当前认证用户的uid完全一致,规则中request.auth.uid == userId是核心校验条件,变量错误会直接导致权限拒绝。 - 检查用户文档是否存在:如果目标用户文档尚未创建,
resource.data会为null,此时resource.data.decks.size()会触发规则校验错误。这种情况需要先初始化用户文档,或在规则中额外处理文档不存在的场景(比如补充create规则)。
内容的提问来源于stack exchange,提问作者MarksCode
相关产品推荐
相关产品推荐

