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/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)
);
}
@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?
Aucun commentaire:
Enregistrer un commentaire