How to enforce immediate Coredata & CloudKit sync? - core-data

The setup:
My app uses either private data, i.e. data of a user identified by the iCloud login, or shared data, i.e. data of another user, shared via iCloud.
It uses thus 2 persistent stores, private and shared. Both are mirrored by Coredata & CloudKit synchronization.
When the user switches from private data to shared data and back, fetch requests and save requests are either directed to the private or the shared persistent store.
The use case:
Assume the user is using the private store. In this case, the shared iCloud database and thus the mirrored shared persistent store do not contain any data, since sharing is not activated.
He/she then receives an invitation of another user to share his/her data.
When the current user accepts the invitation, the shared data of the other user are mapped to the shared iCloud database of the current user, and eventually mirrored to the shared persistent store.
The problem:
Unfortunately, mirroring of the shared data does not start immediately. Sometimes, it starts after a few seconds, sometimes only after the app is restarted.
The question:
How can I enforce immediate Coredata & CloudKit mirroring?
Apparently a NSPersistentCloudKitContainer does not have a function to trigger a re-sync manually. One suggestion I found in this post is to re-initialize the NSPersistentCloudKitContainer, which triggers a re-sync.
Is this the right way to proceed?

Related

Sync for the first time the CloudKit data

My app backup the data to iCloud or sync with user device through the user iCloud account using NSPersistentCloudKitContainer privateDataBase.
The main problem is, when user install the app I need to know if user has data in iCloud or not according this information, I let user to setup account or fetch the existing account, since it takes too long to fetch with local CoreData, I am trying to find a way to fetch directly from iCloud through CloudKit, since I am new in CloudKit, I don't know how to fetch data from CloudKit any help appreciate.

Temporary User Accounts: MongoDB vs Redis

I'm developing an application with NodeJS, ExpressJS and MongoDB. Currently I'm working on the user registration process. I would like to store the user account temporary until the user has verified his email address, if the email address is not verified within a certain amount of time, I would like to remove the temporary account.
Currently I've following two ideas to solve the issue:
Creating a mongoose TempUserModel (besides the UserModel), i.e. if the user does the registration a temp user will be created, as soon as the user verified his email address, the temporary user account will be copied to the real Users collection. Some cronjobs could be setup to delete not verified user accounts after a certain amount of time (probably there are better solutions to let expire a mongodb record)
Setup redis to store the temporary user account data, as soon as the email address get verified, a new user will be created in mongodb. With this solution an expire date could be set to remove not verified accounts after a certain amount of time)
Is it better to store a temporary user account in Redis or in MongoDB?
I would recommend storing the temporary user accounts in MongoDB. Storing them in MongoDB has three advantages over Redis:
If you store a temporary user in MongoDB, it will be very easy to convert them to a real user once they have verified. In fact, you could even have the temporary users and verified users share the same schema, with a has_verified field in that schema being the only difference between the two kinds of users. Changing has_verified to true is a lot easier than saving data from Redis to Mongo.
If you are not already planning to create a Redis database for your project, you will only have to maintain MongoDB. Maintaining MongoDB requires less effort and fewer computation resources than maintaining both Redis and MongoDB.
If you ever make changes to your user schema in the future, it would be easier to only make those changes in once place, i.e. MongoDB, rather than to make those changes in two places.

How to only show documents to specific users in a shared database?

I'm managing a multiuser app using Ionic 3.x, PouchDB, CouchDB and a node.js server running Superlogin. The app is steadily growing and I want to introduce a new feature.
My app has normal users and superusers. Each normal and superuser in my application gets it's own user database. There is also a shared database, let's call it the generaldb.
And here's my problem: Both users can create documents. These documents are synced to the userdb as well as to the general db. These documents have, amongst other things, a keyword (e.g. "colour": "green"). Superusers have access to a specific key. (In the above example that would mean that there are for example 5 superusers who can access the key green.)
Now, no normal user should be able to read, update or write other user's documents on the generaldb. Superusers should be able to read, update or write documents in the generaldb depending on which key they have access to. But they should not be allowed to change documents that don't match their key.
How can I restrict access for normal users in the generaldb, so that only documents created by themselves are synced to their devices and so that they couldn't change other users documents?
How can I ensure, superusers can change normal users documents, as long as they have access to the correct key?
How can I ensure superusers cannot change their own key, so that when number 2 is accomplished, they cannot manually work around the system?
One of the ideas of mine is to only let the users access their own db and have the shared db only accessible by superusers and then do a filtered replication of the userdb to the shared db. But this only solves 1 and seems very inefficient.

Logging device id in database from data collection app

App A is communicating to database X through web service Y. Service Y enables insert, update and delete operations to data in database X. Many authorized people can use app A and connect to database X through service Y.
Developer Q wants to create a database trigger to log some information about the entries and updates on a table in database X including device id or IP. Can developer Q access some device identity through the established connection to database X through service Y?
If he/she can't, is there a workaround?
Short answer yes. The how is a bit more involved. You did not include what language the web service is written in so keeping it high level and focusing on the implementation agnostic way first.
Most languages used to code web services capture request information - device info, web client info, ip address (not reliable though), authentication identification (if not anonymous access), etc. So one typical way to track this data is create a session table in the database that you write all the pertinent request data to for web service session. Then derive a key for each session. Finally add a column for the session key to each table you execute DML on. Alternate approach is to have an operational table (what you already have) and a matching log table. the operational table doesn't have a session key column, but the logging table does. There are other ways to log activity, these are just some to demonstrate the point.
Another way, OO example, is to create a derived connection class that you add in web service session info to. This can then be accessed at the database command execution, usually done via a command object, and instead of writing triggers you programmatically do the logging.
In your particular case, the latter approach seems more appropriate than triggers since triggers could fire when someone does DML on the database directly, or another interface instead of the web service. In which case there would be no request info to begin with.

Azure Session Table stays empty in AspProvider's TableStorageSessionStateProvider

We have a Web Role which used to run in a single instance for some time. To cope with higher loads (and to get a better SLA) we're currently migrating the role to support multiple instances.
The role uses Forms Authentication (with a custom membership provider), and our understanding was that we would have to enable some sort of shared session state between the instances, so if a user signs in on instance 1 and gets his .ASPXAUTH cookie, then instance 2 knows about this cookie.
We did that, and currently the role is running on two instances, and everything works well. We tested that a user stays signed in, even if his request is processed on the other instance than the one on which he signed in. If the user doesn't sign in, access is denied.
We also checked whether the TableStorageSessionStateProvider created a table in the Azure Table Storage account, and indeed, there is a table Sessions with PartitionKey, RowKey and Timestamp columns.
But, to our astonishment, the Sessions table always stays empty. No matter how many users are signed in, there is no data in the table.
How can these instances communicate, if not through the Sessions table?
You're mixing up two different things here: Authentication and Session State.
It's true that, in order to use Session State with multiple instances, you need a shared store (InProc won't work). In that case TableStorageSessionStateProvider would work since all instances have access to the session data stored here. Session state is used when you store something in the current session of the user, like a shopping cart. And you would call it like this: Session["UserShoppingCart"] = shoppingCart;.
But what you're describing in your question has nothing to do with the Session State, it's all about Forms Authentication. When you authenticate on instance 1, you'll get a ticket in return (stored in the .ASPXAUTH cookie). This ticket is encrypted and signed and contains basic information like your username, expiration, custom user data, ...
Now that you have multiple instances it could be that the next request lands you on instance 2. And I think your question was, how do the instances communicate? Well, they don't. Whenever the request starts, before it reaches your page or your controller, the FormsAuthenticationHttpModule kicks in and looks for the .ASPXAUTH cookie. It checks the signature, decrypts it and then fills the HttpContext.Current.User with the information from the cookie (the ticket).
The only link between the instances is the machineKey (used for encypting/decrypting/signing/validating the cookie). Whenever you deploy multiple instances in Windows Azure, the Fabric Controller makes sure all instances get the same machineKey. This way, instance 2 will be able to decrypt and validate the ticket encryped and signed by instance 1.

Resources