Skip to content
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

Merged
merged 45 commits into from
Jul 2, 2019

Conversation

jameesjohn
Copy link
Contributor

Explanation

Fixes part of #5002: Remove csrf from GLOBALS

Checklist

  • The PR title starts with "Fix #bugnum: ", followed by a short, clear summary of the changes. (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • The PR explanation includes the words "Fixes #bugnum: ..." (or "Fixes part of #bugnum" if the PR only partially fixes an issue).
  • The linter/Karma presubmit checks have passed.
    • These should run automatically, but if not, you can manually trigger them locally using python scripts/pre_commit_linter.py and bash scripts/run_frontend_tests.sh.
  • The PR is made from a branch that's not called "develop".
  • The PR has an appropriate "CHANGELOG: ..." label (If you are unsure of which label to add, ask the reviewers for guidance).
  • The PR follows the style guide.
  • The PR addresses the points mentioned in the codeowner checks for the files/folders changed. (See the codeowner's wiki page.)
  • The PR is assigned to an appropriate reviewer.
    • If you're a new contributor, please ask on Gitter for someone to assign a reviewer and don't tick this checkbox.
    • If you're not sure who the appropriate reviewer is, please assign to the issue's "owner" -- see the "talk-to" label on the issue. Do not only request the review but also add the reviewer as an assignee.

Copy link
Contributor

@vojtechjelinek vojtechjelinek left a 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/controllers/base_test.py Outdated Show resolved Hide resolved
core/controllers/base_test.py Outdated Show resolved Hide resolved
core/controllers/profile.py Outdated Show resolved Hide resolved
core/controllers/skill_editor_test.py Outdated Show resolved Hide resolved
core/templates/dev/head/services/CsrfService.ts Outdated Show resolved Hide resolved
core/templates/dev/head/services/CsrfServiceSpec.ts Outdated Show resolved Hide resolved
return {
request: function(config) {
if (config.data) {
config.data = $.param({
csrf_token: GLOBALS.csrf_token,
csrf_token: CsrfService.getToken(),
Copy link
Contributor

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.

Copy link
Member

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?

Copy link
Contributor Author

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

Copy link
Member

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?

Copy link
Contributor Author

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

Copy link
Member

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.

@vojtechjelinek
Copy link
Contributor

@seanlip PTAL

Copy link
Member

@seanlip seanlip left a 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) {
Copy link
Member

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.

Copy link
Contributor Author

@jameesjohn jameesjohn Jun 28, 2019

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done PTAL

Copy link
Member

@seanlip seanlip Jun 28, 2019

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?

Copy link
Contributor Author

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',
Copy link
Contributor Author

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.

Copy link
Contributor Author

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

Copy link
Member

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

Copy link
Contributor Author

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',
Copy link
Contributor Author

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');
Copy link
Contributor Author

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

@oppiabot
Copy link

oppiabot bot commented Jun 28, 2019

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!

Copy link
Member

@seanlip seanlip left a 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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (token !== null)

Copy link
Contributor Author

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) {
Copy link
Member

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."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@seanlip
Copy link
Member

seanlip commented Jun 29, 2019

Also please note merge conflict and failing Travis tests.

@seanlip seanlip assigned jameesjohn and unassigned seanlip Jun 29, 2019
@jameesjohn
Copy link
Contributor Author

jameesjohn commented Jul 1, 2019

@aks681 PTAL as code owner

@oppiabot
Copy link

oppiabot bot commented Jul 1, 2019

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!

Copy link
Contributor

@aks681 aks681 left a 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

@jameesjohn
Copy link
Contributor Author

@seanlip, I think this is ready to be merged.

@seanlip
Copy link
Member

seanlip commented Jul 2, 2019

Thanks, merging!

@seanlip seanlip merged commit 521a4b0 into oppia:develop Jul 2, 2019
@lilithxxx lilithxxx mentioned this pull request Jul 3, 2019
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants