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.
Related
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.
Recently something is changed the way Graph is handling permissions on drive items for external(outside tenant users).
Previously when we give access Write access to an external a unique link was created per user that we can do a patch call to update the roles if we want.
Now only two links are created one which is common for all externals having write role and one for read role.
I could not find a way if I want to update the role of an external from write to read or vice versa without removing all external users with write and adding them again.
Is there a work around to update permissions for external. The documentation is also pretty old its not updated since 2017.
Note: This is the Endpoint we are using/recommended to update permissions.
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.
I would like to sync a core data app with a user with a different iCloud ID and I am trying to figure out the most graceful way to do this. I do not want the data to sync with all users, but want to be able to sync among family members for instance. From the research I have done, I do not think I can do that using iCloud Core Data sync because it only syncs between devices with the same iCloud ID. I have looked at this stackoverflow answer and read a little bit about Ensembles, Parcelkit and TICoreDataSync, Parse etc., but it is not clear to me if any of those options will allow me to sync with multiple users. Does anyone have a good method for syncing a Core Data app with multiple users?
Ensembles and TiCoreDataSync might work. They can use Dropbox file syncing, so in principle they should work with Dropbox shared folders. I don't think these are the main intended uses, so I suggest contacting the developers and/or doing some good testing yourself before assuming this would actually work.
You'll need to think about the user experience, though. At a minimum, your users would both need Dropbox accounts and would have to set up a shared folder before beginning to sync data this way.
Parcelkit probably won't work. It uses Dropbox's data store API which, unlike other Dropbox services, doesn't appear to support shared data.
Services that do support this kind of sharing exist-- for example, Parse and Firebase-- but make sure to review their pricing carefully before using them. Also of course, there have been any number of projects that have their own custom server back end, but that obviously requires having someone on the team who can do that kind of work.
You need to think about other device types (Android at least) if you want your application to be reaching more users.
I'm doing the same now by the following way:
Setup an online database with proper web services (careful with implementation for security matters - DB should NEVER be exposed by anything other than the web services).
Create a Class for your communication with the server (using Class methods with security handling like authentication and authorisation).
Use the class in your app to communicate with the server (SQL operations are done on the server).
To integrate with CoreData you need to create the model in your app similar to the structure in the backend database. Then you need to create a similar class for the app that deals with only local CoreData.
A higher level class might be required if you want to make sure that operations done on both server and local data storage.
Besides, you have to implement a lot of conditions to make sure that data written in local ONLY after making sure that it is stored online (or create an engine for differed operations to run later).
Another Way if you are familiar with notifications:
Use structured notifications between devices for data operations in order to keep everything in sync with other users. The problem with this is the "Autonomy" of the operations. If two operations were done in approximately the same time, you have to find a way to make sure the order of the operations is done properly (maybe timestamp or something).
I'm looking into the same thing for my app and I 'think' you can do a fairly unsecured version of what you are after using using the public folder in cloud kit as mentioned in this question (no accepted answer at time of posting) : Private data sharing using CloudKit
You would need to find a way to differentiate between data that is truly public and those shared among the users you need and some level of authentication.
I'm going to try exporting a permission file with access permission in it to whomever I want to share with combined with a unique identifier located in that permission file.
Keep in mind, as mentioned in the comments of the linked answer, my implementation will be security by obscurity (thanks for that phrase) unless you find a way of adding proper validation to it but my data is relatively insensitive.
Hope this, or any ridicule in the comments, points you in the right direction : )
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.