realm / realm-js

Realm is a mobile database: an alternative to SQLite & key-value stores
https://realm.io
Apache License 2.0
5.81k stars 578 forks source link

Deleting a User Does Not Remove the User Object from Provider #5327

Open alexander-ye opened 1 year ago

alexander-ye commented 1 year ago

How frequently does the bug occur?

Always

Description

When using UserProvider (with useUser) and AppProvider (with useApp), if we do the following:

// In a component nested in the Providers
const app = useApp();
const user = useUser();

await app.deleteUser(user)

then we get user.state becomes Realm.UserState.Removed. However, the user object will still exist, and so the UserProvider will not render fallback—it will still render children.

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

No response

Version

0.4.1

What services are you using?

Atlas Device Sync

Are you using encryption?

No

Platform OS and version(s)

iOS

Build environment

Which debugger for React Native: ..

Cocoapods version

No response

alexander-ye commented 1 year ago

Updated to v.0.4.3 and it works now.

greenafrican commented 1 year ago

@alexander-ye what version of realm-js were you using? I upgraded to 0.4.3 but still having this issue. I'm on 11.2.0 of realm-js

devsales commented 1 year ago

Same here. I'm using realm: 11.3.1..

takameyer commented 1 year ago

Just tried this out and can confirm. I'll reopen this issue. Until we produce a fix, a workaround would be to invoke a logout right after the deletion.

dciccale commented 1 year ago

Just tried this out and can confirm. I'll reopen this issue. Until we produce a fix, a workaround would be to invoke a logout right after the deletion.

invoking user.logOut() after deletion does not work for me, the user still has a reference on app.currentUser. I'm using @react/realm 0.6.0 and realm 12.0.0

wouldn't be possible to implement a workaround on the library? for example at line https://github.com/realm/realm-js/blob/main/packages/realm-react/src/UserProvider.tsx#L52

~check for user.state === 'Removed'or app.currentUser.state === 'Removed' (this is the official realm state for a deleted user) and then call setUser(null)?~

that would also not work, I've checked and state is still with value LoggedIn even after calling app.deleteUser(user)

it seems that this needs to be fixed on realm native binary itself


Workaround

The only workaround I found to work is creating a custom deleteUser function on app services that calls the mongodb admin api to delete the user like so:

https://www.mongodb.com/docs/atlas/app-services/users/manage/#delete-a-user-with-a-custom-function

Note: this requires you to create api keys https://www.mongodb.com/docs/atlas/configure-api-access/#std-label-create-org-api-key

Then on the app I can call

await user.functions.deleteUser()
  .then(() => user.logOut());

This basically sends an http request to our app service function which triggers the user deletion using the mongodb admin api, and when it's done, we call user.logOut() to clear the current user and this effectively renders the fallback component from the UserProvider. This won't delete the local realm file though. It would probably be better to call app.removeUser(user) which I think it deletes the local realm files for this user. Another way would be calling realm.write(() => realm.deleteAll()) this would delete all objects in the realm, probably also from other users on the same device.