Отказано в разрешении на запрос Firestore - PullRequest
0 голосов
/ 29 июня 2018

У меня проблема со структурированием правил безопасности для Firestore. В частности:

db.collection("boards").whereEqualTo("roles.${me.email}", "admin") всегда завершается ошибкой PERMISSION_DENIED.

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

Мои правила безопасности:

service cloud.firestore {
match /databases/{database}/documents {

function isSignedIn() {
    return request.auth != null;
}

match /boards/{board} {

    //Board has owner and 3 possible roles:
    //* admin: can do everything, like an owner, but can be removed
    //* idea_reader: has read only access to the board and its ideas
    //* idea_editor: har write access to ideas and read access to the board itself
    function roles() {
    return ['admin', 'idea_reader', 'idea_editor'];
        }

    function isOwner(rsc) {
    return request.auth.uid == rsc.data.ownerId;
  }

  function getRole(rsc) {
    return rsc.data.roles[request.auth.token.email];
  }

  function isOneOfRoles(rsc, array) {
    // Determine if the user is one of an array of roles
    return isSignedIn() && (getRole(rsc) in array);
  }

  function isAnyRole(rsc) {
    //Determine if user is any role or owner. 
    return isOwner(rsc) || isOneOfRoles(rsc, roles());
  }

  function isValidNewBoard() {
    // Valid if story does not exist and data is set correctly
    return resource == null
                && request.resource.data.ownerId == request.auth.uid
          && request.resource.data.name != null;
  }

  function isValidBoardUpdate() {
    // Valid if ownerId didn't change and called by owner of admin
    return (isOwner(resource) || isOneOfRoles(resource, ['admin']))
                    && resource.data.ownerId == request.resource.data.ownerId
                    && request.resource.data.name != null;
  }

  // Owner and admin can edit. Owner can delete. 
  allow write: if isValidNewBoard() || isValidBoardUpdate();
  allow delete: if isOwner(resource);

  // Owner and any role can read 
  allow read: if isAnyRole(resource);

  match /ideas/{idea} {
    // Any role can read ideas 
    allow read: if isAnyRole(get(/databases/$(database)/documents/boards/$(board)));

    //Owner, admin and idea_editor can edit ideas
    allow write: if isOwner(get(/databases/$(database)/documents/boards/$(board)))
                                || isOneOfRoles(get(/databases/$(database)/documents/boards/$(board)), ['admin', 'idea_editor']);
  }

}

match /{document=**} {
  allow read, write: if false;
}

}
}

Ответы [ 2 ]

0 голосов
/ 08 июля 2018

Проблема была с запросом, а не с правилами безопасности. Это небольшая хитрая вещь, которая не очень хорошо документирована. Итак, давайте посмотрим на мой запрос:

db.collection("boards").whereEqualTo("roles.${me.email}", "admin")

и давайте предположим, что адрес электронной почты n.surname@gmail.com. Тогда запрос выглядит так:

db.collection("boards").whereEqualTo("roles.n.surname@gmail.com", "admin")

Таким образом, Firestore сначала пытается получить доступ к объекту roles, затем к объекту n внутри roles и так далее, и так далее. Вот почему запрос был отклонен - ​​он не соответствовал определенным правилам безопасности. Если бы это работало, у меня могли бы быть доски объявлений, к которым у меня не было бы доступа.

Чтобы исправить эту проблему, мне пришлось изменить запрос, используя FieldPath:

db.collection("boards").whereEqualTo(FieldPath.of("roles", me.email), ROLE_ADMIN)

0 голосов
/ 29 июня 2018

Должны ли литералы шаблона быть

db.collection("boards").whereEqualTo(`roles.${me.email}`, "admin")

вместо

db.collection("boards").whereEqualTo("roles.${me.email}", "admin")

Итак, когда вы пытаетесь запросить документы, на которые не распространяются правила безопасности (me.email! == "$ {me.email}"; me.email === `$ {me.email} `), вы всегда получите сообщение об отказе в разрешении.

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