Проблема с предотвращением изменения пользователями определенных полей документа в Firestore - PullRequest
0 голосов
/ 14 ноября 2018

Я использую Firebase в своем проекте Android, у меня есть коллекция пользователей в базе данных Cloud Firestore, пользователи могут обновлять только некоторые поля, но могут читать все, я знаю, что невозможно защитить часть документа от обновляется, и правила безопасности могут применяться только ко всему документу, поэтому я искал об этом, и единственное решение, которое я нашел, - это создать вложенную коллекцию внутри пользовательского документа, создать новый документ внутри этой вложенной коллекции и, наконец, поместить поля, которые я хочу защитить там, тогда я могу легко защитить этот документ, применяя этот код в разделе правил безопасности:

match /users/{userId}/securedData/{securedData} {
  allow write: if false;
  allow read: if true;
}

Так что теперь никто не может писать эти поля, но каждый может читать, и это именно то, что я хочу, но позже я обнаружил, что мне нужно запрашивать пользователей на основе полей внутри подколлекции, так называемой коллекции. групповой запрос, который на данный момент не поддерживается, поэтому я остановился на двух решениях:

  1. Извлеките всех пользователей и отфильтруйте их на стороне клиента, но это увеличит число считываемых документов, потому что я запрашиваю все документы собрания пользователей + дополнительный документ для подсборки, прочитанный для каждого пользователя, чтобы получить необходимое поле для фильтрация пользователей.
  2. Вместо создания вложенной коллекции в пользовательском документе и возникновения этих проблем, просто сохраните все поля в документе верхнего уровня (пользовательский документ), позволяя пользователям обновлять любое поле.

    match /users/{userId} {
      allow update, read: if true;
      allow create, remove: if false;
    }
    

    Но создайте облачную функцию (onUpdate) для прослушивания обновлений пользовательских документов и обнаруживать изменения в полях, которые не могут быть изменены пользователем, поэтому если пользователь попытался изменить эти поля, я могу обнаружить это и вернуть измененным полям их прежние значения, например:

    export const updateUser = functions.firestore
        .document('users/{userId}')
        .onUpdate((change, context) => {
            const previousValue = change.before.data().securedField;
            const newValue = change.after.data().securedField;
    
            if (previousValue !== newValue) {
                return db.collection('users')
                    .doc(context.params.userId)
                    .update({ securedField: previousValue });
            }
        });
    

Безопасно ли второе решение? какое лучшее решение для этого? или какие-то другие решения?

1 Ответ

0 голосов
/ 14 ноября 2018

Ваш подход, безусловно, является возможностью и интересным использованием облачных функций. Но будет задержка между операцией записи от пользователя и моментом, когда облачная функция обнаружит и отменит изменение.

Я бы наверняка уловил ситуацию в правилах безопасности. Хотя вы не можете запретить пользователю писать поля в правилах безопасности, вы можете гарантировать, что они могут записать только то же значение в поле, которое в данный момент имеет. Это эффективно также делает невозможным для них изменить значение поля. Вы делаете это:

allow write: if request.resource.data.securedField == resource.data.securedField;

Это правило гарантирует, что поле в обновленном документе (request.resource.data.securedField) будет иметь то же значение, что и поле в текущем документе (resource.data.securedField).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...