Realm Mobile Platform: public, private and shared databases? - ios

This question comes from the perspective of someone who's familiar with CloudKit and is moving to the Realm Mobile Platform.
With CloudKit we have the concept of private, public and shared databases. The private belongs to the user, the public can be seen by every user and the shared database is like a view into a user's private database used to share data between a limited number of users (friends).
Let's say I want to allow two users to collaborate on a project, user A will create the project and invite user B to collaborate, which mechanism would I use with realm to allow this, without completely opening up user A's private realm to user B (only the records specific to the project user A wants to share)?

Right now Realm permissions are granular to the database (Realm) level. There's no way to grant specific permissions that only apply to a subset of the data in a given Realm.
A high priority item on our roadmap are features to support working with partial copies of synced Realms. In the meantime, we'd recommend creating multiple private Realms for a given user to represent each subset of permissions. For example, you may have a truly private Realm for a given user, and one or more Realms for that user that represent data which can be shared with other users. In your specific case, you might want to create a Realm per project, rather than a Realm for all projects owned by a user.
As for actually granting permissions, you may create a RLMSyncPermissionValue object and pass it into the appropriate API on RLMSyncUser (e.g. -[RLMSyncUser applyPermission:callback:] or -[RLMSyncUser revokePermission:callback:]) to grant or revoke a permission. This requires knowing the identity of the user, which is generated by the Realm Object Server when the user is created.
You may also create a RLMSyncPermissionOffer object to represent an invitation by your user to another user to access their Realm (i.e. project). Such an object generates a string which can be passed to another user through a different channel (e.g. e-mail) and used to create a RLMSyncPermissionOfferResponse object to accept that offer.
Finally, in addition to the partial replication support I mentioned earlier we also have a few other items in the pipeline to make collaborative use of synced Realms easier; we hope to have more to share very soon.

Related

In firebase, how to create a user and add data in user object from ESP 8266?

I'm working with some IoT projects and for handling all data I have used Blynk application but now I have created my own app but problem is that I want to add sensor data to firebase, but I have multiple users that's why I want to separate my data for every user, how can i do this, which Library is helpful for this? I have searched on Google for this, but everyone adding data in common database but how to separate the data for multiple users?
To separate data per user in your database, you will want to organize the database reference path to a location relevant to the user uid. if your app supports Auth, you can access this with the currentUser object which should have their uid as a property.

Is there any way to transfer ownership of a CloudKit shared record?

I've just spent hours evaluating CloudKit's sharing features for a potential multi-tenancy app and, while I think I know the answer, I felt I should ask the community.
The use case: an app that supports multiple companies, each with its own users that can access shared data (records) within that company only. Imagine Slack's separate workspaces: a user of Company A should be able to see all of Company A's data, and maybe eventually Company A hires a new employee (user), who also should see that same data. Company B has completely separate users/data and is never seen by anyone from Company A.
The question: from my understanding so far of CloudKit, records are associated to a user, not a company/team/group. If User A (of Company A) shares a record with User B, that's totally doable and User B will see everything (including child records). But now let's suppose User A leaves the company. How does another user then take ownership of those records so that User B can continue to access the company's data?
It almost seems like each company would need to have its own iCloud account to serve as a master "owner", which feels unprofessional or challenging for non-techies to understand (and thereafter complicated for sharing with future users).
Am I thinking about this wrong? Am I already barking up the wrong tree by considering CloudKit as the backend for this app?
I think the most suitable setup for what you've described is to use a Public database in a CloudKit container. A CKRecord can be shared and "owned" however you want. The record remains available to all who can access the database.
Sharing a CKRecord via the CKShare functionality is much more limited. When sharing that way, you are simply providing a shared view into someone's Private database. If that user vanishes, the shared record goes with them and the sharing stops. Only the Public database can preserve a record independent of user status.
One caveat is that a Public database has to be owned by a single Apple Developer account. You can't share ownership across companies at the business level. But for the purposes of your app, your dev account can own the database and you can share the data with as many tenants as you want.
Let me know if you have any follow-up questions.

Change security roles of cloudkit records while updating application

I am new to ios development. I am planning to use public database of cloudkit to store user's data.
I want to set security roles such that only creator of the record can access it. No other user (even authenticated) can access (not read/write) the record. Suppose, I deploy the application and users are using it and creating records.
Now In future, while giving update to this application, if I want to change the security roles, and give authenticated users, the permission to read the records created by other users.
Is this possible? and If Yes then the records which are created earlier (before the updated version ) can now be accessed (read )by authenticated users?
Thanks in advance,
Krishna
Krishna, CloudKit doesn't work quite that way. The public zone is always public - everyone using your app can access these. If they are logged in it is possible to set it so anyone can write to the public database. The private database is where you store user specific records that only they can see. If you later want to share with other users you then use use the shared database.
This thread is on a similar topic
Designing for CloudKit is a helpful overview
This WWDC video goes into the specifics of sharing using Cloudkit

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.
Thanks for the detailed write-up. Your proposed architecture seems like a good fit. Here is what I would recommend:
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.
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.
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.

Simperium multiple users accessing data

In the Simperium documentation/help section there is the following text:
All the data that is created seems like it must be tied to a user - is
that correct? Is it possible to have data that isn't tied to a user -
say a database of locations or beers?
Yes, though this isn't very clear yet. You can create a public user
(i.e., a public namespace) with an access token you share with other
users of your app so anyone can read/write to that namespace.
It's possible to limit this to read-only access as well if you need to
authoritatively publish data from a backend service.
Is there an actual example with this?
The scenario I have is as follows
My app will have a calendar
The primary user can add and remove data from the calendar
They will want to invite other users to add and remove data, my thought is that they can give them a token, the user can use their email address and this token to sign in
Am I on the right track?
You're definitely on the right track, but a little too far ahead on that track. The scenario you described is a great fit for Simperium, but sharing and collaboration features aren't yet released.
The help text you quoted is for authoritatively pushing content, for example from a custom backend to all users of your app. An example of this would be a news stream that updates on all clients as new content is added.
This is quite different than sharing calendar data among a group of users who have different access permissions, which is actually a better use of Simperium's strengths. We have a solution for this that we've tested internally, but we're using what we've learned to build a better version of it that will be more scalable for production use.
There's no timeline for this yet, but you'll see it announced on your dashboard at simperium.com.

Resources