Parse.com saving non logged in users - ios

I am building an iOS app with a following/follower relation using Parse.com. I am trying to do something where every time a user follows another user it puts the follower into to an array of Followers in Parse.com but i can not save a user who is not logged in. Is there anyway to get around this using the iOS SDK?

If you want to save a user that is not the current user, you will have to use cloud code and the master key. You can send up the id of the user you want to change, query for that user, and change any fields you want. Here is my cloud code function for editing users, where "myUser" is the id I sent up:
Parse.Cloud.define("editUser", function(request, response) {
//var GameScore = Parse.Object.extend("SchoolHappening");
// Create a new instance of that class.
//var gameScore = new GameScore();
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
query.get(request.params.myUser, {
success: function(myUser) {
// The object was retrieved successfully.
myUser.set("cabinetPosition", request.params.myPosition);
// Save the user.
myUser.save(null, {
success: function(myUser) {
// The user was saved successfully.
response.success("Successfully updated user.");
},
error: function(gameScore, error) {
// The save failed.
// error is a Parse.Error with an error code and description.
response.error("Could not save changes to user.");
}
});
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and description.
}
});
});
You can learn more about cloud code in the parse docs.

You can try to set an array property in your follower user (logged in) which represents the id of users he actually follows. Each time you follows another user, add his objectId in the array.
To get all your followers, use whereKey:containsAllObjectsInArray: method of PFQuery
PFQuery *followersQuery = [PFUser query];
[followersQuery whereKey:#"followsId" containsAllObjectsInArray:#[[PFUser currentUser].objectId]];
[followersQuery findObjectsInBackgroundWithBlock:^(NSArray *followersArray, NSError *error){
// Do stg
}];

Related

Google Consent SDK: How to Save 'Status' Array in UserDefaults?

The variable "status" is not used in this code. Therefore I cannot check the user's consent choice.
I have to store 'status array' in defaults. Once current status is available in array it will not show that Consent form. If not then we will show form and add that status in defaults status array.
Now I cannot check user's consent choice, and the form will load every time on app load.
This would probably solve the problem, but I do not know how to do that in code. Any suggestions?
// Load Form
[form loadWithCompletionHandler:^(NSError *_Nullable error) {
NSLog(#"Load complete. Error: %#", error);
if (error) {
// Handle error.
} else {
// Load successful.
[form presentFromViewController:self
dismissCompletion:^(NSError *_Nullable error, BOOL userPrefersAdFree) {
if (error) {
// Handle error.
} else if (userPrefersAdFree) {
// The user prefers to use a paid version of the app.
} else {
// Check the user's consent choice.
PACConsentStatus status =
PACConsentInformation.sharedInstance.consentStatus;
// store status array in defaults
// once current status is available in array we will not show that form
// if not then we will show form and add that status in defaults status array
//Storing publisher managed consent
PACConsentInformation.sharedInstance.consentStatus = PACConsentStatusPersonalized;
}
}];
I have little clue of iOS, but I'd guess you just have to write the assignment into a single line:
PACConsentStatus status = PACConsentInformation.sharedInstance.consentStatus;

iOS + Parse Cloud Code - updating a specific user (not logged in user)

I am trying to update a user (Which is not the current user). I figured that you have to use cloud code to make the update.
I have created the cloud function below to update the selected user. I am trying to add meetingId's to an array property which belongs to User class.
Cloud Code:
Parse.Cloud.define('updateUser', function(request, response) {
var userId = request.params.userId,
meetingId = request.params.meetingId;
var User = Parse.Object.extend('_User'),
user = new User({ objectId: userId });
user.addUnique("meetingsArray", meetingId)
user.save(null, {userMasterKey:true}).then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
Objective-C
//meetingId - is obtained from Meeting Object.
[PFCloud callFunctionInBackground:#"updateUser" withParameters:#{#"objectId":user.objectId, #"meetingsArray":meetingId} block:^(NSString *result, NSError *error)
{
if (!error) {
NSLog(#"%#",result);
}else if(error){
NSLog(#"%#", error);
}
}];
When I run the app - I get the following error code:
Error Domain=Parse Code=141 "The operation couldn’t be completed. (Parse error 141.)" UserInfo=0x1704f2780 {code=141, temporary=0, error={"code":201,"message":"missing user password"}, originalError=Error Domain=NSURLErrorDomain Code=-1011 "The operation couldn’t be completed. (NSURLErrorDomain error -1011.)"}
I'm new to Cloud code - i just basically want to update the array that belongs to the selected user and add a meetingId to it. Any help would be greatly appreciate it.
There are a few problems with the code that will prevent it from working:
the cloud code expects the meeting id parameter to be named #"meetingId", so change the parameters passed to #{#"objectId":user.objectId, #"meetingId":meetingId}
use Parse.User, not '_User' to extend user.
get - don't build - the user being updated
Summing up...
Parse.Cloud.define('updateUser', function(request, response) {
var userId = request.params.userId;
var meetingId = request.params.meetingId;
var query = new Parse.Query(Parse.User);
query.get(userId).then(function(user) {
user.addUnique("meetingsArray", meetingId);
return user.save(null, {useMasterKey:true});
}).then(function(user) {
response.success(user);
}, function(error) {
response.error(error);
});
});
I was still getting the error after implementing #danh's answer. I needed to add
Parse.Cloud.useMasterKey()
in the .js file then everything worked perfect!

How to enable user to add friends via friend's username and display user's friend list in tableview with swift

I'm currently developing iOS App with Swift that users can add friends via username in one view and display user's friend list in another tableview,I'm currently using parse and I'm able to get my app to let user sign up and log in.
I want to know the code of adding friends via username and display user's friend list with parse,
I've tried looking for this solution and I got nothing but how to get friend list from Facebook which is not related to my app .
Any help is appreciated and Let me know if you need any additional information! ( sorry for my bad english).
You need to use the FBSDK for iOS in order to make a graph request for the Facebook friends list.
I don't quite understand if you want to add a "friend" that already is registered in your app or that has a Facebook account, but in any case you'll need to store your users in a data store, i believe Parse has as PFObject which you can save like this:
var appUser = PFObject(className:"AppUser")
appUser["userFullName"] = "John Doe"
appUser["userFacebookID"] = 1
appUser["userEmail"] = "j.doe#doe.com"
appUser.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
From there what you need is to associate the users, with a "Friendship" object for example, like this:
var userFriendship = PFObject(className:"Friendship")
appUser["invitedUserEmail"] = "jane.doe#doe.com"
appUser["invitingUserEmail"] = "j.doe#doe.com"
appUser["invitationStatus"] = "pending"
appUser.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
After that you can update the objet in order to change the invitation status to "accepted" or "denied, "cancel" etc.
To get a the list of user invitations and friends you need to make a ParseQuery with the arguments you're looking for, such as:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"invitingUserEmail = 'j.doe#doe.com' AND invitationStatus = 'accepted'"];
PFQuery *query = [PFQuery queryWithClassName:#"Friendship" predicate:predicate];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d friends.", objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
You can find a lot more in the Parse Docs here https://parse.com/docs/ios/guide

parse.com / iOS - Is there a way to download the whole class object in json format?

I am testing parse.com and I am creating an app that needs to work offline.
I would like to download the whole class object in json format in order to save it locally and access the data.
I cannot find any documentation on how to do it using Swift/iOS.
I successfully get the object with a specific ID using:
var query = PFQuery(className:"TestObject")
query.getObjectInBackgroundWithId("DuZIpSgjnt") {
(TestObject: PFObject?, error: NSError?) -> Void in
if error == nil && TestObject != nil {
println(TestObject)
} else {
println(error)
}
}
but not the whole class.
What I would like to retrieve is the same json response that I get using REST Api from curl:
https://api.parse.com/1/classes/GameScore
that returns all my objects in json:
{"results":[{"cheatMode":false,"createdAt":"2015-05-15T15:55:17.782Z","objectId":"IKCmjRVet9","playerName":"Sean Plott","score":1337,"updatedAt":"2015-05-15T15:55:17.782Z"},{"cheatMode":false,"createdAt":"2015-05-15T16:05:51.688Z","objectId":"UOKOZkxaGl","playerName":"Marco xxx","score":9998,"updatedAt":"2015-05-15T16:05:51.688Z"}]}
any help appreciated.
Thank you!
If you want to store data persistently, I suggest that you first enable the local datastore, as described below:
Local datastore for Parse iOS
So the operation is basically a fetch then a pin. A fetch looks like:
PFQuery *query = [PFQuery queryWithClassName:#"YourCustomClassName"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *err) {
if (!err) {
// Do something with your objects, e.g. pin them for later access.
}
}];
Pinning just means parse is now storing the pinned data for you locally. you can fetch them later locally by marking you query as such:
[query fromLocalDatastore];

iOS Parse validating user

I want to write code in AppDelegate.m that checks if PFUser.currentUser credentials are still valid. The reason I am doing this is for this scenario. Assume user logged in successfully and now currentUser has the basic information of that user. If the user changes the password at some time, when application launch, it should check if those credentials are up to date or not. If email & password doesn't match the one in table, it should log the user out.
I tried to do this but apparently PFUser.currentUser.password is always set to null while PFUser.currentUser.email has the actual value of email used to log in. How can I achieve this validation without the password being accessible?
Here is the code I have for guidance:
PFQuery *query = [PFQuery queryWithClassName:#"User"];
[query whereKey:#"objectId" equalTo: PFUser.currentUser.objectId];
[query whereKey:#"password" equalTo: PFUser.currentUser.password];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!object) {
/*Credentials changed! Logout user and request login again*/
NSLog(#"Credentials Changed!");
[PFUser logOut];
[[[navigationController viewControllers] objectAtIndex:0] performSegueWithIdentifier:#"loginSegue" sender:self];
}
else {
/*Credentials are still valid..proceed!*/
NSLog(#"Credentials Correct!");
[[[navigationController viewControllers] objectAtIndex:0] performSegueWithIdentifier:#"skipLoginSegue" sender:self];
}
}];
When this failed I tried to NSLog the password and got null so I understood that this was the problem.
I would write a cloud code function using the master key: Parse.Cloud.useMasterKey();
When you include this in your function you will be able to access/check the user's password and send back a "verified" variable or something of that sort.
Here is my cloud code function to modify a user, but you can easily modify it to verify a user's info. There are also many answers on the parse forums on this as well as lots of info in the docs.
Parse.Cloud.define("editUser", function(request, response) {
//var GameScore = Parse.Object.extend("SchoolHappening");
// Create a new instance of that class.
//var gameScore = new GameScore();
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
query.get(request.params.myUser, {
success: function(myUser) {
// The object was retrieved successfully.
myUser.set("cabinetPosition", request.params.myPosition);
// Save the user.
myUser.save(null, {
success: function(myUser) {
// The user was saved successfully.
response.success("Successfully updated user.");
},
error: function(gameScore, error) {
// The save failed.
// error is a Parse.Error with an error code and description.
response.error("Could not save changes to user.");
}
});
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and description.
}
});
});
If you want to verify your current password, you can store your password locally, then use loginWithUsernameInBackground: to verify. Something like,
[PFUser logInWithUsernameInBackground:[PFUser currentUser].username
password:password
block:^(PFUser *user, NSError *error) {
}];

Resources