简体   繁体   中英

How to delete a User from Firebase Database

so I wanted to add the functionality for a user to delete his account to my app.. simple right? I look in documentation, and its easy enough:

FirebaseAuth.getInstance().getCurrentUser().delete()

But then all his data in FirebaseDatabase and Storage remains. This is my structure (give or take) 在此处输入图片说明

In firebase storage its a bit simpler, so I don't include in this question..

Now the problem is, the user is associated with almost all nodes somehow, and there is a lot of places he needs to be deleted. From android device user sends "DeleteUserRequest" to server, and server takes care of delete the user. But after make the method, its hell!!! I needed to borrow dad's monitor to code it because soo deep nested calls!

here is the method

public static void deleteUser(DeleteUserRequest request, ExecutorService executorService) {
    deleteUserReferences(request.getUserId(), executorService);
    deleteUserStorage(request.getUserId());
}

/**
 * Delete Tree
 * - /grades/userId
 * - /subjects/userId
 * - /user_groups/userId -> save groupIdList
 * - /group_members/groupId/userId
 * - /groups/groupId/ [where createdBy=userId] <- Delete that Group using GroupRequestManager
 * - /user_friends/userId -> save friendIdList
 * - /user-friends/friendId/userId
 * - /user_tokens/userId
 * - /users/userId
 * - /friend_requests/userId
 * - /friend_requests/friendUserId/userId
 */
private static void deleteUserReferences(final String userId, ExecutorService executorService) {
    final MultiPathUpdate deleteUpdate = new MultiPathUpdate(FirebaseDatabase.getInstance().getReference());
    FirebaseDatabase.getInstance().getReference()
            .child(DatabaseConstants.LOCATION_GROUPS)
            .orderByChild(DatabaseConstants.PROPERTY_CREATED_BY)
            .equalTo(userId)
            .addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    final ArrayList<String> groupIdsWhereAdmin = new ArrayList<>();
                    if (dataSnapshot.exists()) {
                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                            groupIdsWhereAdmin.add(snapshot.getKey());
                        }
                    }
                    for (String groupId : groupIdsWhereAdmin) {
                        GroupRequestManager.deleteGroup(new DeleteGroupRequest(groupId, userId), executorService);
                    }
                    FirebaseDatabase.getInstance().getReference()
                            .child(DatabaseConstants.LOCATION_USER_GROUPS)
                            .child(userId)
                            .addListenerForSingleValueEvent(new ValueEventListener() {
                                @Override
                                public void onDataChange(DataSnapshot dataSnapshot) {
                                    if (dataSnapshot.exists()) {
                                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                                            final String groupId = snapshot.getKey();
                                            deleteUpdate.delete(new ChildLocation()
                                                    .child(DatabaseConstants.LOCATION_GROUP_MEMBERS)
                                                    .child(groupId)
                                                    .child(userId));
                                        }
                                    }
                                    FirebaseDatabase.getInstance().getReference()
                                            .child(DatabaseConstants.LOCATION_USER_FRIENDS)
                                            .child(userId)
                                            .addListenerForSingleValueEvent(new ValueEventListener() {
                                                @Override
                                                public void onDataChange(DataSnapshot dataSnapshot) {
                                                    if (dataSnapshot.exists()) {
                                                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                                                            final String friendId = snapshot.getKey();
                                                            deleteUpdate.delete(new ChildLocation()
                                                                    .child(DatabaseConstants.LOCATION_USER_FRIENDS)
                                                                    .child(friendId)
                                                                    .child(userId));
                                                        }
                                                    }
                                                    FirebaseDatabase.getInstance().getReference()
                                                            .child(DatabaseConstants.LOCATION_FRIEND_REQUEST)
                                                            .orderByChild(userId)
                                                            .equalTo(true)
                                                            .addListenerForSingleValueEvent(new ValueEventListener() {
                                                                @Override
                                                                public void onDataChange(DataSnapshot dataSnapshot) {
                                                                    if (dataSnapshot.exists()) {
                                                                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                                                                            final String friendRequestId = snapshot.getKey();
                                                                            deleteUpdate.delete(new ChildLocation()
                                                                                    .child(DatabaseConstants.LOCATION_FRIEND_REQUEST)
                                                                                    .child(friendRequestId)
                                                                                    .child(userId));
                                                                        }
                                                                    }
                                                                    deleteUpdate.delete(new ChildLocation()
                                                                            .child(DatabaseConstants.LOCATION_USER_GROUPS)
                                                                            .child(userId));
                                                                    deleteUpdate.delete(new ChildLocation()
                                                                            .child(DatabaseConstants.LOCATION_GRADES)
                                                                            .child(userId));
                                                                    deleteUpdate.delete(new ChildLocation()
                                                                            .child(DatabaseConstants.LOCATION_SUBJECTS)
                                                                            .child(userId));
                                                                    deleteUpdate.delete(new ChildLocation()
                                                                            .child(DatabaseConstants.LOCATION_USER_FRIENDS)
                                                                            .child(userId));
                                                                    deleteUpdate.delete(new ChildLocation()
                                                                            .child(DatabaseConstants.LOCATION_USER_TOKENS)
                                                                            .child(userId));
                                                                    deleteUpdate.delete(new ChildLocation()
                                                                            .child(DatabaseConstants.LOCATION_USERS)
                                                                            .child(userId));
                                                                    deleteUpdate.delete(new ChildLocation()
                                                                            .child(DatabaseConstants.LOCATION_FRIEND_REQUEST)
                                                                            .child(userId));
                                                                    deleteUpdate.update(new DatabaseReference.CompletionListener() {
                                                                        @Override
                                                                        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                                                                            if (databaseError != null) {
                                                                                databaseError.toException().printStackTrace();
                                                                            }
                                                                        }
                                                                    });
                                                                }
                                                                @Override
                                                                public void onCancelled(DatabaseError databaseError) {
                                                                    databaseError.toException().printStackTrace();
                                                                }
                                                            });
                                                }
                                                @Override
                                                public void onCancelled(DatabaseError databaseError) {
                                                    databaseError.toException().printStackTrace();
                                                }
                                            });

                                }
                                @Override
                                public void onCancelled(DatabaseError databaseError) {
                                    databaseError.toException().printStackTrace();
                                }
                            });
                }
                @Override
                public void onCancelled(DatabaseError databaseError) {
                    databaseError.toException().printStackTrace();
                }
            });
}

As you can see, its hell to debug and maintain... I didn't include the GroupRequestManager.deleteGroup(..) but trust, its same hell as this method.. the problem is now what should I do? Is there some sort of flattening nested call framework? Its tricky, because all these calls need to be made in order to get the correct data.. What will help solve this hell? Another style of programing? RxJava? Do I switch to kotlin? Do I just not give the user the option to delete his account, and instead just "disable" it or something?

As Doug Stevenson said, is no worse than creating the user data at all the locations. Actually is simpler. Create a method in which set the value to null for your location like this:

private static void deleteUser() {
    Map<String, Object> map = new HashMap<>();
    map.put("referenceOne", new HashMap<>().put("keyOne", null));
    map.put("referenceTwo", new HashMap<>().put(keyTwo, null));
    map.put("referenceThree", new HashMap<>().put(keyThree, null));
    //and so on
    databaseReference.updateChildren(map);
}

This is the best way to do this because you'll delete all your data at once. It is also called atomic transactions because in this way you'll be sure that all thise lines of code will be executed.

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM