Объявление функции в правилах Firestore - PullRequest
1 голос
/ 04 июня 2019

Вот проблема, с которой я сейчас сталкиваюсь с правилами безопасности Firestore.

Прежде всего, вот пример структуры данных в моей базе данных firestore:

userProfiles/userId/userData

companies/companyId/companyData

Looksдовольно простоКаждый userData включает в себя и массив с именем companies, который включает все идентификаторы компаний, к которым у этого пользователя есть доступ.

Теперь мне нужно написать правила, разрешающие чтение companyData, только если companyId находится в определенном списке компаний с информацией о пользователях.

Вот правила, которые работают для меня:

service cloud.firestore {
  match /databases/{database}/documents {
    match /companies/{companyId} {
      allow read: if companyId in get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
    }
  }
}

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

Я изменил свои правилачтобы это выглядело так, и это также сработало для меня :

service cloud.firestore {
  match /databases/{database}/documents {
    match /companies/{companyId} {
      allow read: if companyId in getUserCompanies()
    }
    function getUserCompanies() {
        return get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
    } 
  }
}

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

service cloud.firestore {
  match /databases/{database}/documents {
    match /companies/{companyId} {
      allow read: if companyId in getUserCompanies()
    } 
  }
}

function getUserCompanies() {
    return get(/databases/$(database)/documents/userProfiles/$(request.auth.uid)).data.companies
}

И это не работает.Никаких ошибок нет, я просто получаю обычное сообщение Read denied от симулятора.

Итак, вопросы: возможно ли переместить функцию наружу, как я это сделал в своем примере?Есть ли какие-то очевидные ошибки, которые я сделал здесь?Есть ли лучший способ сделать мои правила еще более понятными?

PS Я также попытался передать некоторые параметры этой функции, включая идентификаторы пользователя и компании - не повезло.

Ответы [ 2 ]

1 голос
/ 04 июня 2019

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

Так что эта (бесполезная) функция работает, когда она определена глобально:

function isTrue() {
  return true;
}

Но эта функция не будет, потому что она не имеет доступа к request:

function isAdmin() {
  return (request.auth.token.email_verified && 
    request.auth.token.email.matches(".*@google.com"));
}

Иногда я добавляю параметр в определение функции:

function isAdmin(request) {
  return (request.auth.token.email_verified && 
    request.auth.token.email.matches(".*@google.com"));
}

и затем передаю переменную в вызов:

  allow update: if isAdmin(request) || 
    (request.auth.uid == uid && isUnmodified(request, resource, 'name'));
1 голос
/ 04 июня 2019

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

...