-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Fixes part of #5002: Remove CSRF token from GLOBALS #6951
Conversation
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.
Thanks! Few comments.
core/templates/dev/head/App.ts
Outdated
return { | ||
request: function(config) { | ||
if (config.data) { | ||
config.data = $.param({ | ||
csrf_token: GLOBALS.csrf_token, | ||
csrf_token: CsrfService.getToken(), |
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.
What if this is called before we the request for CSRF finishes? We should return a promise from .getToken()
that will resolve only if the token is already available.
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.
@Jamesjay4199 When you mark a comment as resolved, please always include an explanation (for the benefit of future developers/reviewers). Could you respond to @vojtechjelinek's 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 think this will never be the case because the csrf token is only used for post requests and a post request is only sent based on the user interaction with the page, while the request gets sent much earlier
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.
It could theoretically happen though (e.g. if the server is overloaded for some reason). What will the user experience in this case, and what should they experience ideally?
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've refactored it to use a promise.
@vojtechjelinek PTAL
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.
Why do you need to use jQuery? AngularJS has $q, try to use that for promises if possible.
@seanlip PTAL |
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.
One more comment.
// creates a circular dependency. | ||
return new Promise(function(resolve, reject) { | ||
if (token) { | ||
if (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.
Should we throw an error if no token is set (i.e. initialization has not happened yet)? If you think it's possible for this to be called before initialization, then change the name to getTokenAsync(), and add a test that calls getToken() before initializeToken() and make sure that works correctly. Otherwise, throw an error if token is null and just return the token otherwise; no need to return a promise.
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.
@seanlip I think we'll still need to return a promise because it is possible that the initialization is not complete when a POST or PUT request is sent so the request will have to wait for the initialization to be complete.
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.
Done PTAL
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.
OK, can you add a test that calls getTokenAsync() before initializeToken() so that we can be sure this works correctly in the case where token initialization has some latency?
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've done that already here
} | ||
); | ||
|
||
it('should error if getTokenAsync is called before initialization', |
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.
@seanlip It is tested here.
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 called getTokenAsync without calling initialization
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.
Wait, I'm confused, sorry. You said earlier:
@seanlip I think we'll still need to return a promise because it is possible that the initialization is not complete when a POST or PUT request is sent so the request will have to wait for the initialization to be complete.
But this test is checking that it throws an error, which seems different from your description.
Also, where does "Token needs to be initialized" come from? I do not see it in core/templates/dev/head/services/CsrfTokenService.ts
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.
The test checks if getTokenAsync is called without already calling initializeToken.
It throws the error if a call to getTokenAsync was made before initializing the token
} | ||
); | ||
|
||
it('should error if getTokenAsync is called before initialization', |
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.
The test checks if getTokenAsync is called without already calling initializeToken.
It throws the error if a call to getTokenAsync was made before initializing the token
if (tokenPromise) { | ||
return tokenPromise; | ||
} else { | ||
throw new Error('Token needs to be initialized'); |
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.
Also, where does "Token needs to be initialized" come from? I do not see it in core/templates/dev/head/services/CsrfTokenService.ts
@seanlip, Token needs to be initialized comes from here. PTAL
Hi @Jamesjay4199. Due to recent changes in the "develop" branch, this PR now has a merge conflict. Please follow this link if you need help resolving the conflict, so that the PR can be merged. Thanks! |
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.
Ah ok, thank you for the explanation @Jamesjay4199. Sorry for being slow! I see what you're doing now and I think it makes sense.
Two trivial comments, then feel free to merge. Thanks!
}, | ||
|
||
getTokenAsync: function() { | ||
if (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.
if (token !== null)
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.
Done
resolve(token); | ||
}); | ||
} | ||
if (tokenPromise) { |
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.
if (tokenPromise !== null)
And, include a line comment just below this line saying "The token initialization request is still pending."
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.
Done
Also please note merge conflict and failing Travis tests. |
@aks681 PTAL as code owner |
Hi @Jamesjay4199. Due to recent changes in the "develop" branch, this PR now has a merge conflict. Please follow this link if you need help resolving the conflict, so that the PR can be merged. Thanks! |
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.
Note, changes to package-lock.json
@seanlip, I think this is ready to be merged. |
Thanks, merging! |
Explanation
Fixes part of #5002: Remove csrf from GLOBALS
Checklist
python scripts/pre_commit_linter.py
andbash scripts/run_frontend_tests.sh
.