Skip to content

fix: the get_completion JS handler should not ignore FBE blocks - #27422

Merged
mikix merged 1 commit into
masterfrom
mikix/handler-will-recheck-access
May 4, 2021
Merged

fix: the get_completion JS handler should not ignore FBE blocks#27422
mikix merged 1 commit into
masterfrom
mikix/handler-will-recheck-access

Conversation

@mikix

@mikix mikix commented Apr 26, 2021

Copy link
Copy Markdown
Contributor

Commit message:

Because xblock handlers normally get a block tree that already has inaccessible blocks stripped, they don't see FBE gated blocks at all. So the get_completion handler would return True for FBE units incorrectly. Leading to a visual bug as an audit user went through their units in the courseware.

In order to let the handler know about the full tree, I've added a new attribute you can set on your xblock handlers:
my_handler.will_recheck_access = True

This will tell the top-level handler code to get the full tree for you.

As part of this, I've also changed the sequence xblock handlers into proper xblock handlers (not old-style xmodule handlers). This changes their URLs slightly. I've kept the old URLs for now as well, but they can be removed after Maple.

https://openedx.atlassian.net/browse/AA-409

Full set of changes with explanations:

  1. I've added support for xblock handlers to define will_recheck_access. The toplevel handler code in module_render.py will now peek at the xblock to see if it should strip inaccessible blocks or not.
  2. Rather than pipe that new attribute through the xmodule handler shim code, I've converted the sequence handlers to new-style xblock handlers. I've also left support for the old handlers in there, which we can remove after Maple.
  3. I've removed the metadata handler altogether. This was added for the learning MFE's benefit, but then never properly used because that team later added a new API request that then internally called the handler. I think they needed different module lookup flags, much like I did (they seem to both disable debug info and also set will_recheck_access). The handler is not actually called externally from the learning MFE.
  4. To ease piecemail conversion of old xmodule code to modern code, I've also passed the JS runtime down to old style module JS (see change to XBlockToXModuleShim in xmodule.js). This lets old JS easily get the proper handler URL the same way that modern JS does.
  5. The actual bug fix of get_completion.will_recheck_access = True.

This will also need changes to the learning MFE to call the new locations of these handers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The surrounding little refactor was all to just expose _get_usage_key_for_course and _get_descriptor_by_usage_key so that we could call them outside the context of get_module_by_usage_id.

@MatthewPiatetsky MatthewPiatetsky left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. I know we use the will_recheck_access argument in other places, so this is fine, though otherwise I wonder if you could have an argument that more clearly communicates the purpose like strip_inacessible_blocks_from_tree or something
  2. were you able to test that the bug was fixed locally for a FBE example?
  3. do you think it would be worthwhile to add a test with some FBE problems that confirms the completion is calculated correctly?

@Dillon-Dumesnil Dillon-Dumesnil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From what I could understand, yeah, makes sense. Thanks for the PR comment

Comment thread lms/djangoapps/courseware/module_render.py Outdated
Comment thread lms/djangoapps/courseware/module_render.py Outdated
this.num_contents = this.contents.length;
this.id = this.el.data('id');
this.ajaxUrl = this.el.data('ajax-url');
this.getCompletionUrl = runtime.handlerUrl(element, 'get_completion');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is a part I don't have a great understanding of. The runtime already has a method defined to handle this? I don't see any other changes related.

@mikix mikix Apr 26, 2021

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't fully understand this concept of a runtime either. It's a versioned JS specific runtime that only seems to have this method?

But it's how the rest of the modern xblock JS code gets handler URLs.

https://github.com/edx/edx-platform/blob/master/lms/static/lms/js/xblock/lms.runtime.v1.js#L32

@mikix

mikix commented Apr 26, 2021

Copy link
Copy Markdown
Contributor Author

I know we use the will_recheck_access argument in other places, so this is fine, though otherwise I wonder if you could have an argument that more clearly communicates the purpose like strip_inacessible_blocks_from_tree or something

Well that's how I'm using it, but some future handler might actually want to check access itself. I wanted to keep as close to the existing usage of the phrase as possible (show up in searches for that flag, etc).

were you able to test that the bug was fixed locally for a FBE example?

Yeah it seems to work. You know I ain't touching xblock code without testing it. :P

do you think it would be worthwhile to add a test with some FBE problems that confirms the completion is calculated correctly?

Yeah I hadn't gotten to the test part of this PR, honestly. Either fixing or adding. Probably makes sense to add some sort of test somewhere for this new flag / handler behavior.

@mikix
mikix force-pushed the mikix/handler-will-recheck-access branch from f8c2a5b to f89e988 Compare April 27, 2021 16:19
@mikix
mikix marked this pull request as ready for review April 27, 2021 16:20
Because xblock handlers normally get a block tree that already has
inaccessible blocks stripped, they don't see FBE gated blocks at
all. So the get_completion handler would return True for FBE units
incorrectly. Leading to a visual bug as an audit user went through
their units in the courseware.

In order to let the handler know about the full tree, I've added a
new attribute you can set on your xblock handlers:
my_handler.will_recheck_access = True

This will tell the top-level handler code get the full tree for you.

As part of this, I've also changed the sequence xblock handler's
into proper xblock handlers (not old-style xmodule handlers).
This changes their URLs slightly. I've kept the old URLs for now
as well, but they'll be removed after Maple.

AA-409
@mikix
mikix force-pushed the mikix/handler-will-recheck-access branch from f89e988 to b90039b Compare April 27, 2021 19:17
@edx-status-bot

Copy link
Copy Markdown

Your PR has finished running tests. There were no failures.

@mikix

mikix commented Apr 27, 2021

Copy link
Copy Markdown
Contributor Author

Heads up that I fixed tests and added some new ones. No actual "real code" changes so a re-review is not necessary, but if you're bored you can look over the tests.

@ormsbee

ormsbee commented May 3, 2021

Copy link
Copy Markdown
Contributor

@mikix: Thanks for pinging @kdmccormick and myself on this. I'm good with the architectural issues. In the longer term, I definitely have concerns about the level at which FBE is implemented, and the mixing of concerns that is happening by introducing markup HTML at the access permissions layer. But as we discussed earlier, I agree that implicitly passing it along as a parameter of the handler via the .recheck_access attribute is the least invasive/risky way of getting the behavior you need, and that a larger refactoring of the code is not warranted at this time.

Some other high level questions/observations:

  1. Do we have to worry about tracking event data being passed along properly with this change to the sequence AJAX handler (FYI @doctoryes)?
  2. FYI to @symbolist, in case there is any impact on upcoming modulestore cleanup work or LabXchange's use of the runtime.

@mikix

mikix commented May 3, 2021

Copy link
Copy Markdown
Contributor Author

Do we have to worry about tracking event data being passed along properly with this change to the sequence AJAX handler?

I'm not sure I understand the question. Xblock handlers do some default event tracking? (I didn't notice it, but I believe it) And the worry would be that we have some number crunching somewhere that would be interrupted by this handler URL change?

@ormsbee

ormsbee commented May 4, 2021

Copy link
Copy Markdown
Contributor

I'm not sure I understand the question. Xblock handlers do some default event tracking? (I didn't notice it, but I believe it) And the worry would be that we have some number crunching somewhere that would be interrupted by this handler URL change?

Some of the events are explicitly emitted, others are derived from server tracking logs. But I think we're safe here because the ones around sequence navigation look like they're explicitly emitted at the JS layer to the tracking endpoint: https://edx.readthedocs.io/projects/devdata/en/stable/internal_data_formats/tracking_logs.html#seq-goto-seq-next-and-seq-prev

@doctoryes: Does that sound right to you?

@doctoryes

Copy link
Copy Markdown
Contributor

@ormsbee Correct - the sequence events are emitted explicitly. For example, seq_goto is emitted by JS code to the LMS here:

https://github.com/edx/edx-platform/blob/5f569a424e0b8c2c915997393463b0133cd08f86/common/lib/xmodule/xmodule/js/src/sequence/display.js#L314-L321

and then transformed into seq_goto in the tracking logs here:

https://github.com/edx/edx-platform/blob/5f569a424e0b8c2c915997393463b0133cd08f86/common/djangoapps/track/transformers.py#L274-L286

That flow isn't being changed in this PR.

And these events can be seen in Snowflake using queries like this one:

SELECT * FROM PROD.TRACKING_EVENTS.TRACKING_EVENTS_WITH_METADATA
WHERE event_name = 'seq_goto' 
limit 100;

You could use Snowflake queries post-deploy to ensure that the proper events are still being emitted.

@mikix

mikix commented May 4, 2021

Copy link
Copy Markdown
Contributor Author

Thank you for looking, Julia! OK, I'll merge this in 30min or so if no one has any objections

@mikix
mikix merged commit 78c6be8 into master May 4, 2021
@mikix
mikix deleted the mikix/handler-will-recheck-access branch May 4, 2021 19:54
@edx-pipeline-bot

Copy link
Copy Markdown
Contributor

EdX Release Notice: This PR has been deployed to the staging environment in preparation for a release to production.

@edx-pipeline-bot

Copy link
Copy Markdown
Contributor

EdX Release Notice: This PR has been deployed to the production environment.


try {
module = new window[moduleType](element);
module = new window[moduleType](element, runtime);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@mikix @MatthewPiatetsky This seems to have caused a regression for the Conditional Block. After cherry-picking it, the conditional_get handler is not being called causing the ConditionalBlock to display empty. This is because calledElId here gets set to runtime and then the render() on line 17 is not called.

See https://openedx.atlassian.net/browse/TNL-8318 for details.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah geeze sorry - let me work on a fix.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

PR for fix: https://github.com/edx/edx-platform/pull/27625 (needs some more local testing, but I think that's the idea)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks! 🙂

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.

8 participants