Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After new login refreshCustomData doesn't work with useUser() #6058

Closed
ampopdev opened this issue Aug 10, 2023 · 8 comments
Closed

After new login refreshCustomData doesn't work with useUser() #6058

ampopdev opened this issue Aug 10, 2023 · 8 comments
Assignees
Labels
Encryption:Off Frequency:Always More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. O-Community Repro:Always SDK-Use:Sync T-Bug Waiting-For-Reporter Waiting for more information from the reporter before we can proceed

Comments

@ampopdev
Copy link

How frequently does the bug occur?

Always

Description

We have a sync role under App Services Mongo Atlas Rules for one collection:

{
  "roles": [
    {
      "name": "CustomUserDataRule",
      "apply_when": {},
      "document_filters": {
        "write": {
          "foo": "%%user.custom_data.foo"
        },
        "read": {
          "foo": "%%user.custom_data.foo"
        },
      },
      "read": true,
      "write": true,
      "insert": true,
      "delete": true,
      "search": true
    }
  ]
}

If we log with a new user after an anonymous, the hook useUser does return the latest user which would allow to call e.g. refreshCustomData. If we use the user object that is returned by login function then it works correctly (see reproduction steps).

If we kill and open app again everything works correctly or if roles are write/read all. We've spotted similar issues with useQuery and useRealm after a new login as well. The sync session role permissions seems to not be updated across the hooks useUser useRealm, useQuery when a new user logs in, if we have roles permission that depend on customUserData.

This is a quite common use case and is currently a deal breaker, as in general users would open app first time logged anonymously then login with email/google/apple and not expect to reopen app to perform write/read operations with new user.

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

  1. Login anonymously
const credentials = Realm.Credentials.anonymous();
await app.logIn(credentials);
  1. Login with a new user
const credentials = Realm.Credentials.emailPassword(email, password);
await app.logIn(credentials);
  1. Try calling refreshCustomData using useUser hook on a different component:
const userFromHook = useUser();

const customUserDataCollection = userFromHook.mongoClient('mongodb-atlas')
    .db('my_database')
    .collection('CustomUserData');

await customUserDataCollection.updateOne(
  { userId: userFromHook.id },
  { $set: { foo: 'bar' } },
  { upsert: true },
);

await userFromHook.refreshCustomData(); // This does not work and read/write operations to collection that depends on CustomUserData role permission don't work.

But this works correctly:

const userResponseFromLogin = await app.logIn(credentials);
const customUserDataCollection = userResponseFromLogin.mongoClient('mongodb-atlas')
    .db('my_database')
    .collection('CustomUserData');

await customUserDataCollection.updateOne(
  { userId: userResponseFromLogin.id },
  { $set: { foo: 'bar' } },
  { upsert: true },
);

await userResponseFromLogin.refreshCustomData(); // This works correctly and read/write operation to collection that depends on CustomUserData role permission are working correctly without reopening app.

A few workaround attempts that did not work:

  1. We tried saving userResponseFromLogin in redux and calling refreshCustomData after.
  2. We tried restarting the sync session before calling refreshCustomData:
realm.syncSession?.pause();
realm.syncSession?.resume();

Version

11.9.0

What services are you using?

Atlas Device Sync

Are you using encryption?

No

Platform OS and version(s)

iOS 16.4

Build environment

Which debugger for React Native: ..

Cocoapods version

No response

@kneth
Copy link
Contributor

kneth commented Aug 11, 2023

Thank you for reporting and providing so many details. We will have to investigate why the event listener used in @realm/react isn't correctly fired as we expect.

@ampopdev
Copy link
Author

@kneth we tried upgrading to latest version 12.0.0 and scenario is even worse, if we restart app we are getting:

Error: Server permissions for this file ident have changed since the last time it was used (IDENT)

In this case it's quite simple to reproduce, just upsert a new value to CustomUserData that a role depends on, like foo as example:

{
  "roles": [
    {
      "name": "CustomUserDataRule",
      "apply_when": {},
      "document_filters": {
        "write": {
          "foo": "%%user.custom_data.foo"
        },
        "read": {
          "foo": "%%user.custom_data.foo"
        },
      },
      "read": true,
      "write": true,
      "insert": true,
      "delete": true,
      "search": true
    }
  ]
}

@kneth
Copy link
Contributor

kneth commented Aug 22, 2023

@ampopdev A working hypothesis is that the interaction between (client) session multiplexing and the sync server is the root cause. Please try app.internal.syncManager.setSessionMultiplexing(false) to see if there is any change in behavior. It will help us where to investigate.

@ampopdev
Copy link
Author

@kneth we are using react-native SDK and it seems we don't have function to disable but only enableSessionMultiplexing from doc. But it could already be disabled by default, because if we call enableSessionMultiplexing we get Error: Exception in HostFunction: Cannot enable session multiplexing after creating the sync client

For now we have a non optimal workaround which is calling reset on react-navigation that wraps AppProvider, which in essence is restarting the app programmatically, let us know if there is another solution for this

navigation.dispatch(
  CommonActions.reset({
    index: 0,
    routes: [{ name: Routes.main.tabNavigator }],
  }),
);
function RealmWrapper() {
  const { RealmProvider } = PlaceRealmContext;

  return (
    <AppProvider id={'DATABASE_ID'}>
      <UserProvider fallback={TabNavigator}>
        <RealmProvider sync={{ flexible: true }}>
          <TabNavigator />
        </RealmProvider>
      </UserProvider>
    </AppProvider>
  );
}

const RootStack = createStackNavigator();
function RootNavigator() {
  return (
    <RootStack.Navigator
      initialRouteName={Routes.main.tabNavigator}
    >
      <RootStack.Screen
        name={Routes.main.tabNavigator}
        component={RealmWrapper}
      />
    </RootStack.Navigator>
  );
}

export default RootNavigator;

@kneth
Copy link
Contributor

kneth commented Aug 22, 2023

@ampopdev True, accessing an internal API will not work in production (of course, my set up is a bit different). Our sync client and server teams are looking into it.

@ampopdev
Copy link
Author

ampopdev commented Sep 26, 2023

@kneth any updates on this? Let us know if we can help with the troubleshooting, this is a big deal breaker for us at this point .

We tried upgrading to version 12.2.0 but on restart we now get [Error: Server permissions for this file ident have changed since the last time it was used (IDENT) after we update the custom user data:

Steps:

  1. Update Custom User Data
const userFromHook = useUser();

const customUserDataCollection = userFromHook.mongoClient('mongodb-atlas')
    .db('my_database')
    .collection('CustomUserData');

await customUserDataCollection.updateOne(
  { userId: userFromHook.id },
  { $set: { foo: 'bar' } },
  { upsert: true },
);

await userFromHook.refreshCustomData(); // This does not work and read/write operations to collection that depends on CustomUserData role permission don't work.
  1. Restart app and get Error (this error does not happen on version 11.9.0)

@nirinchev
Copy link
Member

This sounds like the intended behavior here. Updating the custom user data will force the server to re-evaluate the permission expressions for the user and since it could be a prohibitively expensive to diff the permissions for each object, it tells the client it needs to redownload the data. The error you're seeing should result in a client reset, which is automatically handled, after which the user will be able to use the newly downloaded Realm. You can read more about this behavior in the docs page.

@nirinchev nirinchev added the More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. label Mar 20, 2024
@sync-by-unito sync-by-unito bot assigned nirinchev and unassigned kneth Mar 20, 2024
@sync-by-unito sync-by-unito bot added the Waiting-For-Reporter Waiting for more information from the reporter before we can proceed label Mar 20, 2024
Copy link
Contributor

github-actions bot commented Apr 4, 2024

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.

@github-actions github-actions bot closed this as completed Apr 4, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Encryption:Off Frequency:Always More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. O-Community Repro:Always SDK-Use:Sync T-Bug Waiting-For-Reporter Waiting for more information from the reporter before we can proceed
Projects
None yet
Development

No branches or pull requests

3 participants