Как обновить правила Firestore с помощью пользовательских ролей - PullRequest
0 голосов
/ 16 июня 2020

Как настроить ПРАВИЛА для управления чтением / записью и удалением в коллекции (ЗАПИСИ) на основе пользовательских ролей, определенных в другой коллекции (ПОЛЬЗОВАТЕЛИ)?

---- Коллекция пользователей ----

USERS: {
    <RandomID1> : { uid: 234, email: "abc@xyz.com", role: "ENDUSER" },
    <RandomID2> : { uid: 100, email: "def@xyz.com", role: "ADMIN" }
}

---- Коллекция записей ----

RECORDS: {
    <RandomID1> : { uid: "234", name: "Record 123" },
    <RandomID2> : { uid: "234", name: "Record 456" },
    <RandomID3> : { uid: "999", name: "Record 999" } /* another user's record */
}

---- Текущие правила ----

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Предполагается, что пользователь зарегистрирован в веб-приложении и использует клиентский Firebase SDK, как добиться следующих случаев?

IFF: USERS.RandomID1.role = 'ENDUSER'

  1. Как ограничить пользователя ЧТЕНИЕ только его записей из ЗАПИСЕЙ, а не чужих?
  2. Как ограничить ОБНОВЛЕНИЯ только их записями в ЗАПИСИ?

  3. Как ограничить УДАЛЕНИЯ для всех своих записей в ЗАПИСИ?

  4. Как ограничить все операции CRUD для остальных коллекций (/ COLLECTION **), кроме RECORDS?

IFF: USERS.RandomID1.role = 'ADMIN'

Как разрешить этому пользователю (Администратору) выполнять все операции CRUD в ЗАПИСИ?

Итак, как переписать или обновить правила для управления этими операциями? Если нет, есть ли лучшие проекты или альтернативы?

Примечание: нам нужно обрабатывать эти случаи, чтобы заблокировать некоторых пользователей / хакеров, которые могут попытаться открыть консоль браузера / окно проверки и выполнить запросы к хранилищу с помощью или без каких-либо условий.

Благодарю за вашу помощь!

Ответы [ 2 ]

1 голос
/ 16 июня 2020

Для 5 вам нужно будет определить настраиваемые утверждения для ваших администраторов, ниже я предполагаю, что поле isadmin установлено в true для администраторов.

Следующие правила должны быть хорошими начало:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 4: Will restrict all others access
    match /records/{recordid} {
      // 1+5(read): restrict reads       
      allow read: if request.auth != null
        && (resource.data.uid == request.auth.uid || request.auth.token.isadmin);
      // 2+3+5(write): +create as a bonus
      allow write: if request.auth != null
        && (request.resource.data.uid == request.auth.uid || request.auth.token.isadmin);
    }
  }
}
0 голосов
/ 16 июля 2020

Вот мой окончательный ответ:

rules_version = '2';
service cloud.firestore {
    match /databases/{database}/documents {
        //Rule on a Collection Groups, instead of simple Collection
        match /{NestedSubCollections=**}/<COMMON_COLLECTION-NAME>/{doc} {
            allow create: if isSignedIn() && isAdmin();
            allow read: if isSignedIn() && (isAdmin() || isThisUserRecord(resource.data.<CUST_USER-ID-FIELD>));
            allow update: if isSignedIn() && (isAdmin() || isThisUserRecord(resource.data.<CUST_USER-ID-FIELD>));
            allow delete: if isSignedIn() && isAdmin();
        }
        //Collection UserDB, to validate profile updates
        match /UserDB/{userId=**} {
            allow create: if isSignedIn() && isAdmin();
            allow read: if isSignedIn() && (isAdmin() || hasUserProfile(resource.data.<CUST_USER-ID-FIELD>));
            allow update: if isSignedIn() && (isAdmin() || hasUserProfile(resource.data.<CUST_USER-ID-FIELD>));
            allow delete: if isSignedIn() && isAdmin();
        }
        //Checking if user is signed-in
        function isSignedIn() {
            return request.auth != null;
        }
        //Checking user's admin status, without the context of accessing collection, but directly
        function isAdmin() {
            return get(/databases/$(database)/documents/UserDB/$(request.auth.uid)).data.<CUST_ROLE-FIELD> == "<ADMIN-ROLE-NAME>";
        }
        //Check whether a current record belong to logged-in user; by <CUST_USER-ID-FIELD>, not oAuth-ID
        function isThisUserRecord(custUserId) {
            return get(/databases/$(database)/documents/UserDB/$(request.auth.uid)).data.<CUST_USER-ID-FIELD> == custUserId;
        }
        //Check whether a logged-in user has existing profile or not
        function hasUserProfile(userOauthId) {
            return userOauthId == request.auth.uid;
        }
    }
}

Он отлично работает в моем производственном приложении, и все защищено без написания ни одной строчки кода в приложении!

Как сделать протестировать?

  1. Обновлена ​​запись пользователя в UserDB с , и в качестве значения
  2. Затем go в ваше веб-приложение, go в консоль браузера и попытка выполнить запросы Firestore и проверить записи и результаты
  3. Если это пользователь без прав администратора , то он может только читать / обновлять в соответствии с нашими правилами, приведенными выше, а остальные запросы завершатся ошибкой, как и ожидалось.
  4. Обратите внимание, что создание / удаление выполняется в серверной части через облачную функцию по соображениям безопасности.

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

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

...