Je me bats au sein de Firestore pour définir des règles de sécurité pour un document. Avec la RTDB, il était possible de définir des règles pour une propriété d'objet spécifique et j'essaie de faire de même avec Firestore.
Code RTDB:
"users": {
".read": true,
".indexOn": ["profile/name"],
"$uid": {
".read": "auth != null",
".write":
"$uid === auth.uid && !data.exists()",
"profile": {
"birthday": {
".write": "$uid === auth.uid"
},
"name": {
".write": "$uid === auth.uid"
},
"banned": {
".write": "root.child('admins').child(auth.uid).exists()"
}
}
}
}
Ci-dessous le même code dans Firestore:
service cloud.firestore {
match /databases/{database}/documents {
match /users/ {
allow read
match /{$user} {
allow read: if request.auth.uid != null
allow write: if request.auth.uid == request.resource.id && exists(/databases/$(database)/documents/users/$(request.resource.id)) === false
match /birthday {
allow write: if request.auth.uid == request.resource.id
}
match /name {
allow write: if request.auth.uid == request.resource.id
}
match /banned {
allow write: get(/databases/$(database)/documents/users/$(request.auth.uid)).data.userType > 3
}
}
}
}
}
Lorsque j'écris des règles de sécurité pour une sous-collection, cela fonctionne bien. Mais pour un champ de document, cela ne fonctionne pas. N'est-ce pas possible ou existe-t-il un segment path
spécial dans la référence de correspondance? La documentation ne dit rien à ce sujet.
Vous pouvez le faire en vérifiant le request.resource.data
propriété. Comme indiqué dans cette section de la documentation . Il vous suffit de faire correspondre le niveau du document. Vous vérifiez les règles de champ avec une condition if
.
Cependant, vous ne pouvez pas contrôler l'accès en lecture à des champs individuels. Un utilisateur peut lire un document entier ou non. Si vous devez stocker des données privées, pensez à les ajouter à une sous-collection du document utilisateur.
Voici un exemple
service cloud.firestore {
match /databases/{database}/documents {
// Make sure all cities have a positive population and
// the name is not changed
match /cities/{city} {
allow update: if request.resource.data.population > 0
&& request.resource.data.name == resource.data.name;
}
}
}