I have an iPad-only app where some users (the ones who buy in-app purchases) have PFUser objects that are linked to their currentInstallation like this:
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
if( [PFUser currentUser] != nil )
currentInstallation[#"user"] = [PFUser currentUser];
The identity behind the PFUser is the Facebook identity:
[PFFacebookUtils initializeFacebook];
[PFFacebookUtils logInWithPermissions:nil block:^(PFUser *user, NSError *error) {
if (!user) {
// Handle error path
failPath();
} else {
// Handle success path
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (error) {
failPath();
} else {
// Save the name on Parse
[PFUser currentUser][kParseUserKeyFacebookName] = user.name;
[PFUser currentUser][kParseUserKeyFacebookID] = user.objectID;
[[PFUser currentUser] saveInBackgroundWithBlock:....
Now I want to release a new app for the iPhone, which acts as a kind of "admin console" for the iPad app. The iPhone app will receive push notifications when things go wrong on the iPad app etc (the iPad is in use by many people).
Question: On the new iPhone app, presuming I can get the user to log in with the same facebook ID, how can I correlate back to the same user's ipad data on parse? For example can I get the ipad app's PFObjects and/or PFUser data in the iphone now?
Concrete example: set a password on the ipad app, log into facebook on the iphone app, enter that same password. How to check it against the ipad app password, from the iphone?
Related
I am using parse in an iOS app and there are two ways of signup, either using email/password or Facebook login.
The problem happen when a user sign up using his email/password then logout and try to sign up using his Facebook account which have the same email.
I am using [PFFacebookUtils logInInBackgroundWithReadPermissions:block: to signup with Facebook which creates a new user object in the Users table in Parse
Now I have two records for the same user and I can not update the record that has the Facebook information with the user email because Parse will not allow duplicate emails
So what should be the best solution to solve this problem?
UPDATE
I have used #kRiZ solution to login using plain Facebook code then either create new user or link the user with the Facebook data
- (void)loginWithFacebookWithSuccessCallback:(APISuccessCallback)successCallback
andFailureCallback:(APIFailureCallback)failureCallback {
// Login PFUser using Facebook
NSArray *permissionsArray = #[#"public_profile", #"email"];
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login logInWithReadPermissions: permissionsArray handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
failureCallback(error);
} else {
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:#"me?fields=id,first_name,last_name,email,gender" parameters:nil];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id fbResult, NSError *error) {
if (!error) {
NSString *email = result[#"email"];
User *existingUser = [self getUserByEmail:email];
if (existingUser == nil) {
[self signUpNewUserWithEmail:email];
} else {
// Need to set the current user to existingUser
}
[self linkCurrentWithAccessToken:result.token
successCallback(#{RESULT:RESULT_OK});
} else {
failureCallback(error);
}
}];
}
}];
}
Now the problem is to assign the [PFUser currentUser] to the existing user in case it is already exists
You can try linking the new Facebook user to an existing user on Parse using the [PFFacebookUtils linkUserInBackground:*... methods.
if (![PFFacebookUtils isLinkedWithUser:user]) {
[PFFacebookUtils linkUserInBackground:user withReadPermissions:nil block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Woohoo, user is linked with Facebook!");
}
}];
}
See Parse documentation on linking.
Login via Facebook (do not save user yet)
Query the user table for user having the same email as this new FB user
If found, link, else, save as new user.
UPDATE:
Linking method with FB access token:
[PFFacebookUtils linkUserInBackground:user
withAccessToken:accessToken
block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Woohoo, the user is linked with Facebook!");
}
}];
I'm using Parse SDK, login and signup are working perfectly : [PFUser currentUser] is returning the current user.
But after restarting app, [PFUser currentUser] is returning nil.
Why is the application not persisting the session ?
Login code (from parse.com) I'm using :
[PFUser logInWithUsernameInBackground:self.username.text password:self.password.text
block:^(PFUser *user, NSError *error) {
if (user) {
// Do stuff after successful login.
} else {
// The login failed. Check error to see why.
}
}];
EDIT 2: Create new project, it works. I don't know how and why, but it works.
EDIT: There is no logoutin the whole project
It looks like you are calling .logout somewhere, in which case the app will return nil for [PFUser currentUser].
The current user will persist from session to session if you do not automatically log out the user.
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
//save the installation
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
currentInstallation[#"installationUser"] = [[PFUser currentUser]objectId];
// here we add a column to the installation table and store the current user’s ID
// this way we can target specific users later
// while we’re at it, this is a good place to reset our app’s badge count
// you have to do this locally as well as on the parse server by updating
// the PFInstallation object
}
I updated the ParseSDK to 1.7.5 and also ParseFacebookUtilsV4 (1.7.5)
Then some our users can not save PFObject like this.
PFObject* post = [PFObject objectWithClassName:#"PostData"];
PFUser* user = [PFUser currentUser];
[post setObject:user forKey: #"user"];
...
[post saveInBackgroundWithBlock: ^(BOOL success, NSError *error){
if ( !success || error != nil ){
....
}
}];
It returns with error "user objects cannot allow writes from other users".
The user is using Facebook login and siged up in previous version's Parse SDK
(before Facebook SDK 4.0).
Even if the user deleted the app and re-installed, it's same error.
And it never happens the user signed up after ParseSDK 1.7.5.
To login with Facebook, I'm doing like this
[PFFacebookUtils logInInBackgroundWithReadPermissions: #[ #"public_profile", #"user_friends", #"email" ] block:^(PFUser *user, NSError *error){
}];
When I commented out adding user to PFObject, it succeeded.
Please give me some advice.
Thanks.
NOTE: For the quick fix, I stopped adding user on client, and use CloudCode
Parse.Cloud.beforeSave( "PostData", function(request, response) {
Parse.Cloud.useMasterKey();
var user = request.user;
var obj = request.object;
obj.set("user", user);
response.success();
});
it works...
I am using Parse for my backend on my iOS application, and I am trying to use a FBLoginView to allow users to login with Facebook.
I am also trying to link the user's Facebook account to their Parse account. When I attempt to link the user to their FB by using
if (![PFFacebookUtils isLinkedWithUser:user]) {
[PFFacebookUtils linkUser:user permissions:nil block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Woohoo, user logged in with Facebook!");
}
}];
}
I receive an error telling me that the Facebook session is invalid. I have determined that the above code seems to be closing the Facebook session (when I comment out the code, the session does not close) and giving me the error. Does anyone have any experience with this error?
Do your other apps use Parse for the backend?
The user state stored in PFFacebookUtils is different from the user returned from the FBLoginView.
If your code looks like this:
#pragma mark FBLoginViewDelegate {
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
// link current user
NSLog(#"User: %#", user);
if (![PFFacebookUtils isLinkedWithUser:user]) {
[PFFacebookUtils linkUser:user permissions:nil block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Woohoo, user logged in with Facebook!");
}
}];
}
}
Then you are currently linking a Facebook user object with a PFUser, which are incompatible. I would suggest using the data that the FBLoginView returns, and creating a parse user in the conventional way:
#pragma mark FBLoginViewDelegate {
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
// link current user
NSLog(#"User: %#", user);
NSString *username = user[#"email"];
NSString *password = user[#"id"];
[PFUser logInWithUsernameInBackground:username password:password block:^(PFUser *user, NSError *error) {
NSLog(#"User: %#", user);
if (error.code == 101) {
// sign up
PFUser *user = [PFUser user];
user.username = username;
user.password = password;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
}];
}
Now [PFUser currentUser] will return a parse user object, that was created based on your Facebook login. If the app is deleted/reinstalled, the next time the user enters the app, the FBLoginView will return a userid that will be used to log in to parse as an existing user.
Edit: A similar issue I've had is with using FBLogin, PFFacebookUtils, and any other recent facebook app logins if my phone has Facebook integrated into iOS settings. It seems to have something to do with the Apple integration of Facebook, and the new Facebook SDKs. It's annoying but I have to currently tell my users to delete their facebook information from the Settings, then they can login, using either PFFacebookUtils, or the process above. I hope this gets resolved soon.
for the first part of your question i'd found a way to login user into my app by just using Facebook with Parse. Actually once the users use this, you can check the data browser of your app and check the auth data filed and the profile filed with all the fb data that i did request within the app.
here is the code i use to login with fb, haven't linked a previous user with a fb account
- (IBAction)loginButtonTouchHandler:(id)sender {
// The permissions requested from the user
NSArray *permissionsArray = #[ #"user_about_me", #"user_relationships", #"user_birthday", #"user_location"];
// Login PFUser using Facebook
[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
//[_activityIndicator stopAnimating]; // Hide loading indicator
if (!user) {
if (!error) {
NSLog(#"Uh oh. The user cancelled the Facebook login.");
} else {
NSLog(#"Uh oh. An error occurred: %#", error);
}
} else if (user.isNew) {
NSLog(#"User with facebook signed up and logged in!");
//Go to your next view
} else {
NSLog(#"User with facebook logged in!");
//Go to your next view
}
}];
}
Hope this helps!
OK, I'm using Parse for an app.
I currently have a Facebook login but we will also be offering Twitter and Email/Password login.
I need to make sure that whichever way the user decides to login/sign up they can link everything together so they only have one account.
I know how to link the current user to a Facebook or Twitter account...
[PFFacebookUtils linkUser:[PFUser currentUser] permissions:nil block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Woohoo, user logged in with Facebook!");
}
}];
But there doesn't seem to be any information on linking the other way around.
i.e. if the user logs in with Facebook. Then how can I link that account with a email/password combo for log in?
Something like
[[PFUser currentUser] linkWithEmail:#"blah" password:#"blah" block:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Woohoo!");
}
}];