Backendless Support
 
Waiting for user's response

Problem saving Parse data to Backendless DB

I've added functionality to my existing Parse user table so that on 'AfterSave', the corresponding record is either created or updated in Backendless. This is so I can support legacy users and keep things in sync until Parse shuts down. I'm using the REST API.

However, I've having a problem with two Parse field types: Password and String.

When attempting to update the Backendless password field with the contents of the Parse password field, an error is thrown.

Similarly, attempting to update the Backendless TEXT field with a Parse STRING that contains new lines, special characters, etc., an error is also thrown. Although it seems if the Parse field contains plain text (ie: 'abc123') it will save to Backendless just fine.

Any thoughts? The response is pretty generic (Request failed with response code 400).

Leave a Comment

Comments (17)

photo
1

Hello,

Is the error response the same for both scenarios (password and test update)?

Could you please show what your REST request looks like? (URL, headers, body).

Regards,

Mark

photo
1

Yes, the response is the same for both scenarios.

Note that the request succeeds as long as I don't attempt to update those 2 problematic ones from Parse. Using dummy data instead for password and bio (TEXT) value works.

  1. Parse.Cloud.httpRequest({
  2. method: 'POST',
  3. url: 'https://api.backendless.com/dev/users/register',
  4. headers: {
  5. 'secret-key': 'my secret key',
  6. 'application-id': 'my app ID',
  7. 'Content-Type': 'application/json',
  8. },
  9. body: {
  10. email: user.get('username'),
  11. password: user.get('password'),
  12. twitterID: user.get('twitterID'),
  13. name: user.get('name'),
  14. legacyID: user.get('objectId'),
  15. isProfileComplete: user.get('isProfileComplete'),
  16. instagramID: user.get('instagramID'),
  17. facebookID: user.get('facebookID'),
  18. editorsRanking: user.get('editorsRanking'),
  19. bio: user.get('attrBio'),
  20. age: user.get('attrAge')
  21. }
  22. }).then(function(httpResponse) {
  23. console.log(httpResponse.text);
  24. }, function(httpResponse) {
  25. console.error('Request failed with response code ' + httpResponse.status);
  26. });

photo
1

I assume you have a different request for when you update a user. This one creates a new user registration.

photo
1

Yes, there is a check that happens before. This code only runs when the user needs to be registered.

I haven't written the update code yet, since I need to get past this first.

photo
1

Sorry, I am confused. I understood you that the password update request is the one that fails. But it sounds like there is a problem with the user registration as well?

photo
1

Sorry, let me clarify:

- When I supply the Parse password value as part of the registration, it fails.

- When I supply a dummy password value (ie: 'test123') as part of the registration, it succeeds.

The goal is to create the account in Backendless so that the user can enter their original Parse password when they log in.

photo
1

Although, as I typed that I started to realize my potential problem. A new password is different since you need to encrypt it. However, I need to persist a password (or more accurately, the salted hash) which has already been encrypted.

photo
1

Do you have access to the original password (entered by the user)? Perhaps the BeforeSave handler would have that data?

Sending hashed/salted password value into our user registration API would not work for the reason that our servers would hash/salt it again and the user would not be able to login.

Regards,

Mark

photo
1

BeforeSave may get me access to it, however the problem will still persist for existing users. This seems to be a problem that must be handled by your existing migration process right? How would your migration engine know to simply store the Parse password value versus hash it again?

photo
1

The migration tool comes in at a lower level and stores the password value "as is". We added support for the same hashing algorithm as Parse's and thus user passwords from Parse work. However, the registration (and user update) APIs sit at much higher level and expect that the password value is in the raw form (which must be hashed/salted).

Why do you believe the BeforeSave approach would be problematic for the existing users?

Regards,

Mark

photo
1

I see.

Actually, I just found out that the user password is never exposed in plain text at any point from Parse - including in BeforeSave. So at the end of the day, there is no way for me to retrieve a user's password, particularly for users who have already created an account and set the password.

Any options for those like me who want to keep both databases in sync in real-time?

photo
1

For user registrations, you'd need to use Parse-export to Backendless-import. For all other changes in the data model, you can still use the current approach.

photo
1

Thanks - at least now I know the limitations.

As for the other field (bio, a Parse string), it can contain any number of special characters including newlines, asterisks, quotes, emojis, etc. Is there a known way to store this data in a Backendless TEXT field without issue? It seems that anything other than basic text causes a problem.

photo
1

It would be quite helpful to see an example of the request (URL, headers, body) which causes the error.

photo
1

I was able to get more info on the error:

  1. {"code":8002,"message":"Could not parse request with message: Invalid Json"}

...which leaves me to believe there is a problem escaping the contents of the Parse field.

It's difficult to get the actual request since this runs in Cloud code.

photo
1

It sounds like the body is malformed (invalid JSON)

Try using Backendless logging API to save the body of the message you're sending:

https://backendless.com/documentation/utilities/rest/ut_logging.htm

Info on logging management:

https://backendless.com/documentation/manage/mgmt_logging.htm

photo
1

Even the logger fails to work because of what is considered bad JSON.

I think at this point this will not work until I encode the contents of the field into something that the JSON parser will like. If I come across something that works or get any more insight, I'll update the thread.