Allow only 2 users to read an object from a public class - ios

I'm building a private chat between 2 users. Currently I've got the "Chat" class open to everyone (read/write) and there is where all messages (objects) go.
I was thinking about adding objects with permission to read only between two users so only they can see what they chat.
I'm grabbing the messages using:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
PFQuery *fquery = [PFUser query]; // query to get the chat partener
[fquery whereKey:#"objectId" equalTo:[[NSUserDefaults standardUserDefaults] stringForKey:#"friendid"]];
PFUser *friend = (PFUser *)[fquery getFirstObject]; // got it!
PFQuery *query = [PFQuery queryWithClassName:#"Chat"]; // new query for grabbing messages
[query whereKey:PF_CHAT_ROOM equalTo:chatroom]; // #"Chat" = #"Chat"
if (message_last != nil) [query whereKey:PF_CHAT_CREATEDAT greaterThan:message_last.date];
[query includeKey:PF_CHAT_USER]; // current user
[query includeKey:[NSString stringWithFormat:#"%#", friend]]; // its friend/partener
[query orderByAscending:PF_CHAT_CREATEDAT]; // sort by date
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
// adding the messages to an array;
}];
For writing messages to parse:
PFObject *object = [PFObject objectWithClassName:#"Chat"]; // class name
object[PF_CHAT_ROOM] = chatroom;
object[PF_CHAT_USER] = [PFUser currentUser];
object[PF_CHAT_TEXT] = text;
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" equalTo:[[NSUserDefaults standardUserDefaults] stringForKey:#"friendid"]];
PFUser *friend = (PFUser *)[query getFirstObject]; // query to get the chat partener
PFACL *roleACL = [PFACL ACL];
[roleACL setReadAccess:YES forUser:[PFUser currentUser]];
[roleACL setReadAccess:YES forUser:friend]; // setting read permission for those guys
object.ACL = roleACL;
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
....
}];
Is this the right way to go?

I've implemented a similar app taking the same approach which seemed to work. But I think you've over complicated for what it needs to be.
You need a Chat class which you seem to have. This may be something similar to:
Chat
Object ID, Message, Author, Date, Date Seen, ACL, etc....
(there's many good schemas out there just google it)
Then when you create a new chat message to a friend you simply just create a new PFObject setting the other user's ACL permission to like you've done correctly.
The user can read his messages by calling
PFQuery *query = [PFQuery queryWithClassName:#"Chat"];
The response of the query will only be the chats that the user has read permission to, not everyones. Therefore there's no need to specify any further query parameters unless you're looking for unread messages, etc..

Related

How can I add all my users to a Role in Parse.com?

I'm having a class UserRatings for user to rate different places. Currently the class has a Public Read and Write ACL. I need to add all my users to a new role so that I can change the public read and write to my new role. How can I add all my users to this role? Also, how can I update the role when a new user is signed up?
I've used the following code to add all my existing users to the class.
PFQuery *query = [PFUser query];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
allUsers=objects;
NSLog(#"%#",allUsers);
}];
PFACL *roleACL = [PFACL ACL];
PFRole *role = [PFRole roleWithName:#"UserRatingsRole" acl:roleACL];
for (PFUser *user in allUsers) {
[role.users addObject:user];
}
[role saveInBackground];
I've not given any child roles. Is that an issue? When I check my Parse Roles, I can't find any users listed in my role. Can anyone help me?
You need to query for the Role object on the server, then continue as you already have.
Try this:
PFQuery *query = [PFUser query];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
allUsers=objects;
NSLog(#"%#",allUsers);
}];
PFQuery *queryRole = [PFRole query];
[queryRole whereKey:#"UserRatingsRole" equalTo:roleName];
[queryRole getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
PFRole *role = (PFRole *)object;
for (var i = 0; i < allUsers.length; i++) {
role.getUsers().add(allUsers[i]);
}
role.save();
}];
You can also check out the answer here: https://parse.com/questions/add-users-to-role

IOS Parse how do I retrieving objects from a query based on two classes?

I have two classes User and Post. The User class has a userType field and I want to retrieve all of the posts from a given userType lets call them group x. In the Post class I have a pointer to the User class.
I was trying to do something like, first retrieve all user Ids for the type of user I want:
PFQuery *queryUser = [PFQuery queryWithClassName:kFTUserClassKey];
[queryUser whereKey:kFTUserTypeKey equalTo:kFTUserTypeX];
[queryUser whereKey:kFTUserLocationKey nearGeoPoint:nearGeoPoint withinMiles:miles];
[queryUser findObjectsInBackgroundWithBlock:^(NSArray *usersTypeX, NSError *error) {
if (!error) {
NSMutableArray *objectIds = [[NSMutableArray alloc] init];
// Add ambassador ids into query
for (PFObject *userX in usersTypeX) {
[objectIds addObject:[PFObject objectWithoutDataWithClassName:kFTUserClassName objectId: userX.objectId]];
}
}
}];
And then I wanted to query based on these objectIds but I am not sure how to query on this array or if this is even the correct way to do this. How can this be done?
Parse provides a matchesQuery method on query, so ...
PFQuery *innerQuery = [PFQuery queryWithClassName:#"User"];
[innerQuery whereKey:#"userType" equalTo:#"X"]; // fix with your real user type
PFQuery *query = [PFQuery queryWithClassName:#"Post"];
[query whereKey:#"user" matchesQuery:innerQuery];
[query findObjectsInBackgroundWithBlock:^(NSArray *posts, NSError *error) {
// posts are posts where post.user.userType == X
}];

Parse.com Following / Follower Logic

Having some trouble trying to figure out some logic for the following situation.
I have built a friends system for my mobile app using parse. Simply put, when a user "follows" something they are put into a relationship. That relationship contains all of the people that the individual user has folowed.
User
Relationship - Friends (contains all of the users that that overall user has followed)
I can query who an individual user is following fairly easily:
PFQuery *query = [PFUser query];
[query whereKey:#"username" equalTo:#"asg"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
for (PFObject *object in objects) {
PFRelation *friendsRelation = [object objectForKey:#"Friends"];
PFQuery *query = [friendsRelation query];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"%#", objects);
} else {
}
}];
}
}];
How would I query who is following a certain user, though? So, a users followers.
If you already know the user, use whereKey:equalTo::
PFObject *user = ...;
PFQuery *query = [PFUser query];
[query whereKey:#"Friends" equalTo:user];
[query findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error) {
If you need to do a query to get the user then instead combine the requests with whereKey:matchesQuery::
[query whereKey:#"Friends" matchesQuery:userQuery];
I actually did a bunch of blog posts talking about implementing a friends list that might help you:
Overview
JavaScript part 1
JavaScript part 2
JavaScript part 3
The code samples are in JavaScript, but shouldn't be too hard to convert to iOS.
It covers the relationships, querying, updating etc.
The short answer to your question it to use a Join Table instead of a Relation so you can easily query from both sides of the relationship.
You can find a lot of information in the relations guide on the Parse site:
https://parse.com/docs/relations_guide#manytomany-jointables
I think what you are asking for is the PFUser *user = [PFUser currentUser] method. If you are trying to retrieve friends for the current user logged in. You could use the same for retrieving the users that the current user logged in has followed.

Query Custom User Class Parse

I'm trying to query three columns that I created in my user class with parse. I successfully saved them to the user class. But I'm having difficulty query these three columns onto a label. I really don't know where to start with the query, I want it to be user specific of course, so user A gets his name, bio, gender, ect. And name is the user's full name, not their username.
This is my code to save the objects:
- (IBAction)save:(id)sender {
PFUser *profile = [PFUser currentUser];
[profile setObject:_name.text forKey:#"Name"];
[profile setObject:_bio.text forKey:#"Bio"];
NSString *var = [[NSUserDefaults standardUserDefaults] objectForKey:#"MyKey"];
[profile setObject:var forKey:#"Gender"];
[profile saveInBackground];
}
For the query I really don't know, this is where I need help. So if you have any suggestions I would appreciate it. Thank you!
Try this one
PFQuery * query = [PFQuery queryWithClassName:#"ClassName"];
[query whereKey:#"Name" equalTo:#"XYZ"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// objects : PFObjects
// you can filter out the data you want and print into lable
}];

Parse.com - How to search/retrieve secured object for current uer

As per parse API documentation, "Security For Other Objects".
Create a private note that can only be accessed by the current user:
PFObject *privateNote = [PFObject objectWithClassName:#"Note"];
privateNote[#"content"] = #"This note is private!";
privateNote.ACL = [PFACL ACLWithUser:[PFUser currentUser]];
[privateNote saveInBackground];
Link: https://www.parse.com/docs/ios_guide#users-acls/iOS
This note will then only be accessible to the current user, although it will be accessible to any device where that user is signed in.
Question: How to retrieve all my private notes ? Unable to find out in documentation.
You have one add more column in your note class named "user" it creates user pointer in your table.
PFObject *privateNote = [PFObject objectWithClassName:#"Note"];
privateNote[#"content"] = #"This note is private!";
privateNote[#"user"] = [PFUser currentUser];
privateNote.ACL = [PFACL ACLWithUser:[PFUser currentUser]];
[privateNote saveInBackground];
And when you want to retrieve all notes which are related to that user then you can use following code
PFQuery *query = [PFQuery queryWithClassName:#"Note"];
[query whereKey:#"user" equalTo:[PFUser currentUser]];
NSArray *usersNote = [query findObjects];
NSLog(#"%#",usersNote);
in above Array u can get records.
Hope this will help to you.
Actually I've got another simple solution:
NO need to create extra column. You can simply use this:
PFObject *privateNote = [PFObject objectWithClassName:#"Note"];
privateNote[#"content"] = #"This note is private!";
privateNote.ACL = [PFACL ACLWithUser:[PFUser currentUser]];
[privateNote saveInBackground];
PFQuery *query = [PFQuery queryWithClassName:#"Note"];
NSArray *usersNote = [query findObjects];
NSLog(#"%#",usersNote);
It will automatically retrieve private note.

Resources