Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Parse.com plugin v2
Started by Develephant Oct 24 2015 08:58 AM

- - - - -
70 replies to this topic
parse cloud coronium api develephant users database
[TOPIC CONTROLS]
Page 2 of 3 1 2 3
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#26

ubj3d.android

[GLOBAL: userInfoPane.html]
ubj3d.android
  • Contributor

  • 741 posts
  • Corona SDK

I am using mod_parse for a long time and it works great.
 
Today ported one of my games to Windows Phone and I am getting this error when calling the login method:
 
A request with this method cannot have a request body.
 
I am not an expert on http, searched the net a bit and found some information that GET should not have a body in the header?
 
How could I make it work on Windows Phone?
 
Would the Parse plugin for Corona help?


[TOPIC: post.html]
#27

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

I would need to see a pseudo-request to really understand why you would get that error. But, with that in mind, the Parse plugin is the most current and fully compliant version for the Parse REST API.

 

Cheers.



[TOPIC: post.html]
#28

ubj3d.android

[GLOBAL: userInfoPane.html]
ubj3d.android
  • Contributor

  • 741 posts
  • Corona SDK

Here it is:

 

 
requestParams: {
  [body] => "username=something&password=something"
  [headers] => {
                 [Content-Type] => "application/json"
                 [X-Parse-Application-Id] => "myApplicationId"
                 [X-Parse-REST-API-Key] => "myApiKey"
               }
 
  local q = { requestId = network.request( queryUri, Parse.GET, function(e) Parse:onResponse(e); end, requestParams ),
    requestType = requestType,
    _callback = _callback,
  }


[TOPIC: post.html]
#29

ubj3d.android

[GLOBAL: userInfoPane.html]
ubj3d.android
  • Contributor

  • 741 posts
  • Corona SDK

And here is the event table from function Parse:onResponse( event )

 

table: 05916180 {
  [name] => "networkRequest"
  [isError] => true
  [bytesTransferred] => 0
  [phase] => "ended"
  [bytesEstimated] => 0
  [requestId] => userdata: 00000008
}


[TOPIC: post.html]
#30

ubj3d.android

[GLOBAL: userInfoPane.html]
ubj3d.android
  • Contributor

  • 741 posts
  • Corona SDK

And here is some more output from the VS console:

 

'TaskHost.exe' (CoreCLR: Silverlight AppDomain): Loaded 'C:\windows\system32\en-US\mscorlib.debug.resources.dll'. Module was built without symbols.
A request with this method cannot have a request body.


[TOPIC: post.html]
#31

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

Are you using the new Parse plugin, or mod_parse? Because your code doesn't look familiar to either.

 

If using mod_parse, then it does not appear that you are using the mod_parse client calls, is that correct?

 

To login a user you use the following format:

 

local function onLoginUser( event )
  if not event.error then
    print( event.response.sessionToken )
  end
end
parse:loginUser( { ["username"] = "MyUser", ["password"] = "strongpw" }, onLoginUser )

 

All headers, body, and various common parameters are handled within the module itself. Perhaps I am unfamiliar with your development environment.

 

Also, mod_parse related issues should be addressed here: https://forums.coronalabs.com/topic/42191-a-parsecom-module-for-corona-sdk/

 

This thread is focused on the newer Parse plugin for Corona.  :)

 

Cheers.

 



[TOPIC: post.html]
#32

ubj3d.android

[GLOBAL: userInfoPane.html]
ubj3d.android
  • Contributor

  • 741 posts
  • Corona SDK

I am using mod_parse and using parse:loginUser.

 

The code if from you mod_parse module, wanted to show the exact parameters before the network.request is called.

 

As I said, I am using it since the first version, it works on all other operating systems (Windows, Mac, Android).

 

This error is from the device, Windows Phone.

 

Guess there must be then some kind of bug in the Corona network module for Windows Phone :(

 

Unfortunately, we can't use plugins on Windows Phone, but I suspect it would work on it since I guess the code behind the plugin is similar to mod_parse.



[TOPIC: post.html]
#33

ubj3d.android

[GLOBAL: userInfoPane.html]
ubj3d.android
  • Contributor

  • 741 posts
  • Corona SDK

Will not spam this thread anymore, just for the information (maybe someone will try to use Parse on Windows Phone).

 

Seems I was right, there is a bug in Coronas network call.

 

I tried this and got the same error as above (this time in "plain" lua):

 


local function networkListener( event )

  if ( event.isError ) then
    print_r( event )
  else
    print ( "RESPONSE: " .. event.response )
  end
end

local headers = {} 
headers["X-Parse-Application-Id"] = "my key here" 
headers["X-Parse-REST-API-Key"] = "my key2 here" 
headers["Content-Type"] = "application/json" 

local params = {} 
params.headers = headers 
network.request( "https://api.parse.com/1/config", "GET", networkListener, params )

 



[TOPIC: post.html]
#34

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

I don't get how you are supposed to maintain a session after a complete app restart so that the user does not have to login again. The module has no setter function" for SessionToken, no way of adding SessionToken in a User.me call and it does not persist the SessionToken e.g. in a sqlite db. This effectivly means that you always lose the current session at an app restart.

 

One alternative is to login each time the app is opened (requiring you to store the password on the device), but over time when thousands of users do it, it will quickly bloat the Session table at Parse since a new Session object is created at each login. Adding an applicationExit listener for logging out seems like an overly ugly workaround. Also, you cannot manually delete sessions at app start since they require that you have the SessionToken...

 

How have you guys solved this?



[TOPIC: post.html]
#35

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

Nobody? Surely, I can't be the only one having this issue?



[TOPIC: post.html]
#36

greatbigtree

[GLOBAL: userInfoPane.html]
greatbigtree
  • Observer

  • 2 posts
  • Corona SDK

Hi Divergent Monkey,

 

I'm having the exact same problem :( The old mod_parse had a method for setting the sessionToken to be re-used:

 

function Parse:setSessionToken( sessionToken )
  self.sessionToken = sessionToken
  return self.sessionToken
end
 
While I'd prefer to use the new plugin, I might have to use the old mod_parse if we can't figure this out!
 
Anyone know how to do it? Parse.com documentation suggests it should be possible? 
 
If you only have the session's token (from previous login or session create), you can validate and fetch the corresponding session by:
curl -X GET \ -H "X-Parse-Application-Id: EOq0NmDADrPux6piVPzB9aCzfiQ1tUw2NHLOkbM0" \ -H "X-Parse-REST-API-Key: zwQExRNSfy94YYprIDX8UQWKA4Zn96Oc4lmZ7Uvy" \ -H "X-Parse-Session-Token: r:pnktnjyb996sj4p156gjtp4im" \ https://api.parse.com/1/sessions/me
 
Here's hoping we find something!


[TOPIC: post.html]
#37

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

This will be addressed shortly, but it partly has to do with the REST API vs native integration. You can store the session token in a text file as an option. The Parse plugin is moving internally to Corona Labs for more parity with the native Parse SDK.

 

I have no knowledge of timelines, but it's something to consider if you're going to be using Parse heavily.

 

In other words, this version of the Parse plugin will not be the officially supported release eventually.

 

Cheers.



[TOPIC: post.html]
#38

greatbigtree

[GLOBAL: userInfoPane.html]
greatbigtree
  • Observer

  • 2 posts
  • Corona SDK

Hi develephant, 

 

Thanks for the quick response! I am already storing the session token in a text file, just am unsure how to use that stored session token to restore a player's session. Any help on that would be greatly appreciated!

 

Also thank you so much for this and mod_parse! Very much appreciated!



[TOPIC: post.html]
#39

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

@develephant: as greatbigtree suggests, the problem is not that we don't know how to persist the sessionToken between app restarts, but that there is no way to make use of it to restore the session later. I know that the version is just 0.x for this plugin, but since this is kind of a showstopper, would it be possible to just add a simple setter function for the time being so that I and everyone else who have put in many hours migrating from mod_parse to the plugin don't have to revert everything? This woud be really appreciated!



[TOPIC: post.html]
#40

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,
 
Parse would like you to think in terms of devices, more than users. A Parse Session is a device connection/login from a particular user. The reason for this is that a user could be logged in to your app from multiple devices. These are all considered Sessions to Parse, and you can expect to have multiple entries from the same user, but different devices.
 
When you provide Parse an "installationId" on each user login you will not have the issue of the Parse Session table filling up. How you derive this "installationId" is completely left to the developer. But Corona SDK does offer some methods to help with this.
 
You can include the installationId in two different ways.
 
--
 
In the config object:
 
If you put the installationId in the config object, you don't need to set it in the header each time.
 
parse.config:installationId("YOUR_DERIVED_INSTALLATION_ID")
 
--
 
In the header:
 
--during signup
parse.request( parse.User.create )
:data({ username="someone", email="me@email.com", password="nopeeking" })
:header("X-Parse-Installation-Id", "YOUR_DERIVED_INSTALLATION_ID")
:response(cb)
 
--during login
parse.request( parse.User.login )
:options({ username="someone", password="nopeeking" })
:header("X-Parse-Installation-Id", "YOUR_DERIVED_INSTALLATION_ID")
:response(cb)
 
 
The plugin makes no assumptions about how you store this data between app launches. Its up to the developer to provide that functionality.
 
Something important to note is that if you want to clear the Parse Session object, you must "logout" the user via the Parse api.
 
parse.request( parse.User.logout )
:response(cb)
 
In most cases though, you will want to keep the user "logged-in", so you can access the Session at a later time.
 
Getting a previous Session
 
If you use an installationId, as shown above, Parse will store a Session object for each device. When you login or sign up, you can pull the sessionToken from the results. If you want to retrieve this session -- in effect logging in -- then you can use:
 
parse.request( parse.Session.me )
:header("X-Parse-Session-Token", "STORED_SESSION_TOKEN")
:response(cb)
 
You can also set this in the Config object:
 
parse.config:sessionToken("STORED_SESSION_TOKEN")
 
Make sure to turn on the debug output to check the payload details:
 
parse.config:debugEnabled( true )
parse.config:debugVerbose( true )
 
Most of this is covered in the Parse REST Guide, but I'm not a huge fan on how they relay the information.
 
I've written this quite hastily, so feel free to add questions or point out errors.
 
Cheers.


[TOPIC: post.html]
#41

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

I've tried to set installationId in both the config object and the header, but none of it works. The installationId column in the Session table still remains "undefined" and new sessions are added at each login. As you can see in the debug output from a signup request, installation id gets sent, but it is still somehow ignored.

 

What am I doing wrong?

 

 

Jan 23 04:41:45.597 ********************************************************************
Jan 23 04:41:45.597 ** Parse RESPONSE @ 01-23 15:41:45 [2]
Jan 23 04:41:45.598 ********************************************************************
Jan 23 04:41:45.598 > createdAt: 2016-01-23T15:41:40.247Z
Jan 23 04:41:45.598 > objectId: sWfbjLpo5gE
Jan 23 04:41:45.606 > sessionToken: r:sDFfG5HlP73ASctthRT4aDSvg
Jan 23 04:41:45.607 ********************************************************************
Jan 23 04:41:45.607 ** RESPONSE META
Jan 23 04:41:45.607 bytesEstimated: 110
Jan 23 04:41:45.608 bytesTransferred: 110
Jan 23 04:41:45.608 isError: false
Jan 23 04:41:45.608 responseHeaders:
Jan 23 04:41:45.608    Access-Control-Allow-Methods: *
Jan 23 04:41:45.608    Access-Control-Allow-Origin: *
Jan 23 04:41:45.608    Connection: keep-alive
Jan 23 04:41:45.609    Content-Length: 110
Jan 23 04:41:45.609    Content-Type: application/json; charset=utf-8
Jan 23 04:41:45.609    Date: Sat, 23 Jan 2016 15:41:40 GMT
Jan 23 04:41:45.609    Location: https://api.parse.com/1/users/sWfbjLpo5gE
Jan 23 04:41:45.609    Server: nginx/1.6.0
Jan 23 04:41:45.609    X-Parse-Platform: G1
Jan 23 04:41:45.609    X-Runtime: 0.819689
Jan 23 04:41:45.609 responseType: text
Jan 23 04:41:45.609 status: 201
Jan 23 04:41:45.610 url: https://api.parse.com/1/users
Jan 23 04:41:45.610 ====================================================================
Jan 23 04:41:45.610 ** REQUEST DATA
Jan 23 04:41:45.610 body: {"username":"x","password":"x","email":"x@x.x"}
Jan 23 04:41:45.610 headers:
Jan 23 04:41:45.610    Accept: application/json
Jan 23 04:41:45.610    Content-Length: 114
Jan 23 04:41:45.610    Content-Type: application/json
Jan 23 04:41:45.610    X-Parse-Application-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxx
Jan 23 04:41:45.610    X-Parse-Installation-Id: 293jdfjc3jdne83ekdle3293kedmde34
Jan 23 04:41:45.610    X-Parse-REST-API-Key: xxxxxxxxxxxxxxxxxxxxxxxxxxx
Jan 23 04:41:45.610 ====================================================================



[TOPIC: post.html]
#42

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

And below you can see that inspite of storing the sessionToken from the signup and reusing it at a later login, I still get a brand new sessionToken, probably because installationId can't be set (see my previous post).

 

Any thoughts?

 

Jan 23 05:31:09.905 ********************************************************************
Jan 23 05:31:09.942 ** Parse RESPONSE @ 01-23 16:31:09 [3]
Jan 23 05:31:09.944 ********************************************************************
Jan 23 05:31:09.945 > createdAt: 2016-01-23T16:30:37.866Z
Jan 23 05:31:09.947 > email: x@x.com Jan 23 05:31:09.948 > emailVerified: true
Jan 23 05:31:09.948 > objectId: VBjUg45FdA
Jan 23 05:31:09.948 > sessionToken: r:DVNLpiuFR2345esWdfr4DwsQ2
Jan 23 05:31:09.948 > updatedAt: 2016-01-23T16:30:54.632Z
Jan 23 05:31:09.948 > username: x
Jan 23 05:31:09.949 ********************************************************************
Jan 23 05:31:09.949 ** RESPONSE META
Jan 23 05:31:09.949 bytesEstimated: 270
Jan 23 05:31:09.949 bytesTransferred: 270
Jan 23 05:31:09.949 isError: false
Jan 23 05:31:09.949 responseHeaders:
Jan 23 05:31:09.949    Access-Control-Allow-Methods: *
Jan 23 05:31:09.949    Access-Control-Allow-Origin: *
Jan 23 05:31:09.950    Connection: keep-alive
Jan 23 05:31:09.950    Content-Length: 270
Jan 23 05:31:09.950    Content-Type: application/json; charset=utf-8
Jan 23 05:31:09.950    Date: Sat, 23 Jan 2016 16:31:05 GMT
Jan 23 05:31:10.021    Server: nginx/1.6.0
Jan 23 05:31:10.021    X-Parse-Platform: G1
Jan 23 05:31:10.021    X-Runtime: 0.161582
Jan 23 05:31:10.021 responseType: text
Jan 23 05:31:10.022 status: 200
Jan 23 05:31:10.022 url: https://api.parse.com/1/login?username%3dx&password%3dx
Jan 23 05:31:10.022 ====================================================================
Jan 23 05:31:10.022 ** REQUEST DATA
Jan 23 05:31:10.022 body: []
Jan 23 05:31:10.022 headers:
Jan 23 05:31:10.022    Accept: application/json
Jan 23 05:31:10.022    Content-Length: 2
Jan 23 05:31:10.022    Content-Type: application/json
Jan 23 05:31:10.023    X-Parse-Application-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Jan 23 05:31:10.023    X-Parse-Installation-Id: 293jdfjc3jdne83ekdle3293kedmde34
Jan 23 05:31:10.023    X-Parse-REST-API-Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Jan 23 05:31:10.023    X-Parse-Session-Token: r:DGjYT37InbvE13DGTHBHYeF45
Jan 23 05:31:10.024 ====================================================================
 



[TOPIC: post.html]
#43

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

I would need to see some code to be able to assist further. If you can't or don't want to post it publicly, send it to chris at coronalabs and I'll take a look.

 

The process I documented was tested numerous times, so I'm interested in your code implementation.

 

Cheers.



[TOPIC: post.html]
#44

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

I have sent my code to your email address, thanks!



[TOPIC: post.html]
#45

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

So, after some research (bonking my head on the table) I found out that Parse is expecting a specific type of id. Of course this isn't mentioned in their docs :blink: . It was working for me due to fact that I was using a hard coded install id that I pulled from another source, which happened to match Parse's expectations.

 

Here is a function that will convert to the proper ID format from the device ID. I'm sure it could be fine tuned, but I'll leave that for the viewer (if anyone comes up with a more compact version, please share).

 

local device_id = system.getInfo('deviceID')
function generateInstallationId( input )
  local crypto = require( "crypto" )
  local hash = crypto.digest( crypto.md5, input )
  local function h( s, e )
    return string.sub(hash, s, e)
  end
  local id = h(1,8)..'-'..h(9,12)..'-'..h(13,16)..'-'..h(17,20)..'-'..h(21,nil)
  return id
end
local install_id = generateInstallationId( device_id )
parse.config:installationId( install_id )

 

 

Something to note from the Corona SDK docs is that Windows phone does not provide a device id:

 

 

On Windows Phone, this will return "Not Supported Yet".

 

If you use this result as a device id, you will generate the same installationId for all Windows phone users. So you'll need to figure out some other identifier you can use to generate the installation id as shown above.

 

Additionally, the sessionToken issue has been addressed as well.

 

Be sure to generate and set the installationId before making any other calls. Hope that does the trick.

 

Cheers.



[TOPIC: post.html]
#46

undecode

[GLOBAL: userInfoPane.html]
undecode
  • Contributor

  • 198 posts
  • Corona SDK

Just got a really bad announcement from Parse, they are shutting down the service in one year.

 

 

We have a difficult announcement to make. Beginning today we're winding down the Parse service, and Parse will be fully retired after a year-long period ending on January 28, 2017. We're proud that we've been able to help so many of you build great mobile apps, but we need to focus our resources elsewhere.

We understand that this won't be an easy transition, and we're working hard to make this process as easy as possible. We are committed to maintaining the backend service during the sunset period, and are providing several tools to help migrate applications to other services.

First, we're releasing a database migration tool that lets you migrate data from your Parse app to any MongoDB database. During this migration, the Parse API will continue to operate as usual based on your new database, so this can happen without downtime. Second, we're releasing the open source Parse Server, which lets you run most of the Parse API from your own Node.js server. Once you have your data in your own database, Parse Server lets you keep your application running without major changes in the client-side code. For more details, check out our migration guide here.

We know that many of you have come to rely on Parse, and we are striving to make this transition as straightforward as possible. We enjoyed working with each of you, and we have deep admiration for the things you've built. Thank you for using Parse.



[TOPIC: post.html]
#47

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

How ironic... Just as my first tests showed that everything was working fine with develephant's clarification above.

 

Well, I guess we just have to start looking for another backend to migrate to...



[TOPIC: post.html]
#48

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

By the way, thanks develephant! As I said in my previous post, your clarification above did the trick and it all seems to work.



[TOPIC: post.html]
#49

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 307 posts
  • Corona SDK

Here's another interesting behavior...

 

When deleting a User object, the corresponding Session (revocable) object is not deleted automatically for some strange reason. If you delete the session manually first, the user can't be deleted since you will get an "Invalid sessionToken" error (209). Same thing happens if you try to delete the user first and then the session. If you logout the user, the session is deleted but since User objects can only be modified (in this case deleted) while logged in, the user can't be deleted like this either. If you try to ignore the zombie session altogether, you will get a 209 error when trying to create another user from the same device.

 

Is this a "Parse" feature/bug or a "Parse plugin" dito?



[TOPIC: post.html]
#50

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,450 posts
  • Corona SDK

Hi,

 

I certainly won't miss Parse (just kidding), but that is an interesting situation.

 

The only documentation I have found in regards to removing Sessions is via logging out the User.

 

My assumption is this is something you would need to write Parse cloud code to handle (via a Hook). There is a "master-key" that can delete anything without a session involved, but that's not something you really want in your client code.

 

I'll take a look as well to see if anything is obvious.

 

Cheers.




[topic_controls]
Page 2 of 3 1 2 3
 
[/topic_controls]