Realm permissions - Manage uses' rights

Hi all!

I’m building an iOS app with Realmk using Sync.
I’m currently trying to implement data permissions to restrict access of the users to the data.
As I saw in this post, collection level permissions are not yet available, so the only way to manage read/write access for users is to do it with sync permission. Am I right?

As far as I understand (from here), the management of the read/write permissions with sync is based on the comparison between the user id or a list of values which can be store in a collection and the partition key defined when enabling Sync.

If my understanding is correct, I have the following problem: I have several collections, each representing a group containing other collections. I’m currently using the partition key to know which collection is included in which other collection, for example:

Collection1:
Group1(id=“group1”, parentId=“root”), Group2(id=“group2”, parentId=“root”)

Collection2:
Group1.2(id=“group1.1”, parentId=“groupe1”), Groupe1.2(id=“group1.2”, parentId=“group1”),
Group2.1(id=“group2.1”, parentId=“groupe2”)

with partition key = parentId

So with this architecture, let’s say I have 100 groups in collection2, if I want my user to have read access to 80 groups, does it mean that I need to store all the partitionId of all the groups in a specific collection (like the permissions one in this example)?

I also have a second question: is there a way to let a user have read/write access only to objects in a collection that he created?

Thanks for your help!

Hi Julien, you’re correct that MongoDB Realm Sync uses the partition value to determine what data gets syncd to the mobile app. Your only allowed a single partition key attribute for all collections, but than be an ecoded key-value pair e.g., partition: parentId=123345) which opens up any number of schemes.

You can include arrays in your User document to specify what partitions a user can access. e.g.

canReadPartitions: ["parentId=12345", "parentId=54321", "otherAttribute=Fred"]

For your Realm sync permissions, you then call a Realm function (passing in the partition value) to determine whether that partition is in the current user’s approved list.

In your case, if parentId is the only attribute then maybe store a list of parentIds in the user document. Note that you could also have your Realm function match patterns - e.g. so if they have parentId: "group1" in their list then it syncs parentId: "group1.1", parentId: "group1.1", …

To only sync collections that the user has created, you could set the partition key to “user=fred”, or store the group id in a list within the user’s document. You could implement either scheme using database triggers. It feels like partition: "user=fred" could be the simpler approach.

We’ve a new guide on the data architecture/partitioning used for a mobile chat app which may give you more ideas on how to make sync partitioning work best for you.

Hi @Andrew_Morgan, thanks for your help!

I read the mobile chat app example which is very clear and helped me to better understand the use of key-value pair for partition, and the use of triggers to check sync permissions.

I just have a question: I understand that setting sync permissions allow to increase the security of the app. However, for my use-case I was wondering what is the difference between using sync permissions and the key-value partitions, as you did in the chat app, and keeping the partition value to know which group is included in which parent group (as explained in my first post) and adding another parameter to store the id of the user who created the group or “shared” if it is a group for all users. In this way, in my swift code I just need to filter my realm objects to match this new parameter = currentUser.id or “shared”.
For my use-case this solution appears to be easier than creating sync permissions, triggers and so on. However, I would like to know if it is reliable and safe to do that.

Thanks again for your help!

Hi @Julien_Chouvet, I think there are a couple of potential disadvantages in relying on a filter in your query vs. restricting things through sync permissions (which means your local realm would contain all of the data for all groups, your filter would just restrict what data the application acted on):

  1. Wasted storage on the mobile device (as it’s storing data that isn’t needed)
  2. Wasted CPU and network bandwidth syncing data that isn’t needed
  3. Longer sync times
  4. If someone hacked the mobile app or device then they’d be able to access data that they’re not entitled to
2 Likes

Ok I see. I didn’t know that filtering objects implies that the local realm will contain all the data.
Thanks again for your help! :slight_smile:

Hello again @Andrew_Morgan,

Sorry to bother you with my questions but as I was reading again your chat app example, I was wondering what is the point of setting a permission for the User because when you open the Sync, you specify partitionValue: "user=\(user.id)". Thus, it is impossible for a user to access the data of other users.

Thanks.

It’s a security thing. If someone hacked or cloned the mobile app, the (secure) backend ensures that they can only sync data that the logged in user is entitled to.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.