-
Notifications
You must be signed in to change notification settings - Fork 57
Add copy to clipboard buttons to display token page #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add copy to clipboard buttons to display token page #200
Conversation
0f2e803 to
f02b3b4
Compare
3632827 to
3cd1e22
Compare
3cd1e22 to
c9a96d7
Compare
spadgett
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
/retest |
everettraven
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems fine to me. I don't think I have approval permissions. Will likely need @ibihim for approval.
/lgtm
| <code>{{.AccessToken}}</code> | ||
| <script> | ||
| var commands = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this is my old school JS, but isn't it better to have something like this namespaced approach:
var openshift = openshift || {};
openshift.commands = openshift.commands || {};
openshift.commands.login = '...';
openshift.commands.apiCall = '...';or a IIFE that is completely isolated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before this PR, the token request page had no JavaScript so I'm not sure if using the openshift variable to namespace the commands is really needed.
I wanted to keep the changes at minimum so I went with a single commands variable to hold the strings to copy.
var commands = { foo: 'x' };is functionally the same as
var commands = {};
commands.foo = 'x';As for IIFE, these are typically used to avoid pollution of the global object namespace but I don't think we need them in our case.
The idea is to define some global object to store the strings to be referenced by the copy button's onclick handler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think that it is always worth to introduce best practices, but nevertheless, this isn't a thing that I would keep blocking the PR.
| oc login | ||
| <span class="nowrap">--token={{.AccessToken}}</span> | ||
| <span class="nowrap">--server={{.PublicMasterURL}}</span> | ||
| <button onclick="navigator.clipboard.writeText(commands.login)">Copy</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we add some feedback for the user, like changing the button text to "Copied!" or so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would add more complexity, which is something I wanted to avoid.
The page template is missing standard HTML structure, including <!doctype html>, <head>, <body> etc. which cause browsers to render this page it in "quirks" mode.
I could try to add some custom-styled "Copied!" feedback text upon clicking the button, but do we really need it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented.
| oc login | ||
| <span class="nowrap">--token={{.AccessToken}}</span> | ||
| <span class="nowrap">--server={{.PublicMasterURL}}</span> | ||
| <button onclick="navigator.clipboard.writeText(commands.login)">Copy</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText
Isn't it best practice to handle the error somehow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We just call the clipboard.writeText function without handling the resulting Promise.
This function is async and resolves when the clipboard's contents have been updated. If we had a "Copied!" feedback text implemented, we'd be handing the Promise, but currently we don't need that.
I'm not sure we need an explicit error handler here, unless we want to implement the feedback text, could be something like "Failed to copy the snippet to clipboard, see browser logs for details" or similar.
In practice, clipboard.writeText function could fail if the page was forbidden to copy text to clipboard via setting page permissions, e.g. for Chromium based browsers [1]:
Writing requires either the
clipboard-writepermission or transient activation.
[1] https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API#security_considerations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vojtechszocs Maybe just throw up an alert on an error? Something like...? "Copy to clipboard failed. Select the content to copy it manually."
In practice, I'd expect clipboard write to almost never fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented
c9a96d7 to
412eb21
Compare
|
New changes are detected. LGTM label has been removed. |
|
@vojtechszocs: all tests passed! Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
|
I wish there would have been a more detailed explanation why it is fine to get rid of the intermediate CSRF step, but after bouncing my head for an hour on this topic, the worst thing I could imagine is that a disgruntled Alice could sneak in her tokens on your page. |
|
I will approve once @everettraven lgtm'ed it... or @liouk |
everettraven
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned about us making a breaking change to the acceptable requests here - because it is out there, and has been out there for a while, I would not be surprised if there is some kind of end user workflow that depends on sending a properly formed POST request to display the token.
Additionally, do we have any kind of testing in place for UX/UI related changes we can update / put in place here?
If there is not existing testing infrastructure here it isn't the end of the world, but if it exists we should make sure the UX changes are appropriately tested.
| func (t *tokenRequest) displayToken(osinOAuthClient *osincli.Client, w http.ResponseWriter, req *http.Request) { | ||
| switch req.Method { | ||
| case http.MethodGet: | ||
| t.displayTokenGet(osinOAuthClient, w, req) | ||
| case http.MethodPost: | ||
| t.displayTokenPost(osinOAuthClient, w, req) | ||
| default: | ||
| if req.Method != http.MethodGet { | ||
| http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a breaking change - is there a particular reason we are making this change?
| <input type="hidden" name="code" value="{{.Code}}"> | ||
| <input type="hidden" name="csrf" value="{{.CSRF}}"> | ||
| <button type="submit"> | ||
| Display Token |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't remove this. This was there to prevent cross-site request forgery.
/hold
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: everettraven, vojtechszocs The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
This PR modifies the token display page for quicker access to token data.
tokenTemplatedirectly, i.e. without HTTP POST "Display Token" form submit.Click "Show" to reveal the snippet. Click "Copy" to copy the snippet to clipboard.
JavaScript code is using standard Clipboard API which should be supported by all modern browsers.