refactor: replace deprecated rebind_noauth_module_to_user, get_real_user, runtime.hostname, runtime.course_id [BD-13] - #249
Conversation
|
Thanks for the pull request, @tecoholic! When this pull request is ready, tag your edX technical lead. |
Codecov ReportBase: 97.78% // Head: 97.78% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## master #249 +/- ##
=======================================
Coverage 97.78% 97.78%
=======================================
Files 72 72
Lines 5870 5876 +6
=======================================
+ Hits 5740 5746 +6
Misses 130 130
Flags with carried forward coverage won't be shown. Click here to find out more.
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
There was a problem hiding this comment.
I've reused your script from openedx/openedx-platform#30320, but it was giving me the following error:
Traceback (most recent call last):
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/decorators/clickjacking.py", line 50, in wrapped_view
resp = view_func(*args, **kwargs)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/module_render.py", line 895, in handle_xblock_callback_noauth
return _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course=course)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/module_render.py", line 1108, in _invoke_xblock_handler
resp = handler_instance.handle(handler, req, suffix)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/xblock/mixins.py", line 84, in handle
return self.runtime.handle(self, handler_name, request, suffix)
File "/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/x_module.py", line 1367, in handle
return super().handle(block, handler_name, request, suffix=suffix)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/xblock/runtime.py", line 1081, in handle
results = handler(request, suffix)
File "/edx/shared-src/xblock-lti-consumer/lti_consumer/lti_xblock.py", line 1325, in result_service_handler
log_authorization_header(request, lti_provider_key, lti_provider_secret)
File "/edx/shared-src/xblock-lti-consumer/lti_consumer/lti_1p1/oauth.py", line 153, in log_authorization_header
params = client.get_oauth_params(request)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/oauthlib/oauth1/rfc5849/__init__.py", line 185, in get_oauth_params
params.append(('oauth_body_hash', base64.b64encode(hashlib.sha1(request.body.decode()).digest()).decode('utf-8')))
TypeError: Unicode-objects must be encoded before hashingTo avoid this, I've replaced the following line in /edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/oauthlib/oauth1/rfc5849/__init__.py.
- params.append(('oauth_body_hash', base64.b64encode(hashlib.sha1(request.body.encode('utf-8')).digest()).decode('utf-8')))
+ params.append(('oauth_body_hash', base64.b64encode(hashlib.sha1(request.body.decode().encode('utf-8')).digest()).decode('utf-8')))Should I do something different while sending this request?
Edit: also, please bump the version in lti_consumer/__init__.py and add an entry to the changelog.
|
@Agrendalath @tecoholic Can you double-check grade linking still work? https://github.com/openedx/xblock-lti-consumer/blob/master/lti_consumer/signals.py#L34 I'm worried that |
|
@giovannicimolin, I've followed the instructions from openedx/openedx-platform#30320 on the devstack with a modification mentioned in my previous comment. Should we do something else to check it? |
|
@giovannicimolin @Agrendalath I might have jumped the gun on this one. I think I didn't do a proper install inside the container while testing this. Let me rework this & submit it again for review. |
43ce5f4 to
d075245
Compare
|
@giovannicimolin The test I created for testing the LTI 2.0 endpoints in openedx/openedx-platform#30320 doesn't seem to create Is there a way to test this? Should we setup a LTI 1.3 client for this? |
|
@tecoholic The LTI AGS models are only used by LTI 1.3 with grades enabled. To avoid the hassle of setting it up, you can:
This should trigger the signal, you can add a debugger/breakpoint to analyze the parameters and match the conditions. 😄 |
|
@giovannicimolin I was able to test the the signal is triggered and processed without issue using the following steps:
Everything worked as expected and the score was verified in the gradebook as well. Does the above testing resolve our concerns? cc: @Agrendalath |
|
@tecoholic That's perfect, thank you for testing it! No more concerns from my side! 👍 |
Agrendalath
left a comment
There was a problem hiding this comment.
@tecoholic, please rebase this on the master branch (we need to bump the version to 4.2.0).
👍
- I tested this: verified that the XBlock is working correctly with the new
rebind_userservice. - I read through the code
- I checked for accessibility issues: n/a
- Includes documentation: n/a
- I made sure any change in configuration variables is reflected in the corresponding client's
configuration-securerepository: n/a
|
Just repeating the note from the description - we shouldn't merge this before openedx/openedx-platform#30320. |
d075245 to
6c49660
Compare
|
@Agrendalath A new commit (05bda98) to related to the |
|
@giovannicimolin, @ashultz0, I'm not familiar with the change introduced in this commit, so I just wanted to mention that this scenario (i.e. creating a new 2022-11-22 15:20:56,058 ERROR 5002 [django.request] [user None] [ip None] log.py:224 - Internal Server Error: /admin/lti_consumer/ltiagsscore/add/
Traceback (most recent call last):
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/contrib/admin/options.py", line 616, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/contrib/admin/sites.py", line 232, in inner
return view(request, *args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1657, in add_view
return self.changeform_view(request, None, form_url, extra_context)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1540, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1586, in _changeform_view
self.save_model(request, new_object, form, not add)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1099, in save_model
obj.save()
File "/edx/shared-src/xblock-lti-consumer/lti_consumer/models.py", line 704, in save
super().save(*args, **kwargs)
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/db/models/base.py", line 739, in save
self.save_base(using=using, force_insert=force_insert,
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/db/models/base.py", line 787, in save_base
post_save.send(
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 180, in send
return [
File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 181, in <listcomp>
(receiver, receiver(signal=self, sender=sender, **named))
File "/edx/shared-src/xblock-lti-consumer/lti_consumer/signals/signals.py", line 64, in publish_grade_on_score_update
raise exc
File "/edx/shared-src/xblock-lti-consumer/lti_consumer/signals/signals.py", line 53, in publish_grade_on_score_update
block.set_user_module_score(user, score, block.max_score(), instance.comment)
File "/edx/shared-src/xblock-lti-consumer/lti_consumer/lti_xblock.py", line 1423, in set_user_module_score
self.runtime.rebind_noauth_module_to_user(self, user)
File "/edx/app/edxapp/edx-platform/xmodule/services.py", line 192, in rebind_noauth_module_to_user
raise RebindUserServiceError(err_msg)
xmodule.services.RebindUserServiceError: rebind_noauth_module_to_user can only be called from a module bound to an anonymous userThe current PR doesn't change this behavior, but please let me know if you'd like to review it before we merge. |
Agrendalath
left a comment
There was a problem hiding this comment.
👍
- I tested this: verified that the XBlock is working correctly (with this exception) after replacing deprecated runtime attributes
- I read through the code
- I checked for accessibility issues: n/a
- Includes documentation: n/a
- I made sure any change in configuration variables is reflected in the corresponding client's
configuration-securerepository: n/a
| hostname='localhost', | ||
| ) | ||
| xblock.course_id = 'course-v1:edX+DemoX+Demo_Course' | ||
| xblock.course_id = course_id |
There was a problem hiding this comment.
Nit: are we still using this and xblock.location (above) anywhere?
|
@Agrendalath thanks for pointing that out. We'll have to figure out how to let that work without so much magic. |
The OAuthlib 1.0 Client's get_oauth_params fails when processing Webob request object with the body stored as a binary instead of string. This commit replaces the client function with a different one which doesn't involve body hashing, as the body hash is calculated explicitly.
adce625 to
ec85ddf
Compare
The `rebind_noauth_module_to_user` function is deprecated in the core edx-platform [1]. This is now replaced with a "rebind_user" service. This commit brings this change to the LTI Consumer XBlock. [1] - openedx/openedx-platform#30320
The hostname used to construct the resource link ID is moved from using a runtime attribute to the LMS_BASE setting.
Replaces usages of runtime.course_id with runtime.scope_ids.usage_id.context_key.
acd18ad to
ebe330a
Compare
rebind_noauth_module_to_user, get_real_user, runtime.hostname, runtime.course_id
ebe330a to
f647c5f
Compare
rebind_noauth_module_to_user, get_real_user, runtime.hostname, runtime.course_idrebind_noauth_module_to_user, get_real_user, runtime.hostname, runtime.course_id [BD-13]
|
@tecoholic 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
|
this is going into the platform today along with a mostly unrelated bugfix as 7.0.1 openedx/openedx-platform#31369 |
|
|
||
| real_user = self.xblock.runtime.get_real_user(urllib.parse.unquote(sourced_id.split(':')[-1])) | ||
| anon_id = unquote(sourced_id.split(':')[-1]) | ||
| real_user = self.xblock.runtime.service(self, 'user').get_user_by_anonymous_id(anon_id) |
There was a problem hiding this comment.
this line turns out to have a bug - it should be
real_user = self.xblock.runtime.service(self.xblock, 'user').get_user_by_anonymous_id(anon_id)
|
@Agrendalath @tecoholic 7.0.1 failed on edx production in the outcome service and had to be rolled back, I think I have figured out why and noted above we're actually already changing that to allow external instead of anonymous IDs in 7.0.2 which will I believe fix the problem without having to revert all the rest of the refactors |
|
@ashultz0, good catch. Thank you for fixing this! |
Description
The
rebind_noauth_module_to_userfunction is deprecated[1] in the core edx-platform. This is now replaced with a "rebind_user" service. This PR brings this change to the LTI Consumer XBlock.This should be considered for review and merged after openedx/openedx-platform#30320 is merged.
Edit
The PR is now updated with changes related to the deprecation of the
hostnameparameter[2] from the runtime as well.It also replaces usages of
get_real_userwith theUserServiceandcourse_idwithruntime.scope_ids.usage_id.context_keyThis should be considered for merging only after openedx/openedx-platform#30308, openedx/openedx-platform#30320, and openedx/openedx-platform#30715 are merged.
Testing instructions
The testing instructions of the parent PR can be used to test the LTI Consumer XBlock.
Additional information
[1] - openedx/openedx-platform#30320
[2] - openedx/openedx-platform#30308