Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring Permissions and Sharing Realms across Multiple Users

I'm using Realm Swift and the Realm Object Server as the storage solution for an app I am working on. I could use a traditional server with a relational database, but I really don't need the server to do any real work. The only backend that I really need is just storage and data syncing. Realm seems to provide exactly what I want.

So far, I have a working example of a realm. The problem that I have started running into is access control. I feel like I may have a fundamental misunderstanding of what Realm can provide me, and there are not a ton of fantastic resources out there. The Realm documentation is pretty detailed, but it doesn't have the best working examples.

My app will be used to track teams from an available set of players. The set of players will be relatively constant and unchanging. The teams, however, will change frequently. With this in mind, I had the following idea of my Realm setup:

  • A single Realm containing the set of all players: /Players. Every user should have read access to this realm but only admins should have write and manage.
  • A single Realm for each user of the application /~/MyRoster. This realm should be read/write by that user. I think that the user should be able to grant another user temporary read/write access to their realm as well.
  • Multiple users should be able to form a team wherein they can read (and potentially write) all team users' rosters.

Does this sound like an acceptable use of the Realm backend? How should I manage the central shared data pool? Should I just create a /~/MyRoster realm for a user as soon as they register? How could I configure the permissions the way that I want them? To me, the permission structure seems very strange. It seems like I can use the PermissionOffer/PremissionOfferResponse constructs to achieve the Realm sharing that I want.

Any help would be greatly appreciated.

like image 552
Nick Alexander Avatar asked Jun 22 '17 17:06

Nick Alexander


Video Answer


1 Answers

Thanks for the detailed write-up. Your proposed architecture seems like a good fit. Here is what I would recommend:

  1. For the global /Players Realm, I would create that within development. Today this is a bit clunky in that you have to use a client SDK to open the Realm as an admin user (because only admin users can create Realms outside of their scope /~/ directory). You could create a code path in your app that if you sign in as an admin, this opens the /Players Realm and then apply a permission change to that Realm:
let permission = SyncPermissionValue(realmPath: "/Players",
                                 userID: "*", // To apply to all users
                                 accessLevel: .read)
user.applyPermission(permission) { error in
  if let error = error {
    // handle error
    return
  }
  // permission was successfully applied
}

This code path doesn't need to be run more than once. Our plan is to add this kind of functionality into the browser in the dashboard so you can just manually create a global Realm and adjust permissions without using a client SDK.

  1. For the user-specific Realms, you do not need to create them immediately, because the Realms will get lazily created when the user eventually needs it. What I mean is that Realm is setup such that you can open a Realm on the client synchronously (enabling the offline-first capability), and then after the first creation when the client syncs to the server, will the server actually become aware and also create the Realm within it. Thus you client code just needs to be setup to open the Realm at /~/MyRoster when necessary.

    As for granting permissions to other users, this would use the Swift access control APIs to apply a permission change to the user's Realm and grant access to the other user. This can happen dynamically, such that the user can grant, then revoke the permission as needed.

  2. For the third part with regards to groups, I would create another global Realm, /Group, that has read/write access to all users which holds the representation of the groups. For example you could have a Group object which contains a list property linking to User objects, with 1 User per user within your application. This way every user could make changes to the Realm to represent the groups he/she is part of.

    You could setup a Realm Function to listen to changes to the /Group Realm such that when a user is added to a group or removed, the function would trigger the necessary permission change to the various Realms in the group.

    Now if your are concerned about access control to the /Group Realm, you could instead, setup a Realm Function that uses an admin user to apply changes to /Groups, listening to a user-specific Realm /~/MyRequests where a user could write an object to this Realm which would trigger the function to make a change to the group Realm. In this manner you could prevent unauthorized requests, and keep the /Group Realm as read-only for all users but admins.

like image 96
Adam Fish Avatar answered Nov 15 '22 11:11

Adam Fish