0
votes

I'm having an issue with the Firebase Realtime Database rules. I register a new user with mAuth.createUserWithEmailAndPassword(email, password). In the onCompleteMethod i want to add my own user-object in the Realtime Database. I'm doing this, because each user has additional information to email/password.

After i check

FirebaseUser fireUser = FirebaseAuth.getInstance().getCurrentUser();
if(fireUser == null) {
    //do something
} else {
    createNewUser(fireUser);
}

the Method

private void createNewUser(FirebaseUser fireUser) {
        // Build the user-object.
        User user = new User();
        user.setUserId(fireUser.getUid());
        user.setUsername(name);
        user.setSex(sex);
        user.setEmail(email);
        user.setAge(time);
        user.setImageUri("");

        // Create database connection and reference.
        DatabaseReference mDatabaseRef = FirebaseDatabase.getInstance().getReference();
        mDatabaseRef.child("users").child(fireUser.getUid()).setValue(user);
    }

is called. But for some reason this DatabaseError is thrown:

W/RepoOperation: setValue at /users/9i6loj4BlCWkgkXOULWxbCSlvnx1 failed: DatabaseError: Permission denied

According to my understanding if the FirebaseUser isn't null - he is logged in and therefore my rules declared in Firebase

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

will allow the user to write the Database. However this code just works when I change my rules to ".read": "true" and ".write": "true".

So my question is: What am i doing wrong here? I only want authenticated users to read/write.

Thanks for any help!

EDIT

@Override
 public void onComplete(@NonNull Task<AuthResult> task) {
     if (!task.isSuccessful()) {
         loadingPanel.setVisibility(View.GONE);
     } else {
         loadingPanel.setVisibility(View.GONE);
         FirebaseUser fireUser = FirebaseAuth.getInstance().getCurrentUser();
         if(fireUser == null) {
             Toast.makeText(getApplicationContext(), "User is null", Toast.LENGTH_SHORT).show();
         }

         // Send verification mail
         sendVerificationEmail(fireUser);

         // Create a new User!
         createNewUser(fireUser);

         //start intent and sign out.
         Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
         FirebaseAuth.getInstance().signOut();
         startActivity(intent);
         finish();

    }
}
1
Can you update your post to include the body of your onComplete() method? That will make more clear the execution path to createNewUser(). - Bob Snyder
I added the onComplete method. I hope it helps! - Hnig

1 Answers

1
votes

Database writes do not complete synchronously. You're signing out before the database operation has time to complete:

     //start intent and sign out.
     Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
     FirebaseAuth.getInstance().signOut();  // <== Can't do this here!
     startActivity(intent);
     finish();

In createNewUser(), you can add a CompletionListener with a log statement to the setValue() call to see when the write completes. You could also add an AuthStateListener with log statement to detect when sign-in/sign-outs complete. Those logs should confirm that the sign-out is completing before the DB write.