How to change PFUser password in Swift? - ios

I've tried updating the same way you would update a PFUser's email and even tried converting obj-c code (from other questions); neither worked. I also have no idea how to use Cloud Code (well...I installed it but I don't know how to pass information into Cloud Code or how to use JavaScript). Is there a way to update a users password without having to send the reset email?

You can not change a user's password that way for security reasons. You have two choices
Password Reset Email
Cloud Code Function to Reset the Password
As I understand that you do not know JavaScript, here is a cloud code function that you can use to reset the user's password, as well as a way to call the function using Swift.
Function (in JavaScript):
Parse.Cloud.define("changeUserPassword", function(request, response) {
// Set up to modify user data
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
query.equalTo("username", request.params.username); // find all the women
query.first({
success: function(myUser) {
// Successfully retrieved the object.
myUser.set("password", request.params.newPassword);
myUser.save(null, {
success: function(myUser) {
// The user was saved successfully.
response.success("Successfully updated user.");
},
error: function(myUser, 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(error) {
alert("Error: " + error.code + " " + error.message);
}
});
});
Swift code to call the above function:
PFCloud.callFunctionInBackground("changeUserPassword", withParameters: ["username" : "MyCoolUsername", "newPassword" : passwordField.text]) {
(result: AnyObject?, error: NSError?) -> Void in
if (error == nil) {
// result is "Successfully updated user."
}
}
Good luck!

Yes, password can be changed without Cloud Code and e-mail. After changing "password" field for current user session is reset, but you can restore it by calling PFUser.logInWithUsername again.
let currentUser = PFUser.current()
currentUser!.password = "<new_password>"
currentUser!.saveInBackground() { (successed, error) in
if successed {
PFUser.logInWithUsername(inBackground: currentUser!.email!, password: currentUser!.password!) { (user, error) in
// Your code here...
}
}
}

Related

Firebase Realtime Database doesn't save data from sign up page

I am working on sign up page of application in Swift. The part of authentication in Firebase works well, but the database doesn't save any information I request. Can anyone help?
My code:
Auth.auth().createUser(withEmail: userEmail,password: userPassword, completion: {(User, error) in
if error != nil {
print(error as Any)
return
}
guard let uid = User?.user.uid else {return}
let ref = Database.database().reference(fromURL:"Database-URL")
let userReference = ref.child("users").child(uid)
let values = ["Firstname": userFirstName,"email": userEmail]
userReference.updateChildValues(values, withCompletionBlock: { (error, reference) in
if error != nil {
print(error as Any)
return
}
})
})
The console prints an error
Optional(Error Domain=com.firebase Code=1 "Permission denied"
UserInfo={NSLocalizedDescription=Permission denied})
By default the database in a project in the new Firebase Console is only readable/writeable by authenticated users:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
See the quickstart for the Firebase Database security rules.
Since you're not signing the user in from your code, the database denies you access to the data. To solve that you will either need to allow unauthenticated access to your database, or sign in the user before accessing the database.
Allow unauthenticated access to your database
The simplest workaround for the moment (until the tutorial gets updated) is to go into the Database panel in the console for you project, select the Rules tab and replace the contents with these rules:
{
"rules": {
".read": true,
".write": true
}
}
This makes your new database readable and writeable by everyone. Be certain to secure your database again before you go into production, otherwise somebody is likely to start abusing it.
I may not be sure but the completion for createUser doesnot give you User and error rather AuthResult and Error. So you have to get the user from result as below
Auth.auth().createUser(withEmail: email, password: password) { (authData, error) in
if let error = error {
debugPrint("FIREBASE ERROR : \(error.localizedDescription)")
} else {
if let authData = authData {
let user = authData.user //here get the user from result
self.saveToDB(user: user) . //save the user to database
}
}
}
This is the new code for firebase from may 2019. just change false to true like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}

How do I run a Cloud Code on Heroku?

With the Parse's announcement of their retirement, I have migrated my Parse Server onto Heroku. With my still neophyte knowledge of Heroku, I do not know if they have a similar function to that of Cloud Code, but I do know that a few months ago Parse Introduced a Heroku + Parse feature that allows you to run Cloud Code on any node.js environment, particularly Heroku.
My dilemma is, I have already migrated my server from parse to Heroku prior to learning about this feature :/ , so I cannot run any parse cloud code form my terminal because there is no existing server there anymore. So the question is, how can I emulate this following Cloud Code in Heroku & How do I adjust my swift?
Cloud Code:
// Use Parse.Cloud.define to define as many cloud functions as you want.
// For example:
Parse.Cloud.define("isLoginRedundant", function(request, response) {
Parse.Cloud.useMasterKey();
var sessionQuery = new Parse.Query(Parse.Session);
sessionQuery.equalTo("user", request.user);
sessionQuery.find().then(function(sessions) {
response.success( { isRedundant: sessions.length>1 } );
}, function(error) {
response.error(error);
});
});
and here is my swift back in xcode:
PFUser.logInWithUsernameInBackground(userName!, password: passWord!) {
(user, error) -> Void in
if (user != nil) {
// don't do the segue until we know it's unique login
// pass no params to the cloud in swift (not sure if [] is the way to say that)
PFCloud.callFunctionInBackground("isLoginRedundant", withParameters: [:]) {
(response: AnyObject?, error: NSError?) -> Void in
let dictionary = response as! [String:Bool]
var isRedundant : Bool
isRedundant = dictionary["isRedundant"]!
if (isRedundant) {
// I think you can adequately undo everything about the login by logging out
PFUser.logOutInBackgroundWithBlock() { (error: NSError?) -> Void in
// update the UI to say, login rejected because you're logged in elsewhere
// maybe do a segue here?
let redundantSession: String = "you are already logged in on another device"
self.failedMessage(redundantSession)
self.activityIND.stopAnimating()
self.loginSecond.userInteractionEnabled = true
}
} else {
// good login and non-redundant, do the segue
self.performSegueWithIdentifier("loginSuccess", sender: self)
}
}
} else {
// login failed for typical reasons, update the UI
dispatch_async(dispatch_get_main_queue()) {
self.activityIND.stopAnimating()
self.loginSecond.userInteractionEnabled = true
if let message = error?.userInfo["error"] as? String
where message == "invalid login parameters" {
let localizedMessage = NSLocalizedString(message, comment: "Something isn't right, check the username and password fields and try again")
print(localizedMessage)
self.failedMessage(localizedMessage)
}else if let secondMessage = error?.userInfo["error"] as? String
where secondMessage == "The Internet connection appears to be offline." {
self.failedMessage(secondMessage)
}
}
}
}
I would first checkout the example repo and read the parse-server documentation. Parse server supports cloud code out of the box and you simply specify which file contains your functions and triggers in the parse-server config. The link you posted with the integration between parse and heroku is not relevant for parse-server.

How to handle sessions with QuickBlox in iOS

I am using Quickblox example writing in Swift for chat app. It uses QMServices.
Questions:
1) is there any approach for user login in iOS application with some session_token generated in any cloud backend ?
2) please help - how to renew user sessions in right way, I always get 422 error (validation error) multiple times (
In app using QuickBlox for iOS I try to login user in appdelegate:
if Storage.sharedInstance.currentUser != nil {
if !ServicesManager.instance().isAuthorized() {
let user =Storage.sharedInstance.currentUser
ServicesManager.instance().loginOrSignUp(user) {
[unowned self] success, error in
if (success) {
self.openMainScreen()
}
}
} else {
openMainScreen()
}
}
And loginOrSignUp function is:
func loginOrSignUp(user: QBUUser!, completion: ((success:Bool, errorMessage: String!) -> Void)!) {
self.logInWithUser(user) { (success:Bool, errorMessage: String!) -> Void in
if (success) {
Storage.sharedInstance.currentUser = self.currentUser()
completion(success: success, errorMessage: errorMessage)
} else {
self.authService.signUpAndLoginWithUser(user, completion: { (response: QBResponse!, user: QBUUser!) -> Void in
if user != nil {
Storage.sharedInstance.currentUser = self.currentUser()
completion(success: true, errorMessage: errorMessage)
} else {
completion(success: false, errorMessage: response.error?.error?.localizedDescription)
}
})
}
}
}
For example using Parse cloud code I can call function from cloud code:
Parse.Cloud.define("signUp", function(req, res) {
var phoneNumber = req.params.phoneNumber;
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
query.equalTo('username', phoneNumber);
query.find({
success: function(results) {
if (results.length > 0) {
Parse.User.logIn(phoneNumber, secretWord).then(function (user) {
res.success(user.getSessionToken());
}, function (err) {
res.error(err);
});
} else {
var user = new Parse.User();
user.set("username",phoneNumber);
user.set("password",secretWord);
user.setACL({"*": { "read": true }});
user.signUp(null, {
success: function(user) {
res.success(user.getSessionToken());
// Hooray! Let them use the app now.
},
error: function(user, error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
},
error: function(error) {
res.error(err);
}
});
});
So using Parse I can just login to app with session_token generated with cloud code.
First question: can I do the same with QuickBlox - use for login some session_token generated in any cloud backend?
And the second question: when user logged in, session is expired in 2 hours and we have to renew session ?
When user has bad connection, before he receive useful information he has to renew session every 2 hours. Even Ukrainian API for Ukrainian usage (not for for best service in the world) use token generated with login function for any other requests. User should not renew session always - he get only useful information.
But if there is no approach in Quickblox without session renewing, then how to do this renew in right way ? I am very new to iOS development, but when I used Parse, I didi not get this problems (

how to correctly make cloud code request with parse?

I am attempting to make all my user sessions with Parse exclusive, meaning if a user is already logged in on a certain device in a certain location, if another device logs in with the same credentials, I want the previous session(s) to be terminated, with a message of an alert view of course. Sort of like the old AOL Instant Messaging format. I figured the code for this action should be written in the login logic, so I wrote this within my login "succession" code :
PFUser.logInWithUsernameInBackground(userName, password: passWord) {
(user, error: NSError?) -> Void in
if user != nil || error == nil {
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("loginSuccess", sender: self)
PFCloud.callFunctionInBackground("currentUser", withParameters: ["PFUser":"currentUser"])
//..... Get other currentUser session tokens and destroy them
}
} else {
Thats probably not the correct cloud code call, but you get the point. When the user logs in once again on another device, I want to grab the other sessions and terminate them. Does anyone know the correct way to go about making this request in swift?
I speak swift with a stutter, but I think I can answer adequately in almost-swift. The key idea is to start the success segue only after the cloud says it's okay. Here's what I think you want:
PFUser.logInWithUsernameInBackground(userName, password: passWord) {
(user, error: NSError?) -> Void in
if (user != nil) {
// don't do the segue until we know it's unique login
// pass no params to the cloud in swift (not sure if [] is the way to say that)
PFCloud.callFunctionInBackground("isLoginRedundant", withParameters: []) {
(response: AnyObject?, error: NSError?) -> Void in
let dictionary = response as! [String:Bool]
var isRedundant : Bool
isRedundant = dictionary["isRedundant"]!
if (isRedundant) {
// I think you can adequately undo everything about the login by logging out
PFUser.logOutInBackgroundWithBlock() { (error: NSError?) -> Void in
// update the UI to say, login rejected because you're logged in elsewhere
// maybe do a segue here?
}
} else {
// good login and non-redundant, do the segue
self.performSegueWithIdentifier("loginSuccess", sender: self)
}
}
} else {
// login failed for typical reasons, update the UI
}
}
Please don't take me too seriously on swift syntax. The idea is to nest the segue in the completion handlers to know that you need to do it before starting it. Also, please note that the explicit placement on the main_queue within the completion handler is unnecessary. The SDK runs those blocks on the main.
A simple check to determine if a user's session is redundant (not unique) looks like this...
Parse.Cloud.define("isLoginRedundant", function(request, response) {
var sessionQuery = new Parse.Query(Parse.Session);
sessionQuery.equalTo("user", request.user);
sessionQuery.find().then(function(sessions) {
response.success( { isRedundant: sessions.length>1 } );
}, function(error) {
response.error(error);
});
});

How to reset a password using parse api?

I am using parse api as a service provider and data center so all my user information is stored in parse server and now i want to add a feature to my ios app for reseting a password but don't know how can i reset a password using parse api.
Can anyone help to know how can i use parse api to reset password of a user ?
PFUser.requestPasswordResetForEmailInBackground(emailTextField.text, block: { (succeeded: Bool, error: NSError?) -> Void in
if error == nil {
if succeeded { // SUCCESSFULLY SENT TO EMAIL
println("Reset email sent to your inbox");
}
else { // SOME PROBLEM OCCURED
}
}
else { //ERROR OCCURED, DISPLAY ERROR MESSAGE
println(error!.description);
}
});

Resources