Правила Firestore нарушаются, если в пути к документу есть запятая

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

/companies/{company}/customers/{userId}
/users/{userId}

Теперь этот userId в значительной степени представляет собой адрес электронной почты, в котором точка заменена запятой. Точка — это символ, который не разрешен в firebase, но запятая разрешена, и наоборот с электронными письмами, так что это имеет смысл, и здесь нет проблем.

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

  function cleanEmail(){
        return request.auth.token.email.split('.').join(',') //Here I also tried %2C
    }

    function isSuperadmin() {
      return exists(/databases/$(database)/documents/admins/$(cleanEmail()))
    }


 match /companies/{company} {
      allow write: if isSuperadmin();
      allow read: if isSuperadmin() || belongsToCompany(company)
}

Симулятор ломался, но я не мог понять почему, поэтому даже отправил отчет об ошибке. В конце концов я попытался сделать путь жестко запрограммированным, а затем обнаружил проблему:

function isSuperadmin() {
      return exists(/databases/$(database)/documents/admins/test,account@gmail,com) //Same issue with get()
    }

Правила Firestore нарушаются, если в пути к документу есть запятая

Я пробовал с exists(), потому что думал, что это может быть ошибка с get(), но проблема остается. Я считаю, что это должно быть ошибкой, поскольку это правильный путь к Firestore, и я видел, как некоторые люди уже использовали эту стратегию «чистой электронной почты».

Забавно, что во время первого тестирования этого не происходило, и я понял, что эта ошибка возникает только в том случае, если запятая стоит ПЕРЕД @. Если вы удалите один перед этим и оставите второй, похоже, сработает:

Правила Firestore нарушаются, если в пути к документу есть запятая

Я мог бы добавить новый шаг к чистой электронной почте, который превращает его в base64, и это может сработать. Если у кого-то есть решение, отлично.

В большинстве систем в качестве имени документа используется UID (буквы и цифры). В правилах это может называться request.auth.uid. Это также кажется лучшим выбором, потому что UID привязан к учетной записи, чей адрес электронной почты и другая контактная информация могут меняться со временем.

danh 29.05.2019 01:07

Я понимаю, но я не могу этого сделать, как я объясняю, потому что я хочу пригласить пользователей, но я не знаю, какой у них будет UID, поэтому я не могу создать правила каким-то детерминированным образом. Я мог бы создавать пользователей, когда их приглашает компания, и тогда я могу получить UID, НО это означает, что пользователь уже создан, поэтому конечному пользователю необходимо сбросить свой пароль, чтобы войти. Не очень удобно для пользователя. Поскольку пользователь будет приглашен (например, пользователь авторизации еще не существует), мне нужен способ хранения данных таким образом, чтобы я точно знал, где будет находиться этот пользователь.

sebastianf182 29.05.2019 01:11

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

sebastianf182 29.05.2019 01:13

Не уверен, что это сработает для вас, но моя система приглашает пользователей, а затем на хуке functions.auth.user().onCreate в облаке создает для них документ в коллекции, названной по их UID. Приложение может видеть UID, как и правила. Я могу показать вам в ответе, если вы думаете, что это примерно.

danh 29.05.2019 01:20

Ну, в основном я этим и занимаюсь, так как у меня есть хук для onCreate. Как вы обрабатываете данные, которые вы хотели бы изменить от имени пользователя после того, как он наконец зарегистрируется? В моем случае это туристическое агентство, которое приглашает пользователя, и прежде чем он примет приглашение, он может сгенерировать свою поездку и все такое. Проблема в том, что, например, в этой записи о поездке не будет информации для UID, поскольку UID еще не существует :) Вы блокируете всю информацию о данных пользователя, пока они не примут приглашение? Я думаю, смогу ли я обойти это, используя только разные запросы на основе электронной почты.

sebastianf182 29.05.2019 01:35
Интеграция Angular - Firebase Analytics
Интеграция Angular - Firebase Analytics
Узнайте, как настроить Firebase Analytics и отслеживать поведение пользователей в вашем приложении Angular.
1
5
143
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я делаю что-то подобное, что выглядит примерно так:

/invitation
    /fb-generated-doc-name
        email: [email protected]
        trip: db-ref-to-trip

/usertrips
    /doc-name-is-UID
        trip: db-ref-to-trip

/trips
   /fb-generated-doc-name
       { ... describes the trip ... }

Схема для пользователя onCreate auth'd:

exports.authDidCreateUser = functions.auth.user().onCreate((authUser, context) => {
  /* 
      find invitation where email == authUser.email
      let docref = collection('usertrips').doc(authUser.uid)
      docref.set({ trip: invitation.trip })
  */
});

Это может помочь мне. Дайте мне несколько дней, чтобы попробовать что-нибудь. Спасибо!

sebastianf182 29.05.2019 05:21

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

sebastianf182 29.05.2019 21:10

Так что в конце концов я сделал что-то подобное + временные анонимные пользователи, которые «обновляются» до обычных пользователей, если пользователь регистрируется. Спасибо!

sebastianf182 05.06.2019 22:28

Другие вопросы по теме