Моя цель
Я хочу разрешить ТОЛЬКО пользователям обновлять определенное поле в пользовательских документах других.
Мой пользовательский документ
/* BEFORE */
{
id: 'uid1',
profile: { /* a map of personal info */ },
connectedUsers: {
uid2: true,
uid3: true,
}
}
/* AFTER */
{
id: 'uid1',
profile: { /* a map of personal info */ },
connectedUsers: {
uid2: true,
uid3: true,
uid4: true, // <--- added.
}
}
Запрос
const selfUserId = 'uid4';
db.runTransaction(function(transaction) {
return transaction.update(userDocRef).then(function(userDoc) {
if (!userDoc.exists) { throw "Document does not exist!"; }
transaction.update(userDocRef, 'connectedUsers.${selfUserId}', true);
});
}
Мое понимание того, как работают правила:
request.resource.dara
является целевым документом entire
after
изменение.
Для операции update
вышеизложенное остается верным. Я не совсем понимаю, что означают Документы:
Для операций обновления, которые изменяют только подмножество документа
В полях переменная request.resource
будет содержать в ожидании
состояние документа после операции.
исх
Мои правила: (см. Обновление ниже)
function existingData() { return resource.data }
function expectedData() { return request.resource.data }
- проверьте, добавлено ли запрашивающее
uid
после обновления.
function isAddingRequester() {
return expectedData().connectedUsers[requesterId()] != null
}
- проверьте, добавлен ли только элемент
1
или 0
в connectedUsers
после обновления. 0
, если запрашивающая сторона уже есть в списке.
function isAddingOneAtMost() {
return expectedData().connectedUsers.size() == existingData().connectedUsers.size() + 1
|| expectedData().connectedUsers.size() == existingData().connectedUsers.size()
}
- проверить, не изменились ли все остальные поля пользовательского документа после обновления.
function isNotChangingOtherFields() {
return expectedData().id == existingData().id
&& expectedData().profile == existingData().profile
}
Мои вопросы
Правильно ли я понимаю, как правила Firestore работают? Что означает упомянутый выше документ под pending document state
?
Отражают ли мои реализации правил мои намерения? Я запутался после поиска и узнал, что на симуляторе может быть ошибка.
в моей isNotChangingOtherFields
функции, могу ли я сравнить объект profile
напрямую с оператором ==
?
Обновление - 2018/01/17 15:00
Удалено existingData()
и expectedData()
.
function isAddingRequester() {
return request.resource.data.connectedUsers[requesterId()] != null
}
function isAddingOneAtMost() {
return (request.resource.data.connectedUsers.size() == resource.data.connectedUsers.size() + 1)
|| (request.resource.data.connectedUsers.size() == resource.data.connectedUsers.size()) // NOTE: if the requester is already in the list.
}
function isNotChangingOtherFields() {
return request.resource.data.profile == resource.data.profile
&& request.resource.data.id == resource.data.id
}
function isNotAddingOtherFields() {
return request.resource.data.size() == resource.data.size()
}
Результаты отладки
Интересно, что результаты НЕ одинаковы в симуляторе и на производстве.
// PASSED in simulator & production:
allow update: if isAddingRequester();
// PASSED in simulator but NOT production:
allow update: if isNotChangingOtherFields();
// PASSED in simulator but NOT production:
allow update: if isNotAddingOtherFields();
// FAILED in both simulator AND production:
allow update: if isAddingOneAtMost();
// NOTE: inserted 2 mock data before update.
// PASSED in simulator:
allow update: if resource.data.connectedUsers.size() == 2;
// FAILED in simulator:
allow update: if request.resource.data.connectedUsers.size() == 3;
// PASSED in simulator:
allow update: if request.resource.data.connectedUsers.size() == 1;
Вопрос
Если request.resource
является документом после обновления, почему request.resource.data.connectedUsers.size()
1 вместо 3
(2 существующих + 1 новое добавленное)?
Связанные данные (из симулятора)
Если у меня есть функция:
expectedData() { return request.resource.data }
И я получил такие неожиданные результаты:
// PASSED:
allow update: if request.resource.data.id == expectedData().id;
// FAILED if the order is changed.
allow update: if expectedData().id == request.resource.data.id;