Remove self from shared record - cloudkit

What is the correct way for a user B to remove himself from a shared record owned by user A? I think I remember from some of the WWDC videos that user B would just delete the CKShare from his shared db, but it seems that the user will still remain a participant when looking at the permissions with user A's device. And, user B can "rejoin" by using the original link used to receive the record the first time.

Probably long forgotten, but I found this while looking for the same information (very few detailed articles about CKShares...).
Deleting the share seems to be the only way if you are not the share owner. User B remains, but his status changes to not determined.
Trying to remove the currentUserParticipant from the CKShare results in the following exception:
Terminating app due to uncaught exception 'CKException', reason: 'You cannot remove yourself as a participant on the share. Delete the share instead if you want out.'
Only the owner can add/remove participants to the share.

Related

Postgres - Locking insertion of non-existing row until transaction is committed

I have an application in which there are users, issuers, certificates and issues. users are the basic account, and issuers are the upgraded accounts who are able to distribute certificates to users. And distributing of certificates are called issues. The app uses postgres 14.4.
There is something called 'passive issue' in the application, which refers to issue of a certificate to a user that is not yet registered. Passive issue executes a transaction as follows:
check if user exists, if it does ignore it, if it does not, continue
create a passive issue which has awaiting register status
and then when that user actually registers, a trigger fires and updates the issue status.
The problem is that, after checking if user exists, and it does not, but right at that moment the user creates the account, and we try to passive issue, it will throw an error saying user already exists.
There are 2 possible approaches to solve this you might have thought so far:
just catch and check the error and redirect it to normal issuing path rather than passive issue within the api itself
return the error and let client retry the request by sending a request to normal issue path
The problem with above solutions:
It can not be done. Simply because this application uses blockchain, and normal issue endpoint requires the signature of the issuer. Passive issue is specifically implemented to be sent without a signature, and signature is generated on the client-side. And sending the private key to api is NOT even a possibility due to security concerns.
This is possible. This way the client will be noticed that this account registered, and it can prepare the signature and directly send a request to normal issue api. But it requires a longer and more complex implementation with retry logic etc.
And what I think would be the most neat solution in my case is such a scenario of passive issue:
check if user exists, and if it doesn't, lock the insert into the user table for that specific email ONLY
create passive issues for those accounts with await registration status (tx committed at this point and lock is released)
now even if the user tried to register in the middle, it will wait until issues are created and then user will be registered, and then trigger will fire, and since there are passive issues on this user now, it will update them.
So... Long story short: is there a way to put a lock on insertion of non-existing rows? And if there is, is it more feasible than the 2nd or any other possible solution?

How to send notifications to an offline member deleted from a chat group?

I am new to XMPP and working on a group chat application similar to watsapp. The scenario is:
"User A creates a group chat adding users B, C and D to it. All members are online and they are chatting. Now D takes the app to background or kills the app. Now A removes D from the group. How user D will be notified that A has removed him from the group, when D comes back to the app ?
I am using ejabberd (15.11) with PostgreSQL and following the XMPP architecture. I am not sure if the answer is out there, so would like to get help here.
XMPP MUC specifications says in section 9.5: Modifying the Member List:
If a removed member is currently in a members-only room, the service
SHOULD kick the occupant by changing the removed member's role to
"none" and send appropriate presence to the removed member as
previously described. The service MUST subsequently refuse entry to
the user.
It means that the participant will only receive his own status change modification if it is present it the room when the event happen. If he is not online at that time, he can only know his credentials has been removed, because he cannot join the room anymore. In other words, in the current state of the specifications, there is no way to get that removal notification when user was not in the room when the removal happened. You can just infer he was removed because he cannot join the room again on next login.
There is nothing else defined in XEP-0045 Multi-User Chat to store membership event for offline participant and later delivery.

Friend list through relations

I'm creating a social media app. I'm able to allow the current user to search for a PFUser and add the user to a friendship relation. I'm struggling on accessing the friendship relation and getting all the friends to create a table view right now. Could someone help me with this?
A Relation type in Parse represents just like what it literal meaning is. It's just a relation that contains no data. If you want to access the data inside the relation. You will need to perform query on it like so:
let query = relation.query() // I assume relation is an instance of PFRelation you want
Actually, Parse tutorial provides us a very comprehensive guide and you should check that first: https://parse.com/docs/ios/guide#relations
NOTE: This answer provides alternatives to using Relations to make a Friend System
I have created a friend system in two ways using Parse and both a function of your specific needs.
The first time I implemented a friend system. I had a table of Users and a table of Relationships. The Relationships table stored the usernames (or ObjectIds) of the two users in a relationship and the state of that relationship (friends, request sent, etc). The problem with this is that the queries can be kinda complicated, and if you have a lot of users, this may end up being too slow.
The second option is storing friend information in the User table itself. For each user, you add the columns with they type Array: Friends, RequestSent, and RequestReceived. Anytime a user sends a request they update their own user row and send a message to CloudCode to update the other affected user. Take a look at this example:
User A sends a request to User B:
User A adds user B's name to RequestSent
User A sends a message to cloud code that he/she wants to add user B
CloudCode adds User A's name to User B's RequestReceived
User B wants to accept User A's request
User B adds user A's name to Friends
User B removes user A's name from RequestSent
User B sends a message to CloudCode that he/she wants to accept User A's friend Request
CloudCode adds user A's name to Friends
CloudCode removes user A's name from RequestReceived
With this option, you never perform any server side queries. You only ever perform get operations. The downside to this option is if the logged-in user has thousands of friends/requests, it will take a while to download that information.
Note: The reason you have to use CloudCode is that a User can only change information about him/herself. The other option is to have CloudCode manage all the adding/removing so better checks can be made.
I found with this method that you can sometimes have one user who is listed a a friend in another users row but not their own. Controlling everything from CloudCode could eliminate this kind of error.

How can I delete a group of posts that my app created?

My app sent out a batch of posts tonight that were created erroneously. I would like to delete them, but I don't currently store the ids of posts that I create.
Is there a way to query for posts made after a certain time?
Once I have the ids I think I know how to delete them.
I'm using the Ruby gems facebooker2 and mogli.
You can retrieve the posts from feed or home connection of user.
For using those connections to read users post you will need read_stream permissions from user (which may be a bit problematic in your case if you not yet have this permission granted) and active access_token (this one will be needed to remove the posts too).
feed connection can be easily parsed to get posts from your application (since every post object have application property containing name and id)
home connection contain much more details to parse but you can filter results by application using filter (like /USER_ID/home/filter=app_2305272732).
Once you discovered the posts you may delete 'em by issuing DELETE request to Graph API:
DELETE https://graph.facebook.com/POST_ID?access_token=...
Or several posts for same user:
DELETE https://graph.facebook.com/?ids=POST_ID_1,POST_ID_2,POST_ID_N?access_token=...
Notes:
Since you said you didn't stored ids of post that published, more problematic may be discovering the list of users who got posted.

How to share data between iPhones?

This seems like a simple problem, but the more I plan it out, the harder it seems. The basic idea is this:
Person A wants to give person B permission to see his/her data on person B's device. Person A uses either person B's phone #, email, or Facebook info to send a request to person B. A has a unique ID for their device, but A does not know B's ID before the request. B might not have the app a well thus no account or ID exists.
What would be the best method for this handshake using phone #, email, or Facebook with a JSON, schemaless backend? I do have support for notifications, I'm just not sure how to properly and securely make the transfer so person A can have person B's ID to always send data to them in the future.
There are just so many factors, I'm having trouble wrapping my head around it.
It was pretty rough to be honest. I used Parse as my backend and hooked up my users using Facebook & email. I had an intermediate table for sharing. Each user had an array of user IDs that they were sharing with. I enabled push notifications so that when you shared with another person, they got a notification and an option to return sharing. Thus, each user had an array of people they wanted to share with. The sticky part was the handshake which I still don't like how I did. I basically check if each user has the other's user ID in their sharing array. In my opinion, its very sub optimal, but it works for now.