Mon équipe en a discuté récemment et ne semble pas pouvoir déterminer avec certitude le comportement réel/prévu:
Si vous avez une règle de sécurité comme la suivante:
match /categories/{document=**} {
allow update: if request.auth.uid != null
&& request.resource.data.firstName is string
&& request.resource.data.lastName is string;
}
Et vous créez une instruction de mise à jour du frontend vers/categories/avec les données suivantes:
{
firstName: 'A valid firstName'
}
La règle de sécurité est-elle alors censée réussir ou échouer?
Dans le documentation de référence , il est dit que
Les données fournies par le développeur sont présentées dans request.resource.data, qui est une carte contenant les champs et les valeurs. Les champs non fournis dans la demande qui existent dans la ressource sont ajoutés à request.resource.data
Questions connexes:
{age: 28}
Question 3 avec plus de détails (question de schéma) Supposons que vous ayez un modèle comme celui-ci:
interface Category {
firstName: string;
lastName: string;
age?: int;
groupId?: string;
}
Maintenant, nous créons une règle de sécurité comme celle-ci:
match /categories/{document=**} {
allow update: if request.auth.uid != null
&& request.resource.data.firstName is string
&& request.resource.data.lastName is string;
&& request.resource.data.age is int;
&& request.resource.data.groupId is string;
}
Ensuite, nous avons le scénario suivant, si je comprends bien:
Aucun de ces scénarios correspond bien aux propriétés facultatives. Parce que si vous devez fournir toutes les propriétés (comme dans le scénario 1), ce ne sont pas vraiment des propriétés facultatives. Et si vous ne les fournissez pas, comme dans le scénario 2, cela échoue.
Peut-être que je manque quelque chose ici, un guide de base sur la façon de valider les données avec des propriétés facultatives écrites dans Firestore?
Une règle de sécurité pour un paramètre facultatif, quelque chose comme ceci:
match /categories/{document=**} {
allow update: if request.auth.uid != null
&& request.resource.data.firstName is string
&& request.resource.data.lastName is string;
&& request.resource.data.age is int; // ignore if NOT provided
&& request.resource.data.groupId is string; // ignore if NOT provided
}
La règle de sécurité est-elle alors censée réussir ou échouer?
Cette mise à jour réussira si le document mis à jour possède déjà un champ lastName
et que ce champ est un string
. (Je suppose que vous exécutez cette mise à jour pendant l'authentification afin que request.auth.uid != null
Renvoie vrai)
Répondre aux questions connexes:
firstName
et lastName
, l'ajout du champ age
réussira. Notez que la règle vérifie uniquement si ces 2 valeurs sont des chaînes. Il ne spécifie pas que le document ne peut pas avoir plus de 2 champs.Mise à jour :
Ce que j'ai compris de votre question mise à jour 3, c'est que vous ne souhaitez mettre à jour le document que si l'utilisateur a fourni à la fois le prénom et le nom. L'âge et groupId sont facultatifs.
Pour ce faire, vous pouvez vérifier si ce request.resource.data.firstName
N'est pas déjà celui de la base de données en utilisant: resource.data.firstName != request.resource.data.firstName
. Vos règles de sécurité devraient donc ressembler à ceci:
match /categories/{document=**} {
allow update: if request.auth.uid != null
&& (request.resource.data.firstName is string && resource.data.firstName != request.resource.data.firstName)
&& (request.resource.data.lastName is string && resource.data.firstName != request.resource.data.firstName)
&& request.resource.data.age is int
&& request.resource.data.groupId is string
}
Maintenant avec ces règles, une mise à jour avec ces données échouera:
{
firstName: 'A valid firstName'
}
Alors que ces 3 réussiront:
{
firstName: 'A valid firstName',
lastName: 'A valid lastName'
}
{
firstName: 'A valid firstName',
lastName: 'A valid lastName',
age: 20
}
{
firstName: 'A valid firstName',
lastName: 'A valid lastName',
age: 20,
groupId: 'groupId'
}
Mise à jour 2: Pour avoir age
et groupId
comme champs facultatifs, utilisez l'opérateur OR et la fonction hasAll()
pour vérifier si la demande a ces champs:
match /categories/{document=**} {
allow update: if request.auth.uid != null
&& (request.resource.data.firstName is string && resource.data.firstName != request.resource.data.firstName)
&& (request.resource.data.lastName is string && resource.data.firstName != request.resource.data.firstName)
|| (request.resource.data.keys().hasAll(['age']) && request.resource.data.age is int)
|| (request.resource.data.keys().hasAll(['groupId']) && request.resource.data.groupId is string)
}