web-dev-qa-db-ja.com

Firestoreルールの親ドキュメントフィールドにアクセスする

私はFirestoreにレシピブックを実装しています。このブックでは、すべてのユーザーが作成したすべてのレシピを表示できますが、レシピの編集または削除はレシピの元の作成者のみが許可されています。すべてのユーザーが新しいレシピを作成することもできます。

私の問題は、サブコレクションの親ドキュメントのフィールドで「リッスン」するためのサブコレクションのアクセス許可を設定できないことです。

各レシピドキュメントには3つのものが含まれています。レシピの名前が格納されているnameというフィールド、作成者uidのrequest.auth.uidが格納されているcreatorUIDというフィールド、および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 = permit-denied]:権限がないか不十分です。 FirebaseError:権限がないか不十分です。

呼び出しはAngularクライアントとその公式ライブラリから行われます。

12
Payerl

ルールはカスケードされないため、ルールによってキャプチャされるドキュメントに必要なチェックを実行する必要があります。

一般的に言って、{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;
        }
    }
  }
}
30
Dan McGrath

上記のダンの答えはうまくいきます!参考までに、私の場合はルートの親ドキュメント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';
        }
    }
  }
}
1
sMyles