支払いにStripeを使用しています。このため、Firestoreに次のデータモデルがあります。
Users/{userId}/payments/{document}
各{document}
は次のようなオブジェクトです。
{
amount: 55
token: {...}
charge: {...}
}
ユーザーはtoken
フィールドに書き込める必要があります(これはサーバーに渡されるものです)が、ユーザーがcharge
フィールドに書き込めないようにしたいと思います。
現在、私のルールでは、すべてのユーザーがこのドキュメントを読み書きできます。
match /payments/{documents} {
allow read, write: if request.auth.uid == userId;
}
希望するセキュリティを実現するFirestoreルールは何ですか?
次のようなものがうまくいくと思います。これにより、クライアントは請求以外のフィールドを更新したり、請求フィールドのないドキュメントを作成したりできます。
service cloud.firestore {
match /databases/{database}/documents {
function valid_create() {
return !(request.resource.data.keys().hasAll(["charge"]));
}
function valid_update() {
return request.resource.data.charge == resource.data.charge
|| (valid_create()
&& !(resource.data.keys().hasAll(["charge"])))
}
match /payments/{userId} {
allow read: if request.auth.uid == userId;
allow create: if request.auth.uid == userId
&& valid_create();
allow update: if request.auth.uid == userId
&& valid_update();
}
}
}
この単一の関数を使用して、フィールドが作成または変更されているかどうかを確認できます。
function incomingDataHasFields(fields) {
return ((
request.writeFields == null
&& request.resource.data.keys().hasAll(fields)
) || (
request.writeFields != null
&& request.writeFields.hasAll(fields)
));
}
使用法:
match /payments/{documents} {
allow read:
if request.auth.uid == userId;
allow create, update:
if request.auth.uid == userId
&& !incomingDataHasFields(['charge']);
セキュリティをさらに強化してトークンフィールドへの書き込みのみを許可する場合:
function incomingFieldsCountIs(count) {
return ((
request.writeFields == null
&& request.resource.data.keys().size() == count
) || (
request.writeFields != null
&& request.writeFields.size() == count
));
}
...
allow create, update:
if request.auth.uid == userId
&& incomingFieldsCountIs(1)
&& incomingDataHasFields(['token'])
&& !incomingDataHasFields(['charge']);
セットタイプ が他のいくつかのクールなものとともに発表されました。
セットを使用して、ドキュメントにフィールド "a"、 "b"、および "c"のみがあることを確認します。
request.resource.data.keys().toSet() == ["a", "b", "c"].toSet()
同様に、ドキュメントに指定されたキーのみがあり、他のキーはないことを確認できます。
(request.resource.data.keys().toSet() - ["required","and","opt","keys"].toSet()).size == 0?`