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

ServerPermissionsChanged Error when CustomUserData changes #6277

Closed
aureosouza opened this issue Nov 23, 2023 · 12 comments
Closed

ServerPermissionsChanged Error when CustomUserData changes #6277

aureosouza opened this issue Nov 23, 2023 · 12 comments
Labels
Needs-Attention Reporter has responded. Review comment. O-Community T-Bug Waiting-For-Reporter Waiting for more information from the reporter before we can proceed

Comments

@aureosouza
Copy link

aureosouza commented Nov 23, 2023

How frequently does the bug occur?

Always

Description

If we update the CustomUserData the device sync stops working on version 12.3.0 (on version 11.9.0 it works fine). We have a sync role under AppServices in Atlas Rules for one collection that depends on CustomUserData. It's a quite common scenario to update the CustomUserData and allow syncing of new data and this was working fine on 11.9.0. But we are not not able to upgrade to version 12.3.0 as this is not working anymore, we always get ServerPermissionsChanged error on Atlas logs side.

{
  "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
    }
  ]
}

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

  1. Login anonymously (or any other type of login)
const credentials = Realm.Credentials.anonymous();
await app.logIn(credentials);
  1. Try calling refreshCustomData
const user = useUser();
const realm = useRealm();

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

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

await user.refreshCustomData(); // This does not work and read/write operations to collection that depends on CustomUserData role permission don't work.
realm.syncSession?.pause();
realm.syncSession?.resume();
// Tried as well realm.syncSession?.reconnect();
  1. When we close and open app again, sync doesn not work and getting in Atlas AppService Logs:
ServerPermissionsChanged Error
ending session with error: permissions have changed since last use (ProtocolErrorCode=228)

Version

12.3.0

What services are you using?

Both Atlas Device Sync and Atlas App Services

Are you using encryption?

No

Platform OS and version(s)

iOS 16

Build environment

"react-native": "0.71.8",

Cocoapods version

No response

@takameyer
Copy link
Contributor

@aureosouza I just made some updates to one of our examples which includes a very similar use case to what you are describing.
At the moment, when updating rules, a client reset needs to occur in order to start syncing again. I would recommend setting the client reset configuration in a similar way as our examples realm config. This is using automatic recover or discard (wiping the local realm and re-downloading) on changes like this.
We do have some projects on the server side in the works that will make this flow a bit easier, but at the moment, this is our recommendation.
Let us know if this helps!

@sync-by-unito sync-by-unito bot added the Waiting-For-Reporter Waiting for more information from the reporter before we can proceed label Nov 24, 2023
@aureosouza
Copy link
Author

@takameyer thanks a lot for the support and providing the examples, we had a careful look at the code and if we understand correctly, as a workaround we would have to trigger a client reset using e.g. an Atlas function to manually delete the _realm_sync${context.app.id} database for that ownerId, together with the mode: ClientResetMode.RecoverOrDiscardUnsyncedChanges? Is this the recommended way for production at this point? Because from docs we would expect the client reset to happen automatically when custom user data changes and sync session restarts.

We believe this bug might be solved on the client side, because this is working smothly in version 11.9.0 and started breaking in version 12. Let us know if we can provide anything to help investigate and find a solution for this.

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Nov 27, 2023
@takameyer
Copy link
Contributor

takameyer commented Nov 27, 2023

@aureosouza We have recently made a fix to ensure we match up with the docs. On our original v12 release, it was assumed that this default client reset mode was happening in core, which was false. We have now set the default to ClientResetMode.RecoverUnsyncedChanges and recommend our users to use ClientResetMode.RecoveryOrDiscardUnsyncedChanges depending on their apps needs.

@aureosouza
Copy link
Author

@takameyer thanks for that but we just upgraded to latest 12.3.1 but still we are getting ServerPermissionsChanged Error in the logs in App Services after we update the custom user data. Do we still need to trigger manually a client reset using e.g. an Atlas function to manually delete the _realm_sync${context.app.id} database for that ownerId?

@takameyer
Copy link
Contributor

@aureosouza You'll need to call user.refreshCustomData() and also restart the sync session.
The first method ensures your local user data is up to date, and the second will force the client reset to occur, since the permissions have been updated.

@aureosouza
Copy link
Author

@takameyer yes we should be already doing that, and it is working fine on version 11, but does not work on version 12, let us know if the following code is missing anything:

await user.refreshCustomData(); 
realm.syncSession.pause();
realm.syncSession.resume();

Do we still need to call a similar function as your example triggerClientReset to force the client reset when rule changes?

@elle-j
Copy link
Contributor

elle-j commented Nov 28, 2023

Hi @aureosouza,

Refreshing Session:

One difference between our example code that @takameyer linked to and the code example you just provided is that we are calling realm.syncSession.resume() in the connection listener (handleConnectionChange()).

Both realm.syncSession.pause() and realm.syncSession.resume() are asynchronous methods, and a convenient way to know when the connection state has actually changed is to add a listener.

You could try a similar approach to see if your syncing starts working again. But perhaps something faster to try first is to set rerunOnOpen: true in your sync configuration for initial subscriptions.

Without knowing how your subscriptions are set up, you can always compare with our example as we use the strategy of subscribing to all objects of a certain type, then letting the backend permissions determine what gets synced to the device.

ServerPermissionsChanged:

I believe this error will still show (in the App logs) when the permissions are changed, but once the above client updates have been made, syncing should work again with the new permissions.

Trigger Client Reset:

Do we still need to call a similar function as your example triggerClientReset to force the client reset

No, that function is only used for demo purposes and should not be used in production.

@aureosouza
Copy link
Author

@elle-j thanks a lot for the support we tried the approach using the listeners to have a sync behaviour between pause and resume functions and it helped initially, but when changing a couple of times the custom user data we are getting error on mobile:

[error] Connection[1]: Session[7]: A fatal error occurred during client reset: 'A previous 'Recover' mode reset from 2023-12-01 15:14:45.549505000 did not succeed, giving up on 'Recover' mode to prevent a cycle'

One reminder that might help with investigation is that everything was perfect on version 11.9.0, so the backwards compatibility was not respected on new version 12 for the realm mobile. That's the reason we are not upgrading yet, please let us know if we can help provinding anything else, thanks again.

@kneth
Copy link
Contributor

kneth commented Dec 21, 2023

@aureosouza We have a number of fixes to client reset in recent version. Not that they seem to be related but worth to mention.

@sync-by-unito sync-by-unito bot added Waiting-For-Reporter Waiting for more information from the reporter before we can proceed and removed Needs-Attention Reporter has responded. Review comment. labels Dec 21, 2023
@aureosouza
Copy link
Author

aureosouza commented Feb 1, 2024

@kneth we just updated to latest 12.6.0 and scenario is the same, when we change the CustomUserData used in a rule for the 2nd time we get on mobile:

[error] Connection[2]: Session[8]: A fatal error occurred during client reset: 'A previous 'Recover' mode reset from 2024-02-01 14:41:08.941233000 did not succeed, giving up on 'Recover' mode to prevent a cycle'

And on server logs:

ending session with error: permissions have changed since last use (ProtocolErrorCode=228)

Reminder this does not happen on version 11, we will try to investigate the issue to help with a PR fix for this, let us know if there are any insights on this to help solving the issue, thanks.

imagem

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Feb 1, 2024
@kneth
Copy link
Contributor

kneth commented Feb 14, 2024

@aureosouza

With v12.6.0 you probably don't want to do pause()/resume() as it might cancel the client reset.

@sync-by-unito sync-by-unito bot added Waiting-For-Reporter Waiting for more information from the reporter before we can proceed and removed Needs-Attention Reporter has responded. Review comment. labels Feb 14, 2024
@aureosouza
Copy link
Author

@kneth Perfect! Removing pause and resume functions worked like a charm in version 12.6.0, I guess the reset is happening automatically on this version. Changing custom user data that depends on rules, now triggers the sync session correctly. Closing issue.

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Feb 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 Feb 20, 2024
@sync-by-unito sync-by-unito bot reopened this Feb 20, 2024
@sync-by-unito sync-by-unito bot closed this as completed Feb 21, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Needs-Attention Reporter has responded. Review comment. O-Community 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

4 participants