realm / realm-core

Core database component for the Realm Mobile Database SDKs
https://realm.io
Apache License 2.0
1.02k stars 165 forks source link

Possibly delete_user method should clear the current user (issue being experienced usgin realm/react) #6931

Open dciccale opened 1 year ago

dciccale commented 1 year ago

Please apologise if this shouldn't be here, I've spent many hours debugging, checking stuff to be sure, building the repos and testing some fixes myself but I am unfamiliar with the project or some languages being used in order to crack it. I'll do my best to explain the issue I'm experiencing (as well as others).

Expected results

While using flex sync with @realm/react package and calling app.deleteUser(user) which calls the compiled native code SyncManager::delete_user(const std::string& user_id) apart from triggering user deletion, it should logout the deleted user. Currently using react-native sdk, deleting the user, does in fact deletes the user on client and server, but the app does not change state, and the current user stays logged in even though the user doesn't exist anymore. It should clear the current user I guess.

Actual Results

The react native app, stays on a logged-in screen, it doesn't reset the user state from the UserProvider of the realm-react sdk. Please allow me to reference this issue over the other repo, however I don't think it is an sdk bug but a core thing (i think) https://github.com/realm/realm-js/issues/5327

Steps & Code to Reproduce

Any plain example using react native and @realm/react sdk should behave like this.

From docs: https://www.mongodb.com/docs/realm/sdk/react-native/use-realm-react/

import { AppProvider, UserProvider, useApp, useUser } from '@realm/react'

const LoginComponent = () => {
  // Login functions...
  // Once logged-in it will render child components of `<UserProvider>`
  return (<></>)
};

const App = () => {
  const app = useApp();
  const user = useUser();

  async function deleteUser() {
    // Delete the currently logged in user
    await app.deleteUser(user);
  }

  return (
    <RealmProvider sync={{user, flexible: true}}>
      <button onClick={deleteUser}>Delete user</button>
    </RealmProvider>
  );
}

const AppWrapper = () => {
  return (
    <AppProvider id={appId}>
      <UserProvider fallback={LoginComponent}>
          <App />
      </UserProvider>
    </AppProvider>
  );
};

Deleting the user, deletes the user but the App stays rendered (logged-in), instead of rendering the fallback component from <UserProvider> because the app.currentUser is not being cleared after user deletion

Note: When calling user.logOut() or app.removeUser(user) which from what I understand calls SyncManager::log_out_user(const std::string& user_id) and SyncManager::remove_user(const std::string& user_id) respectively it is in fact having an effect on app.currentUser over at the react sdk https://github.com/realm/realm-js/blob/main/packages/realm-react/src/UserProvider.tsx#L52 effectively setting the user to null and rendering the "not logged-in" fallback component given to <UserProvider> which is the expected behaviour.

Core version

Core version: v13.17.2 realm-js version: 12.0.0 @realm/react version: 0.6.0

dciccale commented 1 year ago

Adding to this issue, I'm not 100% sure it is part of it but something seems off.

I am using Custom JWT Authentication

When calling delete_user it compares user->identity() against metadata->identity(), #L518 and when I open the sync_metadata.realm file (located locally on ios simulator app directory) with Realm Studio, the UserIdentity.id column and the UserMetadata.identity column do not contain the same objectId in my case. A total guess here, because I am not sure what values user->identity() and metadata.identity() are actually retreiving although it seems like those are the values, which are not equal, it means it won't be calling this line to remove the data files.

Edit1: I have found that UserMetadata table has an identities column of type List<UserIdentity> which actually holds the UserIdentity.id but the delete_user method is not checking against the UserMetadata.identities array, is only checking against the UserMetadata.identity column which doesn't match with the custom jwt identity id.

I have no idea how to further and properly debug the whole setup in between a synced realm + relam core repo + realm react repo + ios simulator all in development/compile mode to test things myself.

Nevertheless, i don't think this explains why the user stays logged in, on my initial comment, or maybe it does. This line doesn't look off to me, my app does not have multi-user setup, so it seems to be called just fine which should clear the current user, but still stays logged in.

nicooo91 commented 7 months ago

Hi! I have exactly the same issue, did you manage to solve it? Thanks in advance!