как написать правила безопасности Firestore, чтобы также разрешить значение null и неопределенное значение в одном поле?

# #firebase #google-cloud-firestore #firebase-security

Вопрос:

У меня есть поле в моем документе Firestore под названием lastApproval , которое должно быть меткой времени, если оно имеет значение.

это мои упрощенные правила

 match /users/{userID} {

  allow create: if isValidUserStructure(incomingData())
  allow update: if isValidUserStructure(incomingData())

}

function incomingData() {
  return request.resource.data;
}


function isValidUserStructure(user) {
    return  user.email is string
         amp;amp; user.fullname is string
         amp;amp; user.lastApproval is timestamp  // error in here

}
 

как вы можете видеть, isValidUserStructure функция будет использоваться для проверки при создании и обновлении пользовательского документа.

при создании пользовательского документа это lastApproval поле будет равно нулю, как это

 const data = {
  fullname: 'John Doe',
  email: 'my@email.com',
  lastApproval: null
};

await db.collection('users').doc('userIDHere').set(data);
 

но при обновлении документа мне нужна только метка времени.

 const data = {
  lastApproval: new Date()
};

await db.collection('users').doc('userIDHere').update(data);
 

а также я хочу передать правила безопасности, если lastApproval они недоступны, например, если пользователь хочет обновить полное имя только так

 const data = {
  fullname: "My New Name"
};

await db.collection('users').doc('userIDHere').update(data);
 

поэтому я хочу, чтобы мои правила безопасности принимали метку времени, значение null и неопределенное значение для lastApproval поля

Я пытался, но ошибся

введите описание изображения здесь

пожалуйста, помогите 🙂

Комментарии:

1. Один важный момент, если у других людей была та же проблема, что и у меня : вам нужно отправить ключ поля, который вы хотите проверить (в примере вверх lastApproval = null ), иначе правило не будет работать. Правила Firestore не поддерживают user.lastApproval == undefined . Обязательно включите ключ поля, даже если он равен нулю, иначе правило не будет работать.

Ответ №1:

null Насколько я знаю, такого типа не существует. Вы можете найти все доступные типы в документации.

Если вы хотите проверить, равно ли значение нулю, попробуйте user.lastApproval == null вместо этого. Чтобы проверить lastApproval , существует ли свойство в первую очередь, попробуйте это:

 match /collection/{doc} {
  allow write: if 'lastApproval' in request.resource.data amp;amp; (..otherLogic)
}
 

Таким образом, вы можете записать свою функцию как:

 function isValidUserStructure(user) {
    return  user.email is string
         amp;amp; user.fullname is string
         amp;amp; (('lastApproval' in user amp;amp; user.lastApproval is timestamp) || !('lastApproval' in user)) 
}

 

Комментарии:

1. спасибо, я понял идею, ваша логика проверки наличия свойства кажется правильной, но я не знаю, почему она не проходит модульное тестирование моих правил безопасности. Я просто использую ((user.lastApproval is timestamp) || (user.lastApproval == null)) , чтобы пройти тестирование

2. @Alexa289 вы должны проверить, определено ли это поле в первую очередь. (('lastApproval' in user amp;amp; user.lastApproval is timestamp) || !('lastApproval' in user)) . Это !(lastApproval in user) означает, что поле отсутствует, но вы все равно хотите разрешить запись, так как поле электронной почты и имя допустимы.