访问Firestore规则

时间:2018-01-25 09:18:31

标签: firebase firebase-security angularfire2 google-cloud-firestore

我在Firestore中实施食谱书,其中每个用户都能够看到所有用户创建的所有食谱,但只允许食谱的原始作者编辑或删除食谱。任何用户也可以创建新配方。

我的问题是我无法将子集合设置为" listen"在subcollections parentdocument的字段上。

每个食谱文档包含三件事。一个名为name的字段,其中存储了食谱的名称,一个名为creatorUID的字段,其中存储了创建者uid的request.auth.uid,另一个名为ingredients的子集合包含了一些随机的字段。

service cloud.firestore {
  match /databases/{database}/documents {

    function isSignedIn() {
      return request.auth != null;
    }

    match /ListOfRecipes/{recipe} {
        allow read, create: if isSignedIn();
        allow update, delete: if resource.data.creatorUID == request.auth.uid;

        match /{list=**} {
            allow read: if isSignedIn();
            // Should return true if recipe.creatorUID has same value as request.auth.uid
            allow write: if recipe.creatorUID == request.auth.uid;
        }
    }
  }
}

问题在于,使用这些规则只能创建配方文档。自从db说明

以来,没有创建子集合及其文档
  

FirebaseError:[code = permission-denied]:权限丢失或不足。   FirebaseError:权限丢失或不足。

这些电话来自Angular客户及其官方图书馆。

3 个答案:

答案 0 :(得分:23)

规则不会级联,因此您需要对规则捕获的文档执行所需的任何检查。

一般来说,{x=**}规则通常是一个错误,=**仅用于非常具体的用例。

从您的问题来看,我假设您的数据模式是这样的:

/ListofRecipes/{recipe_document}/List/{list_document}

在这种情况下,您需要将您的规则配置为以下内容:

service cloud.firestore {
  match /databases/{database}/documents {

    function isSignedIn() {
      return request.auth != null;
    }

    match /ListOfRecipes/{recipe} {
        allow read, create: if isSignedIn();
        allow update, delete: if resource.data.creatorUID == request.auth.uid;

        function recipeData() {
            return get(/databases/$(database)/documents/ListOfRecipes/$(recipe)).data
        }

        match /List/{list} {
            allow read: if isSignedIn();
            allow write: if recipeData().creatorUID == request.auth.uid;
        }
    }
  }
}

答案 1 :(得分:1)

基于Dan的答案,您应该能够通过将creatorUID添加到子集合文档中来减少数据库中对子集合updatedelete的读取次数。

您必须将create限制为仅创建者,并确保已设置creatorUID。这是我对丹的规则的修改:

service cloud.firestore {
  match /databases/{database}/documents {

    function isSignedIn() {
      return request.auth != null;
    }

    match /ListOfRecipes/{recipe} {
        allow read, create: if isSignedIn();
        allow update, delete: if resource.data.creatorUID == request.auth.uid;

        function recipeData() {
            return get(/databases/$(database)/documents/ListOfRecipes/$(recipe)).data
        }

        match /List/{list} {
            allow read: if isSignedIn();
            allow update, delete: if resource.data.creatorUID == request.auth.uid;
            allow create: if recipeData().creatorUID == request.auth.uid
                          && request.resource.data.creatorUID == request.auth.uid;
        }
    }
  }
}

答案 2 :(得分:0)

Dan的答案非常有效!仅供参考,在我的情况下,我只需要根父文档ID,可以使用嵌套语句上方的match语句中的变量,如下所示:

service cloud.firestore {
  match /databases/{database}/documents {

    function isSignedIn() {
      return request.auth != null;
    }

    match /ListOfRecipes/{recipeID} {
        allow read, create: if isSignedIn();
        allow update, delete: if resource.data.creatorUID == request.auth.uid;

        match /List/{list} {
            allow read: if isSignedIn();
            allow write: if  recipeID == 'XXXXX';
        }
    }
  }
}