Partial Sync / Reference Realm Status


#1

Hi there!
We’re working on an iOS app (objective-c) with a web front-end using GraphQL. We’ve had pretty good luck so far (with your help), however I’m a bit confused as to the current state of Partial Sync / Reference Realms.

First off, what’s the difference? Specifically, we’re looking for fine-grained permissions.

Secondly, I found this issue which seems to indicate that reference realms are only accessible to admin users. Am I correct in assuming this is a security issue?

To go along with that, I found another topic (which I can’t post since I’m a new user) which indicates that reference realms are still in testing.

So what’s the current state of reference realms, partial sync, and fine-grained permissions? Are they workable? What workarounds are required?

P.S. These questions all started when I tried to connect from obj-c I (using .isPartial = YES). I currently always get an error message:

HTTP response: 71aa7767-e822-440d-8cc8-c19519b37fde {“type”:“https://realm.io/docs/object-server/problems/invalid-realm-type",“title”:"The type of the Realm file was invalid.”,“status”:400,“code”:619}


#2

Here’s that second topic:


#3

@arsinio

First off, what’s the difference?

Partial Realms are created from a reference realm by executing client query-based sync. If you are looking to use fine-grained permissions you will need to use query-based sync

reference realms are only accessible to admin users.

This is a special case when using the GraphQL-Realm npm plugin. We will resolve this in the future. You can connect with normal Swift or Obj-c APIs to a reference realm with a regular user without admin priviledges.

Query-based sync has been out of beta for a while and will be our recommended way to sync going forward.

I currently always get an error message:

This is because you are attempting to connect to a full realm with a partial sync query. Click on the Realm in Studio and Click the upgrade button and you should now be able to connect.


#4

@ianward
Thanks for the clarification!!!

However, I’m afraid I’m still having problems connecting to the reference realm using a regular user…maybe I’m doing something wrong…

Here is how I’m trying to open the realm:

RLMSyncCredentials* credentials = [RLMSyncCredentials credentialsWithUsername:@"regularUser" password:@"----" register:NO];
    [RLMSyncUser logInWithCredentials:credentials
                        authServerURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://%@", SERVER_URL]]
                         onCompletion:^(RLMSyncUser * _Nullable syncUserIn, NSError * _Nullable errorIn) {
                             
                             NSURL *syncServerURL = [NSURL URLWithString:[NSString stringWithFormat:@"realms://%@/%@", SERVER_URL, @"testUserInfo"]];
                             RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
                             config.syncConfiguration = [[RLMSyncConfiguration alloc] initWithUser:syncUserIn realmURL:syncServerURL];
                             config.syncConfiguration.isPartial = YES;
                             
                             [RLMRealm asyncOpenWithConfiguration:config
                                                    callbackQueue:dispatch_get_main_queue()
                                                         callback:^(RLMRealm * _Nullable realm, NSError * _Nullable error) {
                                                             NSLog(@"here");
                                                         }];
                         }];

On the iOS side of things, my breakpoint @ “here” always gives me the following error:

Error Domain=io.realm.sync Code=4 “Operation canceled” UserInfo={NSLocalizedDescription=Operation canceled, statusCode=89}

In Realm Studio logs, I see the following:

127.0.0.1 - GET /realms/files/%2FtestUserInfo?shouldCreate=true&realmType=full HTTP/1.1 200 84 - 0.753 ms

HTTP response: 2e9a1a4d-5caa-4e1b-8b86-4b0c209ce7df {“type”:“https://realm.io/docs/object-server/problems/invalid-realm-type",“title”:"The type of the Realm file was invalid.”,“status”:400,“code”:619}

Of particular interest is the realmType=full…no matter what I’ve tried on the iOS side of things, I cannot get that to change. For reference my Realm is definitely a “reference” Realm, created and upgraded through Realm Studio.


#5

@arsinio Can you reveal System Realms, select __admin Realm and then find your Realm you are trying to connect to? What does it say for RealmType ?


#6

@ianward
Turns out this was my fault…after thinking about it for a while I realized that i hadn’t updated my Realm Cocoapod for a while…I was still at 3.4.0. Running pod update seemed to fix the problem!

This may be a question for a separate thread, but how long do query subscriptions persist (both on the device and the server)? The app we’re building has a significant offline component and it’s important that we be able to operate without an internet connection for extended periods of time. Can I subscribe to my “user data” and operate off that locally for a week or so? How do I unsubscribe to a “named” subscription? Also, do subscriptions to a given object also “sync” linked objects or do I need to subscribe to those object independently?


#7

@arsinio The subscription is persisted to disk on the device so you can use it offline and linked objects are automatically pulled in - the rest of your questions can be answered here
https://docs.realm.io/platform/using-synced-realms/syncing-data#using-query-based-synchronization


#8

@ianward
Thanks for the link! I’ve definitely read through this already, but some things aren’t apparent to me:

  • Linked objects are automatically pulled in…what about LinkingObjects (the other direction)?
  • How do subscriptions operate between “sessions” of the app? Let’s say I use the app online (subscribing to my “user data”). Close the app (without invalidateing my subscriptions) then start the app in offline mode. Is my “user data” still available?
  • Assuming the previous use-case, do I ever need to invalidate / unsubscribe from my subscriptions?

#9

@arsinio

what about LinkingObjects (the other direction)?

No - only forward links are pulled in

How do subscriptions operate between “sessions” of the app?

The subscription is persisted to disk and will work offline

do I ever need to invalidate / unsubscribe from my subscriptions?

That depends on your usecase - when you unsubscribe the data in that subscription is removed from your device.


#10

Hello,
where are we on this point ?
Do we still need to use admin users in order to get graphql access ?
Thanks!


#11

@mbritto No we respect user permissions in graphql now


#12

Is there something to change in the way we authenticate ? Does it also work with reference realms ?
I’ve added the user to a role and gave this role realm permission and it’s refused right at the refresh token /auth call :

{
    "type": "https://realm.io/docs/object-server/problems/invalid-realm-type",
    "title": "The type of the Realm file was invalid.",
    "status": 400,
    "code": 619
}

I only get this error if this user is not an Administrator.
Thanks


#13

@mbritto Sorry perhaps I misunderstood what you are trying to do - are you trying to use GraphQL with query-based sync and have it respect permissions? If so you can do that by creating subscriptions with this mutation -

An admin account is required to open a reference realm in “full” sync mode. Reference realms are designed for query-based sync


#14

Thanks for getting back to me. I’m trying to authenticate with GraphQL with my users account on a web based site. The realm is a reference realm, and I’m trying to authenticate with this :

const credentials = Credentials.usernamePassword(username, password)
const user = await User.authenticate(credentials, this.instanceUrl)
const config = await GraphQLConfig.create(user, this.realmPath)

If the user is an admin, it works. If not, the second /auth request (the one where I pass the data token and get an access_token in exchange) fails and returns this :

Once I’ll manage to authenticate the user, I’ll (probably) be able to subscribe and try to get data.


#15

@mbritto You need pass in isQueryBasedSync: true,

as the 4th argument to your create call

https://docs.realm.io/sync/graphql-web-access/using-the-graphql-client#query-based-sync-support


#16

ok so there is indeed a new way to configure the client. I haven’t noticed that change. Thanks!

First attempts make me pass the auth part (cool!) but my subscriptions queries always come back empty on the callback.
Not sure if this is related to access control or not. There is no error, just empty results where there are usually data (on full sync). I even tried a query without any filter like in the docs and nothing comes back.
Here is my subscription :

async subscribe () {
    const client = await this.getClient()
    const observable = await client.subscribe({ query: gql`
        subscription {
          users {
            uuid
            email
          }
        }
      ` })
    return observable
  }

With the observable I get :

newSubscription.subscribe({
    next (data) {
        console.log(data)
    },
    error (value) {
        console.error(value)
    }
})

The next method is called but the data is always empty :


#17

@mbritto You need to create the subscription with a specific mutation called: createXXXSubscription

See changelog here -


#18

Thanks @ianward!
That is another information I didn’t have. It’s complicated to gather all information needed between the official doc, the changelogs of the service, the changelogs of the client, etc.
This new information changes the way I’ll handle data on the website. I’ll try to switch to this later on, hopefully this will be out of beta and more documented.

Thanks for your help!