I want to create a ViewController where user can change there existing password. I m using Parse API - objective-c

PFUser *user = [PFUser currentUser];
// I can see the details of the users when this is called including password
if (user) {
if ([_login_txtpassword.text isEqualToString:user[#"UserPasswrod"]]) {
user[#"userPassword"] = _login_txtnewpassword.text;
[user saveInBackground];
NSLog(#"done");
}
}
this code is not working.... i have put blocks to test my code ... it doesnt pass the if statement
A little conflict in my concepts related parse (so consider me as a noob)
P.S i have read the documentation and search internet but couldnt find a solution.
Many Many thanks in advcance

The right way to do this is to try to log the user in with the old password, then set the new password if successful. (notice this code uses the parse User password attribute, not #"userPassword" as in the OP code, which won't work under any circumstances)...
NSString *username = [PFUser currentUser].username;
NSString *oldPassword = self.oldPasswordTextField.text;
NSString *newPassword = self.newPasswordTextField.text;
[PFUser logInWithUsernameInBackground:username password:oldPassword
block:^(PFUser *user, NSError *error) {
if (user) {
user.password = newPassword;
[user saveInBackground];
} else {
// update UI to tell user that the old password is incorrect
}
}];

Actually you can't override the password of the current user directly from your ViewController. The user should request a new password, that will by sent to his/her email by Parse.
PFUser *currentUser = [PFUser currentUser];
NSString *userEmail = [NSString stringWithFormat: #"%#", currentUser.email];
[PFUser requestPasswordResetForEmailInBackground:userEmail];
or
[PFUser requestPasswordResetForEmailInBackground:self.userEmailTextfield.text];

Related

Permissions for a new user / Parse-server-Heroku

I just created a new user on parse-server/Heroku. Using code like this:
PFUser *x = [[PFUser alloc] init];
x.username = #"XXX";
x.password = #"yyyy";
x.email = #"email123#abc.com";
[x signUpInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
if (succeeded) {
NSLog(#"kensu registration ALL OK!!!!");
} else if (error) {
NSLog(#"kensu registration error: %#",error);
}
}];
The user creation went fine. And I can log in witn this new user.
The problem comes after.
When I log in with the new user, I am not allowed to make any update on my mongoDB.
I get this kind of error message:
[Error]: Permission denied for action update on class ....
If I log with the unique user I had before, I can update without any problem. Why?
I looked at the user collection to see any difference, then tried a few things, but without success.
I hope someone can point me in the right direction.

Parse: Remove user when session ends?

I was wondering if it were possible to remove a user completely from the database if their session ends? Maybe in sign up, I can check if there is a session for the username the person is using and if there isn't, it deletes the previous user and registers a new one?
How do I check if there is a current session for a certain username?
UPDATE:
PFQuery *query = [PFQuery queryWithClassName:#"Friends"];
[query whereKey:#"username" equalTo:[[PFUser currentUser] objectForKey:#"username"]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
for (Friends *currentFriend in objects) {
[currentFriend deleteInBackground];
}
}];
You can either:
1. [Recommended] Use a anonymous user to begin with, Reference can be found here.
2. In AppDelegate.m - applicationWillTerminate: method, you can do
[user deleteInBackground];
[PFUser logOut];
This will delete your logged in user permanently, locally and from remotely.
To
check if a session has a certain username
, all you need to do is:
PFUser user = [PFUser currentUser];
if ([user.objectId isEqualToString:"myTargetUserId"]) {
NSLog("Target user exists");
}

Saving user causes object not found error

Saving a user causes Error: object not found for update (Code: 101, Version: 1.2.19)
[PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *geoPoint, NSError *error) {
if (!error) {
[PFUser currentUser].location = geoPoint;
[[PFUser currentUser] save];
}
}];
what am I doing wrong?
http post request https://api.parse.com/2/update
{
"iid": "[redacted]",
"classname": "_User",
"data": {
"email": "test#test.com",
"objectId": "[redacted]"
},
"session_token": "[redacted]",
"v": "i1.2.19",
"uuid": "[redacted]"
}
response
{
"code": 101,
"error": "object not found for update"
}
I have the same problem as you, I done some testing and figure out root cause:
Create new class GameScore as document
Do the same create and update object and find out it works well
Check the "ACL" columns and compare to your problem data. See?
Works ACL, I done modify for * to make it clear
Failed ACL.
As you could see the write privilege lock to user "6iIv5XWZvM", that's why your update will "not found object"
You could change data record directly to "*" to let your update works well.
OK! Here is solution as follow:
Change every record "ACL" data col as follow:
{"*":{"write":true,"read":true}}
You need login PFUSer as specific user to change ACL to public. For my case use objectId will be "6iIv5XWZvM". I need set password and login info and use code to login and modify it. Detail iOS code as follow:
//iOS Sample
[PFUser logInWithUsernameInBackground:#"USERNAME" password:#"PASSWORD" block:^(PFUser *user, NSError *error) {
if (user) {
PFQuery *query = [PFQuery queryWithClassName:CLASS_NAME];
[query findObjectsInBackgroundWithBlock:^(NSArray *objs, NSError *error) {
for (PFObject *obj in objs) {
PFACL *defaultACL = [PFACL ACL];
[defaultACL setPublicReadAccess:YES];
[defaultACL setPublicWriteAccess:YES];
[obj setACL:defaultACL];
[obj saveInBackground];
}
}];
} else {
// The login failed. Check error to see why.
}
}];
However remember to add following setting before you save new data, if you don't want to happen anymore (note: it will be security concern)
//It is iOS code sample.
PFACL *defaultACL = [PFACL ACL];
[defaultACL setPublicReadAccess:YES];
[defaultACL setPublicWriteAccess:YES];
[PFACL setDefaultACL:defaultACL withAccessForCurrentUser:YES];
Try this, i'm using this, when i need to save objects for the current user. Hope it will help.
PFUser *user = [PFUser currentUser];
[user setObject:geoPoint forKey:#"location"];
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error){
NSLog(#"Error %# %#", error, [error userInfo]);
}
}];
The error : "object not found for update" append when the you try to save an object that the user does not have ACL access.
In order to let the user change the object you need to set PFACL permission when you create the object :
For a specific user :
PFObject *object = /*the object you want to save*/
NSString *userID = /*the objectID of the user you want to let perform modifications later*/
PFACL *groupACL = [PFACL ACL];
[groupACL setWriteAccess:YES forUserId:userID];
object.ACL = groupACL;
For a all users :
PFObject *object = /*the object you want to save*/
NSString *userID = /*the objectID of the user you want to let perform modifications later*/
PFACL *groupACL = [PFACL ACL];
[groupACL setPublicWriteAccess:YES];
object.ACL = groupACL;

parse.com API - how to run a query inside parse classes files?

I will try to explain myself as best as I can.
My app has a login & sign Up using the Parse API .
after signing or logging the User see a page with a Button and a Text Field which he can write Numbers in it ,
let's say he write , for example: 1234.
the button job is to save the data from the text field
Now i'm sure my Button method isn't the best way, but it's work :-)
NSString *whoIsTheUser = [PFUser currentUser];
NSString *phoneNumbers = phoneNumberField.text ;
NSString *fullData = [NSString stringWithFormat:#" %# , %#", whoIsTheUser, phoneNumbers];
NSLog(#" %#, %# ", whoIsTheUser, phoneNumbers);
PFObject *addValues= [PFObject objectWithClassName:#"phoneNumber"];
[addValues setObject: fullData forKey:#"numbers"];
[addValues saveInBackground];
So now what i'm having is the data saved to parse site under class of Numbers (forKey:#"numbers")
and it's look like this :
<PFUser:hqExhaYaIN:(null)> {email = "buffo#yahoo.com";username = buffo;} , 1234
what I'm trying to do is to add another button which going to check if theres another user
who wrote the same numbers and then send an alert or do something .
I have tried to read about the PFQuery but didn't find any solution.
is it even possible to run Query in the classes name ? or maybe theres another way to do it ( within the parse site ) ?
thank you so much for any suggestion !
It looks like you need to split up fullData in your parse objects and do something like this
PFQuery* numQuery = [PFQuery queryWithClassName:#"phoneNumber"];
[numQuery whereKey:#"numbers" equalTo:phoneNumbers];
[numQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if(!error)
{
for(PFObject *numObject in objects)
{
//Do what you need to do here
}
}
else
{
//handle error
}
}
EDIT - this means you would save your PFObjects like this
PFObject *addValues= [PFObject objectWithClassName:#"phoneNumber"];
[addValues setObject: phoneNumbers forKey:#"numbers"];
[addValues setObject: whoIsTheUser forKey:#"theUser"];
[addValues saveInBackground];
i hope it's going to help someone like it's helps me , if you want to query for info without the user info use those lines
PFQuery* numQuery = [PFQuery queryWithClassName:#"phoneNumber"];
[numQuery whereKey:#"numbers" equalTo:phoneNumbers];
[numQuery whereKey:#"theUser" notEqualTo:[PFUser currentUser]];
[numQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
all I had to do is add notEqualTo and CurrentUser :-)

NSURLCredential and NSURLConnection

I have been trying to search for a way to unset the credentials once you set a NSURLCredential with a NSURLConnection that is using NSURLCredentialPersistenceForSession, but I couldn't find a working solution. Removing the NSURLCredential from the NSURLCredentialStorage only removes it from the storage and not from the NSURLConnection cache. I tried turning cache off and it still keeps it. I need it to be NSURLCredentialPersistenceForSession as I don't want it to be uploading the large data then getting back the you need to authenticate message then authenticating with NSURLConnection and then resending the large data, I just want to authenticate once and send the large data once. I have a way to authenticate before sending the large data by checking some properties, but that doesn't allow me to logout or re-ask for authentication. I'm writing a WebDav client just so you understand where I stand, and the reason I need to unset the credentials is if someone has multiple accounts on the WebDav server and wants to login to another account. I tried looking into the cookies to see if it set something there, but it doesn't. I know it's only for the session, which means once your quit and relaunch the application, you can login as the other user. But that may confuse some people. I thought about writing my own Authentication system, but I wouldn't know how long that'll take.
Sorry if the above message is too long, I am just making sure I explain everything in detail so someone can try to help me with a valid answer and not a, go here leading me to something I tried.
Thanks for any help,
Mr. Gecko.
Update: Example code.
CFHTTPMessageRef message = [self httpMessageFromResponse:response];
authentication = CFHTTPAuthenticationCreateFromResponse(kCFAllocatorDefault, message);
CFHTTPMessageRef message = [self httpMessageFromRequest:request];
CFStreamError error;
CFHTTPMessageApplyCredentials(message, authentication, (CFStringRef)[credentials user], (CFStringRef)[credentials password], &error);
NSLog(#"%d", error.error); // Returns -1000
CFStringRef value = CFHTTPMessageCopyHeaderFieldValue(message, CFSTR("Authorization"));
NSLog(#"%#", (NSString *)value); // Returns NULL
if (value!=NULL)
CFRelease(value);
Update: Code that I tried with removing credentials.
- (void)resetCredentials {
NSURLCredentialStorage *store = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *allCredentials = [store allCredentials];
NSArray *keys = [allCredentials allKeys];
for (int i=0; i<[keys count]; i++) {
NSURLProtectionSpace *protectionSpace = [keys objectAtIndex:i];
NSDictionary *userToCredentialMap = [store credentialsForProtectionSpace:protectionSpace];
NSArray *mapKeys = [userToCredentialMap allKeys];
for (int u=0; u<[mapKeys count]; u++) {
NSString *user = [mapKeys objectAtIndex:u];
NSURLCredential *credential = [userToCredentialMap objectForKey:user];
NSLog(#"%#", credential);
[store removeCredential:credential forProtectionSpace:protectionSpace];
}
}
}
I'm working with a webdav server and had a similar issue. I found a solution within the sample code for apple's AdvancedURLConnection's project. It appears that the secret is to iterate over the protection spaces and then the credentials for each space. It's probably needlessly over complex but it works for me.
NSURLCredentialStorage *store = [NSURLCredentialStorage sharedCredentialStorage];
assert(store != nil);
for (NSURLProtectionSpace *protectionSpace in [store allCredentials]) {
NSDictionary *userToCredentialMap = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:protectionSpace];
assert(userToCredentialMap != nil);
for (NSString *user in userToCredentialMap) {
NSURLCredential *credential = [userToCredentialMap objectForKey:user];
assert(credential != nil);
[store removeCredential:credential forProtectionSpace:protectionSpace];
}
}