iOS Parse validating user - ios

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) {
}];

Related

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

Check for unique phone number before allowed to sign up with parse ios

I've integrated my app with the parse framework and have added a few extra fields during the sign up process, one of those being phone number. I'd like to check to make sure the phone number entered is unique prior to them being allowed to sign up, like parse does for username and email. However, I can't find documentation anywhere on how to do so.
I've tried running a query on PFUser to check if the entered phone number is in the Users table but the query won't work (results are always nil) unless its included in the signUpInBackgroundWithBlock of code. However, putting the query here still uploads the info to parse no matter the results of the query. Has anyone found a way to do this? Thanks in advance!
Would be helpful if you share your query but something like the following should probably do the trick:
PFQuery *query = [PFQuery queryWithClassName:#"User"];
[query whereKey:#"phoneNo" equalTo:#"0123456"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
if (objects.count == 0) {
//Allow Number to be saved
} else {
//Give warning that the number is already in use
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
You can add a "beforeSave" trigger that validates the phone number uniqueness. The Parse.com documentation has some good examples.
Parse.com documentaion

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];

Parse.com saving non logged in users

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
}];

Getting Parse PFUser: relational data

I have a Parse class "Posts". "Posts" has a column, "user" which stores the user that made the post. It is of type Pointer<_User>.
I want to be able to retrieve the user, and then get an image stored in the User class.
So far I have:
PFQuery *postQuery = [PFQuery queryWithClassName:#"Post"];
[postQuery includeKey:#"user"];
PFObject *result = [postQuery getFirstObject];
if (result) {
NSLog(#"successful query"); //Successful!
} else {
NSLog(#"unsuccessful query");
}
PFUser *user = result[#"user"];
if (user) {
NSLog(#"successful found user");
} else {
NSLog(#"unsuccessful found user"); //Not successful
}
I successfully get "result", but I no "user". What am I missing?
In this case, the User object pointed to had been deleted. If a pointer column is included and it resolves to a non-existing object, it won't fail, but the object won't be fetched/included either. You can probably detect this scenario after query w/ includeKey by checking for the createdAt field.

Resources