Device sync: granular field permissions

In one query, I’m trying to return different fields based on what permissions someone has but it doesn’t seem possible based on the current setup. For example, if someone is in someones friend list return their first name and last name, else just return their first name. I thought this would be possible with multiple rules but given it only takes one rule per query it seems tricky.

I ideally want something like this:

"MongoUser": [
      {
        "name": "read-only",
        "applyWhen": {},
        "read": true,
        "write": false,
        "fields": {
          "first_name": {
            "read": true,
            "write": false
          },
          "last_name": {
            "read": {
                "_id": {
                    "$in": "%%user.custom_data.contacts"
                }
            },
            "write": false
          },
     }
]

Is this possible in some way that I’m missing, or is this a feature request? When i try and implement something like the above I get the error that the field permission has to be a Bool not an Object.

You should be able to overcome that error as I have seen examples comparing a value to an array of values within the custom user data. Is .contacts a list of objects or a list of id values themselves?

A long note: the documentation states that custom user data should not contain ids for controlling access to individual documents. The docs clearly state tho that custom data granting access to groups of documents are ok. While you are not controlling access to an individual document specifically in your custom data, and you are granting access to a group of document fields instead, one caveat came to mind that I wanted to share with you. The docs mention that anytime custom user data changes that affect permissions, a client reset will occur. This means anytime the user’s contact list changes, you will experience a client reset.

Wanted to pass that along.

1 Like

Thanks for messaging and yeah in their docs they say not to reference set documents, although referencing users they don’t seem to be opposed to.
Contacts is an array yes. And it does work when referencing and will return if I put it in the applyWhen, or Read part of the json. However it doesn’t seem to control what field can be returned on a document by document basis. I don’t think what I want to do is possible at the moment, but I realllly wish it was. Hopefully someone see’s this and can correct me. :crossed_fingers:

@Ryan_Lindsey Field Level Permissions for sync currently only support boolean values. So you can only set

“write”: false

or

“read”: true,

For example.

Is your example just an example or do you actually want to hide the lastName of users. Sync applies a user a single role per collection on connection. So what you could do is split out the data into another top-level collection and apply FLP there.

Another option is to have add a friends array to the User document. If the userId of the user is in the friends array - then apply the friends role, which allows the user to read the lastName. Otherwise do not allow them to read the last name.

Hope this helps

1 Like

Hey Ian, thanks for following up. Our real world use case is for meeting up with people in person through events so we need to be very careful with what data we expose to the client given that we don’t want to allow strangers to be able to see other people’s location. Although if you’re someone’s friend you can see if they are nearby.

What we currently do is have a users collection, and then when we want to fetch which users are in an event, we currently have an an API which checks if they are friends or not. If they are not friends, we only return their name, user id, and phone hash. Whereas if they are friends, we return those fields, their current location, and a couple of other secure fields.

We want to start using Device sync so we can have more real-time data as opposed to using our APIs, and also that would remove the amount of code we’d have to manage. However if we just have to end up duplicating and manage that data to work with sync then the trade off doesn’t make too much sense for us.

I set up a ‘contacts’ array in the users custom_data and in my real world example there are:

  • 10 people going to the event
  • 1 of those people are my friend and are listed in my custom_data field.

What I’d like to happen is when I run the query that is on the user collection I only get the location field back for that one user.

As only one rule can be picked per session per collection, having field level permissions using an expression seems to be a way this would work perfect for our use case. Given that technically everyone can read the document, but only some can read set fields.

I hope that gives you a bit more context on what we are trying to achieve and why. Obviously there are hacky ways around it but the above solution I think would be our perfect use case.

@Ryan_Lindsey unfortunately, the only way to support this at this time is split any fields or data out of that document and into a separate collection which you can then apply different field level permissions to based on if they are a matched friend or not.

1 Like

Okay thanks Ian, good to know I wasn’t missing anything. Is this a use case you’ve seen often and are likely to add support for in the next year? Or is this likely something that is unlikely to exist in the future, or if so, be very far in the future?

@Ian_Ward Like Ryan asked, any chance additional functionality could be coming soon?

@Ian_Ward will field level permissions be supported on sync once device sync permissions are merged with the rules UI in app services?