为什么我的Firebase Firestore安全规则允许对现有文档进行.set()操作,但是.set()缺少字段

丹尼尔·温纳斯滕

这是我对stackoverflow提出的第一个问题,所以请让我知道我是否缺少该问题的某些方面,这是优选的还是必需的。

我的目标是了解当创建的文档缺少下面列出的Firestore规则要求的字段时,为什么下面显示的Mocha测试通过了。

摩卡测试代码(请注意,项目ID已检查且正在运行,但此处省略)

const assert = require("assert");
const firebase = require("@firebase/rules-unit-testing");
const { firestore } = require("firebase-admin");
const { debug } = require("console");

const MY_PROJECT_ID = "####";

const myID = "user_abc";
const theirID = "user_def";

const myAuth = {uid: myID, email: "[email protected]"};
const theirAuth = {uid: theirID};

function getFirestore(auth) {
    return firebase.initializeTestApp({projectId: MY_PROJECT_ID, auth: auth}).firestore();
}


function getAdminFirestore() {
    return firebase.initializeAdminApp({projectId: MY_PROJECT_ID}).firestore();
}


beforeEach(async ()=>{
    await firebase.clearFirestoreData({projectId:MY_PROJECT_ID});
});


describe("Our Social App", () => {

    it("Can overwrite an existing post with allowed fields", async()=>{
        const postPath = "/posts/post_123";
        const admin = getAdminFirestore();
        await admin.doc(postPath).set({authorID:myID, content:"content", 
                                       visibility:"private",
                                       headline:"headline"});

        const db = getFirestore(myAuth);
        const docRef = db.doc(postPath);
        await firebase.assertSucceeds(docRef.set({}));
    });

});

after(async ()=>{
    await firebase.clearFirestoreData({projectId:MY_PROJECT_ID});
});

消防站规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    function documentFieldsCheckOut(requiredFields, allowedFields){
      let requiredAndAllowed = requiredFields.concat(allowedFields);
      return request.resource.data.keys().hasAll(requiredFields) &&
             request.resource.data.keys().hasOnly(requiredAndAllowed);
    }

    function updateHasOnlyAllowedFields(allowedFields){
      return debug(request.resource.data.keys()).hasOnly(allowedFields);
    }

    match /{document=**} {
      allow read, write: if false;
    }

    match /posts/{postID} {
   
      allow update: if ((resource.data.authorID == request.auth.uid) || userIsModerator()) 
                        && updateHasOnlyAllowedFields(["visibility", "content"]);
      
      allow create: if (request.resource.data.authorID == request.auth.uid) &&
                        documentFieldsCheckOut(["authorID", "content", "visibility", "headline"], 
                                                ["photo", "location", "tags"]);
    }

 }
}

注意:注释掉await admin.doc(postPath).set({authorID:myID, content:"content", visibility:"private", headline:"headline"});会导致测试按预期失败。
此外,将.set更改为.updateawait firebase.assertSucceeds(docRef.set({}));也会导致测试按预期失败。

弗兰克·范普菲伦

如果我对您的理解正确,那么您会问为什么此呼叫成功:

const admin = getAdminFirestore();
admin.doc(postPath).set({authorID:myID, content:"content", 
                                   visibility:"private",
                                   headline:"headline"});

使用管理特权的调用会绕过数据库的安全规则。因此,无论您使用什么安全规则,此调用都不会被他们拒绝。


第二个写操作是不同的:

const db = getFirestore(myAuth);
const docRef = db.doc(postPath);
docRef.set({})

这次,据我所知,您将通过非管理员引用,这意味着写入必须遵守安全规则才能被接受。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

firebase安全规则仅允许对文档的某些特定字段/属性进行写权限

Firestore安全规则-我可以查询具有特定字段的文档吗?

Typescript Map <enum,set <enum >>“此调用没有重载”,但是我不明白为什么?

为什么我仅添加新文档时,Firebase Firestore计数会读取操作?

为什么我的函数没有设置 Firebase 文档而是执行其他所有操作?

如果我在查询中对其进行限制,为什么 firebase firestore 会执行多个读取操作?

Firestore 安全规则是否允许我更改请求数据或现有数据?

为什么我的对象没有插入std :: set中?

List <dynamic>元素具有字段,但是我无法访问它们。为什么?

如何使用 set 方法更新 firestore 中的现有文档

Firebase Firestore 安全规则:如果按特定字段过滤,则仅允许集合组查询

Firebase Firestore 安全规则 | 如果字段值与 auth uid 相同,则允许读取

为什么memcached set操作不是幂等的?

为什么缺少字段?

为什么我的Firebase文档被覆盖?

如何使用 Firebase 安全规则仅允许指定的子名称进行写入操作

在 Android Firestore 的批量操作中使用 set() 方法增加字段

Firebase说我的规则不安全,为什么?

为什么 std::set 允许我插入重复的(非唯一的)自定义元素?

即使文档字段在Firestore安全规则中不可用,如何允许访问?

为什么向我的模型添加 related_name 会破坏使用 set_all 的现有查询集?

为什么要对List <进行泛型转换?在Sun JDK 6上成功将Set ..>扩展到List <Set ..>,但是在Oracle JDK 7上无法编译?

为什么在我尝试构建 Angular 11 应用程序时缺少“Iterable”、“Set”、“Map”等的类型定义?

为什么set_xlim()没有在我的图中设置x限制?

为什么我的bool属性没有使用C#中的Get / Set接收值?

为什么当 Set 状态改变时我的 React 组件没有重新渲染?

Django ManyToMany字段的set()操作是否清除现有关系?

如何只允许现有用户编辑他们的数据?(Firebase 安全规则)

为什么update()完全覆盖Firebase中的数据?set()与update()