Мое обходное решение:
function add(a, b, precision) {
var x = Math.pow(10, precision || 2);
return (Math.round(a * x) + Math.round(b * x)) / x;
}
precision относится к числу цифр, которые вы хотите сохранить после десятичной точки во время добавления.
Модель разрешения Firebase позволяет пользователю получить доступ к данным, к которым вы явно разрешаете доступ. Поскольку в ваших правилах безопасности вы предоставляете доступ только к /users/$uid
, пользователь не может читать из root /
. Документация Firebase описывает это в разделе «rules cascade» .
Кажется, вы хотите использовать правила безопасности для фильтрации данных, что невозможно в модели безопасности Firebase. См. Раздел «Правила не являются фильтрами» в документации Firebase, а также эти предыдущие вопросы и ответы:
Самое простое решение - разрешить чтение узла users
:
{
"rules": {
"users": {
".read": "auth !== null && auth.provider === 'password'"
}
}
}
И затем запросить на этом уровне:
getData(ref.child("users"));
Я получил это исключение, используя немного другой подход к чтению из моей базы данных, но именно так я решил проблему.
Прежде всего, моим правилам базы данных понравилось это:
{
"rules": {
"student": {
"$uid": {
".write": "auth != null && auth.uid == $uid",
".read": "auth != null && auth.uid == $uid"
}
}
}
}
Раньше, чтобы писать в базу данных ученика, я использовал этот код в своей работе:
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.e(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.e(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
...
Student student = new Student();
student.setPhoneNumber("+23480547455343");
student.setCountryOfOrigin("Nigeria");
mDatabaseReference.child("student").child(user.getUid()).setValue(student).
addOnCompleteListener(DetailsCaptureActivity.this,
new OnCompleteListener<Void>() {
...
});
Обратите внимание, как дочернее имя (ученик) совпадает с именем ребенка в данных firebase правила?
Теперь, чтобы прочитать данные этого пользователя, я сделал это:
//Set up an AuthStateListener that responds to changes in the user's sign-in state:
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
user = firebaseAuth.getCurrentUser();
if (user != null) {
databaseReference = firebaseDatabase.getReference().child("student").child(user.getUid());
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Student student = dataSnapshot.getValue(Student.class);
phoneNumberTextView.setText(student.getPhoneNumber());
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, databaseError.getMessage());
}
});
} else {
Log.e(TAG, "onAuthStateChanged:signed_out");
}
}
};
Я получил исключение, исключенное из разрешения, если только:
databaseReference = firebaseDatabase.getReference().child(user.getUid());
Проблема заключается в том, что у Firebase есть ошибка, которая после проверки подлинности вам нужно подождать, пока пользователь не появится в FirebaseAuth
, а затем вы сможете ее использовать.
Что я сделал, как
Observable.fromCallable(() -> signInImpl())
.map(this::toFirebaseUser)
.map(this::waitForUserToAppearInAuthenticator)
.flatMap(this::doSomethingInDatabase);
, где
@NonNull
private FirebaseUser waitForUserToAppearInAuthenticator(@NonNull final FirebaseUser user) {
final CountDownLatch cdl = new CountDownLatch(1);
final FirebaseAuth.AuthStateListener l = firebaseAuth -> {
final FirebaseUser cu = firebaseAuth.getCurrentUser();
if (cu != null && user.getUid().equals(cu.getUid())) {
cdl.countDown();
}
};
mFirebaseAuth.addAuthStateListener(l);
try {
cdl.await(20, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
mFirebaseAuth.removeAuthStateListener(l);
}
return user;
}