J'utilise Stripe pour les paiements. Pour cela, j'ai le modèle de données suivant dans Firestore:
Users/{userId}/payments/{document}
chaque {document}
est un objet qui ressemble à:
{
amount: 55
token: {...}
charge: {...}
}
Les utilisateurs doivent pouvoir écrire le champ token
(c'est ce qui est transmis au serveur), mais je ne souhaite pas que les utilisateurs puissent écrire le champ charge
.
Actuellement, mes règles autorisent tout utilisateur à lire et à écrire dans ce document:
match /payments/{documents} {
allow read, write: if request.auth.uid == userId;
}
Quelles règles Firestore permettront d'atteindre la sécurité souhaitée?
Je pense que les solutions suivantes fonctionneraient, car elles permettraient aux clients de mettre à jour des champs à l'exception des frais, ainsi que de créer des documents sans le champ de frais.
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/{documents} {
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();
}
}
}
Avec cette fonction unique, vous pouvez vérifier si des champs sont/ne sont pas créés/modifiés.
function incomingDataHasFields(fields) {
return ((
request.writeFields == null
&& request.resource.data.keys().hasAll(fields)
) || (
request.writeFields != null
&& request.writeFields.hasAll(fields)
));
}
Usage:
match /payments/{documents} {
allow read:
if request.auth.uid == userId;
allow create, update:
if request.auth.uid == userId
&& !incomingDataHasFields(['charge']);
Si vous souhaitez augmenter davantage votre sécurité pour permettre l'écriture uniquement dans le champ de jeton:
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']);