Правила безопасности Firestore получают поле / идентификатор ссылки - PullRequest
3 голосов
/ 14 марта 2019

У меня есть две коллекции - арендаторы и пользователи.

Документ по аренде имеет поле с именем «landlordID» и имеет тип REFERENCE (не String).

Теперь в моих правилах безопасности FirestoreЯ хочу разрешить обновление аренды ТОЛЬКО, ЕСЛИ поле landlordID этого аренды совпадает с идентификатором пользователя, отправившего запрос, а именно request.auth.uid.

Прочтите его как «разрешить обновление документа об аренде, если пользователь, создавший пользователя, аутентифицирован, следовательно, request.auth.uid! = Null, а идентификатор поля landlordID должен быть равен идентификатору запроса.auth.uid.

Следовательно, код должен быть примерно таким:

    service cloud.firestore {

      match /databases/{database}/documents {

        match /tenancies/{tenancyID}{

            allow update: if request.auth.uid != null && 
                        request.auth.uid == get(resource.data.landlordID).id
    }

}

Я также пытался get(/databases/$(database)/documents/users/$(resource.data.landlordID)).data.id

Поддержка снимка экрана моей базы данных

enter image description here

Это должно быть очень просто, но get () просто не работает. Документы Firebase, прокрутка до "Доступ к другим документам" не помогалав моей ситуации, и я не уверен, как заставить это работать.

Было бы стыдно, если ссылки не могут быть использованы таким образом, как они похожи на любое другое поле документа.

Ответы [ 3 ]

3 голосов
/ 14 марта 2019

Я вижу здесь пару проблем. Первая проблема заключается в том, что функция get () ожидает полностью указанный путь ducument, что-то вроде:

get(/databases/$(database)/documents/users/$(resource.data.landlordID)).data.id

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

Тип ссылки в Firestore не очень полезен (пока), я думаю, что вы должны хранить landlordID в виде строки, тогда вы можете просто сделать что-то вроде:

service cloud.firestore {

      match /databases/{database}/documents {

        match /tenancies/{tenancyID}{

            allow update: if request.auth.uid != resource.data.landlordID;

    }

}
2 голосов
/ 10 мая 2019

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

    function isUserRef(field) {
      return field in resource.data
        && resource.data[field] == /databases/$(database)/documents/users/$(request.auth.uid)
    }

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

1 голос
/ 20 апреля 2019

У меня была та же проблема, на которую мне нужен был ответ.См. эту гугл-ветку с ответом кого-то из гугл.Чтобы процитировать это:

Вы можете получить идентификатор из пути, используя оператор "index":

some_document_ref должно выглядеть как /databases/(default)/documents/foo/bar

который имеет 5 сегментов: ["databases", "(default)", ...]

some_document_ref[4] должен быть "бар", разрешить создание: если request.resource.data.some_document_ref [4] == "бар";

Вы можететакже используйте для них обычные функции get и exists.

Несколько сложных аспектов, с которыми вы можете столкнуться:

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

  • Там нет большой поддержкидля написания ссылок с помощью симулятора в консоли Firebase.Я использовал эмулятор Firestore, чтобы проверить это поведение (gist1, gist2)

...