# #javascript #firebase #react-native #google-cloud-firestore #firebase-security
Вопрос:
Возникла проблема, из-за которой правила безопасности firestore блокируют моих слушателей в реальном времени
Вот правила безопасности:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
function isAdmin(uid) {
return get(/databases/$(database)/documents/employees/$(uid)).data["Type"] == "Admin";
}
match /transactions/{transactionID} {
//allow transaction if admin or if the user making the request is the EID of the relevant assignment
allow read, create: if isAdmin(request.auth.uid) ||
get(/databases/$(database)/documents/assignments/$(resource.data.assignment)).data.EID == request.auth.uid;
}
match /threads/{threadID} {
allow read, write: if resource.data.Parties[0] == request.auth.uid ||
resource.data.Parties[1] == request.auth.uid;
}
match /sites/{siteID} {
allow read;
}
match /employees/{employeeID} {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
match /employees/{employeeID}/EditHistory {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
match /employees/{employeeID}/Sessions {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
match /directory/{any} {
allow read;
}
match /assignments/{assignmentID} {
allow read, write: if isAdmin(request.auth.uid) ||
get(/databases/$(database)/documents/assignments/$(assignmentID)).data.EID == request.auth.uid;
}
match /analytics {
allow read: if isAdmin(request.auth.uid);
}
}
}
}
Все мои слушатели блокируются с ошибкой «недостаточно разрешений», но когда я пытаюсь выполнить соответствующие запросы get в правилах безопасности, они разрешены.
Вот пример запроса, который я пытаюсь выполнить.
firebase.auth().onAuthStateChanged(user => {
if (user) {
unsubscribeTimetrackingListener = firebase.firestore().collection('employees').doc(currentUser.uid).collection("Sessions").where("Date", "==", generateDateStr(0))
.onSnapshot((querySnapshot) => {
fetchHistory();
}, (err) => {
console.error("Timetracking Listener Error: ", err);
})
}
});
Есть ли какие-либо шаги, которые я могу предпринять отсюда, чтобы попытаться отладить, почему прослушиватели блокируются?
Спасибо.
Ответ №1:
Я бы написал ваши вложенные правила безопасности так:
match /employees/{employeeID} {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
match /EditHistory/{history} {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
match /Sessions/{session} {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
}
В целом, предоставление доступа к документам относится ТОЛЬКО К ЭТОМУ УРОВНЮ — оно НЕ распространяется автоматически на дочерние уровни. Вложенные правила, приведенные выше, добавляют доступ к вложенным коллекциям.
Вы также можете написать:
match /employees/{employeeID} {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
match /employees/{employeeID}/EditHistory{histories} {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
match /employees/{employeeID}/Sessions/{sessions} {
allow read, write: if isAdmin(request.auth.uid) ||
(employeeID == request.auth.uid)
}
[обратите внимание на добавление {истории} и {сеансов}]
Комментарии:
1. Я бы проверил
isAdmin
после проверки, совпадает ли идентификатор пользователя, чтобы вы могли сократить поиск в базе данных.