purescript / trypurescript

PureScript in the browser
https://try.purescript.org
BSD 3-Clause "New" or "Revised" License
119 stars 50 forks source link

Unable to create a gist #118

Open gabejohnson opened 6 years ago

gabejohnson commented 6 years ago

When attempting to share, I receive an alert with the message:

From try.purescript.org
Failed to create gist

This is caused by a failed POST:

Request URL: https://api.github.com/gists
Request Method: POST
Status Code: 422 Unprocessable Entity

The response payload:

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Gist",
      "code": "missing_field",
      "field": "user"
    },
    {
      "resource": "Gist",
      "code": "missing_field",
      "field": "files"
    }
  ],
  "documentation_url": "https://developer.github.com/v3/gists/#create-a-gist"
}
soupi commented 6 years ago

Thanks for reporting this! Maybe the API for creating an anonymous gist changed. I'll try to take a look at this over the weekend.

soupi commented 6 years ago

So Github removed the option to post anonymous gists.

One possible alternative is to use a different service, such as lpaste.

joncfoo commented 6 years ago

It's not entirely certain what the future of lpaste is - https://www.reddit.com/r/haskell/comments/862k28/looking_for_new_maintainer_of_lpastenet/

Would it be ok to use GitHub OAuth and then create the gist as the editing user?

joncfoo commented 6 years ago

The following is a result of the PureScript hack session:

If we decide to go down the oauth route to store gists on behalf of users we'll have to:

  1. OAuth application needs to be registed with GitHub in order to receive secret tokens

    • we'll probably need a dev account as well to allow folks to hack on the repo
    • callback url will be important - something like http://localhost:3000 will suffice for the dev account
  2. Bring in the following packages

    • cookie (to encode/decode cookie data from the header)
    • clientsession (store user data (tokens) in an encrypted cookie)
    • http-client
    • http-client-tls
    • hoauth2 (used to make oauth2 requests - it's entirely possible not to use this)

The flow of code from trypurescript (FE, BE - front-end, back-end) would look like:

User has a previous session

The session info is in the secure cookie

  1. FE: user clicks share on trypurescript (triggers XHR call to BE)
  2. BE: if user has a session and a previous authtoken exists, use it to create a the gist on behalf of the user and report success/failure
    • on failure, delete the secure cookie

User does not have a previous session

  1. FE: user clicks share on trypurescript (triggers XHR call to BE)
  2. BE: requests the FE take the user to github for authentication/authorization (to allow trypurs to create gists - using the gist scope)
  3. BE: user is redirected back to a trypurescript endpoint with github specific data (exchange code)
  4. BE: use the received exchange code and make the github api call to obtain an authtoken that represents the user
    • store the token in a client session (secure cookie)
    • do this so when user again clicks share they will not have to reauth with github
    • also will not have to reauth if server restarts (until cookie expires)
  5. BE: use received authtoken to create gist via github api
  6. BE: user is taken back to the FE where they left off with a status message (probably in a query param)

Notes:

gabejohnson commented 6 years ago

We should have a control that sets the visibility (secret/public) of the gist (default to secret).

soupi commented 6 years ago

I've seen the thread before and I'm pretty certain someone is going to pick lpaste up. Also I think it's by far the simplest solution to the problem (a simple UI for sharing a trypurs gist from trypurs).

milesfrain commented 4 years ago

Would either of these options work:

Unfortunately, both of the above are vulnerable to spam.

hdgarrood commented 4 years ago

I think option 1 is likely to be against GitHub's Terms of Service, or at least liable to get the account we use banned; from their point of view, I'd expect that it's basically the same as anonymous gists. I'm not keen on option 2 either, and yeah, that's because of spam.

milesfrain commented 4 years ago

What are your thoughts on storing code as a compressed string in the URL?

The typescript web editor does this with lz-string (code link).

const hash = `code/${LZString.compressToEncodedURIComponent(State.inputModel.getValue())}`;
// later
let userCode = LZString.decompressFromEncodedURIComponent(code)

This simplifies things in a few ways:

The downside is that these links are a lot longer than a gist.

You don't want these pasted into Slack not as linked text.

Unfortunately Slack made the insane decision to have Ctrl+Shift+u be the hotkey for generating links (not Ctrl+k like virtually every other program: github editor, google docs, etc.), which also happens to be the "Unicode Code Point" shortcut in Ubuntu, and there's no way to change this hotkey in Slack. Another option is the overloaded Ctrl+v shortcut on highlighted text, but that won't give you link preview until you send the message. Zulip just lets you use the [text](link) pattern.

Here's an example URL.

Here's what happens if the URL is pasted raw.

https://www.typescriptlang.org/play/#code/PTAEBUAsEsGdQKYA8CGBbADgGwaOo0B7WAFywE88A7CcjBAZQGMAnaDEgGlACMEmUAV1i5oJPPDSCmkALAAoEIhSxoCFqBKFQgqgBN1pFPs0x4AdxSUAZtBakAdKACC4kpFwIT5hAHIsWApKTIQAbuqgkITmmtqsCCgkuO64sOi4TFgq8DyC4sLQVADmoABSDAAihEzUpAl6DgpBYADiXurQNQDCWbAi8CgsuCiglpRaoGnjkImgIxiDJJ2CWRokdAjNoAb0+vCENMaEKWsbTgBihBrI6NgI3B5DEnPbLCg+LFvmMDKgAjRRLB6OZUSiwK7iQjWUCEHgAK34XF4eRhVAoqOSGwAXE15JlsqAKm8PgAeHrHGDFcAbAB8oAA3gpQH8DkkqCRYFjQOT3IUitT6ABtAC6oAAvKARQBuXHMlB6PQAClhCKYJC5PMp-I2AEoGUzmaY4A4QuyvByHBhhJBlfDETqZfJmQBfWWgIZEcKKvWMp2GoYkQQsGi82Am1nmsMYQgYb2Ol0KV3yLYASRoVwMa20wmGhOJ6m45EIglG0ACoCoCAQwKOJy263osVGVwA1qX3Djk-JCkkWNYUExcAxqm3fcyQlgrlzSGxio6kwoe+p+4OIAwYCxxGPJtAAF4ILkAIlgh9AAB9QIe0KeL4esIf57ilAB1DLGP5DRK5onvCJw4TiNYVyTCOOSUAsfR8tQpibIoYANkOI6jB4NA+B+CRJC8lYxD+HydqapAgUwLa4REErYXmv4sCSw7ETScZPmAABy0SjG+hwKjCGgemEqSgU2KSvFRnbgsRpEsA48pKvSLKTiwR7fGICCns6DoKAR4hoOQtFthKokkfmEk8V6aldkozgWAg5YqOhiRQSMeiGaAQEaOA652By+EHIRHIbiQ4nihWCA4YZJJuX59Gmb5HniZJCqKjJqj7ke16gKpjqptCRaCL4TwjDwYiIEwg7smwTCFsWLIrMCCDhDQ8Rfi8jlUV8PyQAQ0BIAg8A6QMJjhR5YE6KoxQvLo0AHJ26neZpnXVgF5HBZRpI6eea4RQxZlgF0n5LKNIz4n0oBYNALa4AF5hiFEKKCcgJBvLQ9DMGwHBbLA5DsigSDuggACOgh2N1w1QYJSSYFkmEkCgJSFGUlTVE4aZGrAWw3ODuBoQYtiVjBmgIODjWhIM0AoDwODcCkNAYCwYTQAY9YeKA1MxuoSxAwcuOHZyjEQNoMzhMjzYsG2sOCdgVhFDTuh6BVOXlpW1ZNjIxhFLBSiCSIJB7UU8ATHwLylCgRPPewgFlvcILAgYOCQx4WwCowrCmyyBhzDwvFPgAVJ7TKe6AAACYPi5h9L0s6zrcpOvJUhsvvAOpvTwES3UiBo24aSw0haCw3r6n6zLAN7AcIQymp8g7IoR578f58j4Zmuy8AStKBoLn6hd+-7CxvGgpdR1qDsRyqiKgNXBpSbaqokD6BrMqG9dshaVqwDaw9qqZCZdgXRf+wGQY0PSZcx-QVc18yxkILn27nwggbBnXpqL1GMabZvbdKFAXhsbZmEjBRJehBJnDKoTApqKG9r7YuGwsYMgAPJ2jVBHLohBZjOBoEpXuUI-j9z5JAruNN6CbkoPSGcfII4TmAp-WSxYNAuRZIkOOPNP6oRQt-Bqv8goxEKEYKgq4sHuFmFzL4uAcxQMbBMbI0AighkZkTNgpMcBzAGHmFO6hWqdHajMfQOB4DIMSGGL2ncS70mTn0dQZIUEkBpKfaaVBCIhESKY1OgUKJOPUJtaajihhmIkhPGSFD5KXkllWKgKlTIaXoeICUDj-LeNTg4C+cYgA

milesfrain commented 4 years ago

Here's an editor prototype with both gist and url-compressed code saving and sharing.

https://milesfrain.github.io/gist-prototype/?gist=66a6389000ac663e8ba6d97381bfe4d0 https://github.com/milesfrain/gist-prototype

This eliminates the need for local storage, and the confusion that happens when folks try to share an edited gist that points to their local session. This new version guarantees that the URL you copy contains an accurate snapshot of your current editor view.

Here's an example of a current TryPureScript link that looks different to me as is does for you: https://try.purescript.org/?gist=429eab1e957e807f9feeddbf4f573dd0&session=f56137be-699b-23c3-f457-6227d3b126b3

Let me know if this is the strategy we want to go with for TryPureScript.

natefaubion commented 4 years ago

@milesfrain I think that sounds like a neat approach!

thomashoneyman commented 4 years ago

This is really cool! I'm on board with this approach. It's a best-of-both-worlds in that if you don't want to bother with a gist or you don't want to authenticate anything then you can use the longer link, and if you want a shorter link for aesthetics or because you want a gist then you can.

hdgarrood commented 4 years ago

I'm happy to consider this approach - I definitely agree that having the same URL have different behaviour based on what happens to be in the user's local storage is not ideal. I'm a little hesitant about having compressed code in the URL, as I'm sure we will see some of those huge URLs floating around, although that's probably an acceptable price to make stuff on Try PS easily shareable.

thomashoneyman commented 4 years ago

Fortunately the typical size of a TryPureScript module is pretty small and the URL isn’t that long.

maxdeviant commented 4 years ago

Create all gists through a tryPureScript account

I think option 1 is likely to be against GitHub's Terms of Service, or at least liable to get the account we use banned; from their point of view, I'd expect that it's basically the same as anonymous gists.

FWIW this is the approach that play.rust-lang.org takes and it seems to be okay.

pete-murphy commented 2 years ago

Here's an editor prototype with both gist and url-compressed code saving and sharing.

https://milesfrain.github.io/gist-prototype/?gist=66a6389000ac663e8ba6d97381bfe4d0 https://github.com/milesfrain/gist-prototype

I agree this is a neat approach, is there still interest in implementing this? As noted, TS Playground uses lz-string for (de)compression and so does Try Reason. Would adding a dependency like that still be within the scope of the project? There is a native Compression Streams API but it doesn't have great browser support at the moment.

thomashoneyman commented 2 years ago

I'm personally fine with that. I think it's a nice feature.