Firebase Firestoreでは、(カスタム割り当てされた)管理者のみにリソースの書き込み/更新/削除を許可しようとしています。そのために、次のセキュリティルールがあります。
service cloud.firestore {
match /databases/{database}/documents {
match /resources {
allow read;
allow write, update, delete: if get(/users/$(request.auth.uid).isAdmin);
}
match /resources/{resource} {
allow read;
allow write, update, delete: if get(/users/$(request.auth.uid).isAdmin);
}
}
}
usersコレクションで管理者としてマークされているユーザーでサインインしています:
NfwIQAjfNdS85yDvd5yPVDyMTUj2は、認証ペインから取得したUIDです。
ただし、何らかの理由で(PDATE:理由が特定されました。回答を参照)、書き込み時にPERMISSION_DENIEDエラーが発生します。 resourcesコレクションは、管理者ユーザーでサインインしていることを絶対に確認した後です。
おそらく、Firestoreからリクエストログを表示することは可能ですか?それから私は何を見ることができましたrequest.auth.uid
それを私のコレクションやルールと一致させるように見えます。
質問を書いている間、私はそれを機能させました!私は2つの間違いを犯しましたが、ドキュメントを正しく読めば、どちらも回避できたはずです。
最初に、 サービス定義関数get
へのすべての呼び出しでは、パスの前に/ databases/$(database)/ documents /。そのため、このルールは次のとおりです。
allow write: if get(/users/$(request.auth.uid)).isAdmin;
これになります:
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).isAdmin;
長いですが、そうです。 Firestoreがそれ自体でそれを実行できない理由はわかりませんが、同じパスプレフィックスがget
へのすべての呼び出しで同じままであるため、おそらくこれは将来の機能のためです。クロスデータベースクエリなど、まだ準備ができていません。
Second、get
関数は resource を返します。これは、.data
を呼び出す必要があります。含まれている実際のデータを取得します。したがって、これを行う代わりに:
get(/path/to/user/).isAdmin
これを行う必要があります:
get(/path/to/user/).data.isAdmin
今、私はそのロジックを ユーザー定義関数 に抽出できたらいいのにと思います:
function isAdmin() {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin;
}
しかし、そうすると再びPERMISSION_DENIEDになり、関数で実際に何が起こっているのかを知らずに、これを理解するためにもっと時間を費やすかどうかはわかりません。
UPDATE:@ Hareesh 指摘 関数はマッチャーのスコープ内で定義する必要があるため、関数を配置することができます次のようなデフォルトのトップレベルマッチャーで:
service cloud.firestore {
match /databases/{database}/documents {
function isAdmin() {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true;
}
// ...
}
}
私が気づいたいくつかのポイント
match /resources
はコレクションを指しており、そのルールはそのドキュメントに影響を与えません。ここで私は doc から引用しています
コレクションのルールは、そのコレクション内のドキュメントには適用されません。ドキュメントレベルではなくコレクションレベルで記述されたセキュリティルールがあるのは珍しいことです(そしておそらくエラーです)。
したがって、コレクションのルールを作成する必要はありません
次に、ルールでallow write, update, delete:
あなたはどちらかを言うことができますallow write:
または具体的にはallow create, update, delete:
3つのオプションのいずれかまたはそれらを組み合わせます。
これを試して
service cloud.firestore {
match /databases/{database}/documents {
match /resources/{resource} {
function isAdmin() {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).isAdmin ||
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin;
}
allow read;
allow create, update, delete: if isAdmin();
}
}
}