# #firebase #google-cloud-firestore #firebase-security
Вопрос:
У меня есть next.js веб-приложение, в котором пользователи должны платить, чтобы получить доступ к некоторому контенту. Я использую firebase для аутентификации и stripe для одноразовой оплаты с использованием расширения stripe firebase. Мне было интересно, есть ли способ получить доступ к паре ключ-значение, такой как оплачено: истина из «коллекции платежей», чтобы я мог использовать эту информацию для предоставления доступа пользователю или нет. Я пытался создавать пользовательские утверждения на основе пары ключ-значение, например, paid: true, но у меня была та же проблема, что и с незнанием того, как получить доступ к значению ключа для «текущего пользователя».
Я включил изображение ниже и свои правила из firestore:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid} {
allow read, write
match /checkout_sessions/{id} {
allow read, write: if request.auth.uid == uid;
}
match /subscriptions/{id} {
allow read, write: if request.auth.uid == uid;
}
match /payments/{id} {
allow read, write: if request.auth.uid == uid;
}
}
match /products/{id} {
allow read: if true;
allow write: if false;
match /prices/{id} {
allow read: if true;
allow write: if false;
}
match /tax_rates/{id} {
allow read: if true;
}
}
}
}
Ответ №1:
Мне было интересно, есть ли способ получить доступ к паре ключ-значение, такой как оплачено: истина из «коллекции платежей», чтобы я мог использовать эту информацию для предоставления доступа пользователю или нет.
Да, как объяснено в документе Firestore:
Используя функции
get()
иexists()
, ваши правила безопасности могут сравнивать входящие запросы с другими документами в базе данных.
В частности, с get()
помощью вы можете получить содержимое документа Firestore. Однако обратите внимание, что
get()
exists()
Обе функции и ожидают полностью заданных путей к документам.
Это означает, что вам нужно знать идентификатор различных документов, т. Е. user
payment
документов и, чтобы получить значение paid
поля payment
документа. Я думаю, вы знаете идентификатор документа пользователя (возможно, идентификатор uid пользователя).
Но, похоже, идентификатор платежного документа автоматически генерируется Firestore. Это может затруднить указание документа в правиле безопасности. Если вы знаете, что существует только один платежный документ, вы вполне можете назначить фиксированный идентификатор документа (например paymentDoc
) таким образом, чтобы было легко (и возможно) указать на этот документ с помощью этого get()
метода.
Что-то вроде:
allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)/payments/paymentDoc).data.paid == true;
Обратите внимание, что при использовании этих методов правил безопасности каждый раз при оценке правила учитывается одно чтение документа Firestore. Если вы знаете, что это правило будет проверяться много раз, возможно, будет лучше использовать другую систему.
Как вы уже сказали, Пользовательские утверждения являются одним из возможных решений: у вас в облаке есть Облачная функция, которая добавляет пользователю конкретное пользовательское утверждение при подтверждении платежа. (Тогда вам нужно иметь дело с другим побочным эффектом! Утверждение требует времени для распространения на аутентифицированного пользователя на стороне клиента с помощью маркера идентификатора, решения см. Здесь)
Комментарии:
1. Я смог получить идентификатор документа таким образом: const docId = firebase . firestore() .коллекция(«пользователи») .doc(user.uid) .коллекция(«платежи») .get() .затем(querySnapshot => { querySnapshot. forEach(doc => { console.log(doc.id); возврат doc.id; }); }); console.log(docId); но я не могу захватить doc.id за пределами константы docID, так как возврат обещания не определен
2. Проблема здесь в том, чтобы захватить его в правиле безопасности , где вы не можете использовать запрос.