Получить Отсутствующие или недостаточные разрешения с помощью правил get () и exist () по запросу - PullRequest
1 голос
/ 26 марта 2019

Мы попытались перечислить все документы из коллекции «событий».(/event/{eventId}) в документации каждого события существует свойство 'users' (array) со всем идентификатором пользователя в событии.У нас есть другая коллекция «роль» с ролью каждого пользователя для каждого события.(/role/{eventId}/userRole/{userId})

У нас есть разрешение на получение одного события с

db.collection('event').doc(eventId).get()

Но когда мы попытались (из android и в Интернете) сделать запрос вроде

db.collection('event').where("users", "array-contains", user.uid).get()

мы получили FirebaseError: Missing or insufficient permissions.

Правила события:

    match /event/{eventId} {
      allow read:
        if isAuth() && 
        inEvent(eventId, request.auth.uid);
      allow create: 
        if isAuth() &&
        checkEventName() &&
        isOwner(database) &&
        request.resource.data.users == [];
      allow update:
        if isAuth() &&
        resource.data.ownerId == request.auth.uid &&
        checkEventName() &&
        isOwner(database) &&
        request.resource.data.mediaCount == resource.data.mediaCount &&
        request.resource.data.users == resource.data.users;
      allow delete:
        if false;
    }

Правила роли:

    match /role/{roleId} {
      allow read: 
        if isAuth();
      allow write:
        if false;

      match /userRole/{userRoleId} {
        allow read:
          if isAuth() &&
          userRoleId == request.auth.uid;
        allow create:
          if isAuth() &&
          userRoleId == request.auth.uid && 
          exists(/databases/$(database)/documents/event/$(roleId)) &&
          request.resource.data.actual is number &&
          request.resource.data.actual >= 0 &&
          request.resource.data.actual <= 10 &&
          request.resource.data.previous is number &&
          request.resource.data.actual == request.resource.data.previous;
        allow update: 
          if isAuth() &&
          userRoleId == request.auth.uid &&
          request.resource.data.actual == 0 &&
          resource.data.actual != 0;
        allow delete: 
          if false;
      }
    }

Идентификатор роли соответствует идентификатору события.

В правиле чтения события у нас есть inEvent (eventId, request.auth.uid).Когда мы пишем

function inEvent(eventID, userID) {
      return true;
}

, запрос работает, но если мы попробуем что-то вроде

return exists(/databases/$(database)/documents/role/$(eventID)/userRole/$(userID));

или

return get(/databases/$(database)/documents/role/$(eventID)/userRole/$(userID)).data.actual >= 10;

, мы всегда получим ошибку разрешения

Мы проверили все данные и правила, но мы не понимаем, почему мы можем получить отдельное событие, но не список.Что мы делаем не так?Можем ли мы использовать get () и exist () для списка разрешений?

1 Ответ

0 голосов
/ 26 марта 2019

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

Обычно это означает, что информация, которую вы хотите защитить, должна присутствовать в (или подколлекции) документе, к которому вы пытаетесь разрешить доступ, или в фиксированном месте для текущего пользователя. Лучшее, что я могу придумать для вашего случая, - это иметь ACL под событием, которое читается, хотя даже тогда я не совсем уверен, можете ли вы смоделировать его так, чтобы сервер мог статически оценивать.

Также см .:

...