refactor: removes calls to deprecated ModuleSystem attributes

Removes references to these deprecated attributes from the platform code:
* runtime.anonymous_student_id
* runtime.seed
* runtime.user_id
* runtime.user_is_staff

Related changes:

* Ensure that all platform XBlocks which use these attributes "need" the user service.
* ProblemBlock: Removes check for existence of runtime.seed attribute in preparation for removal of this attribute from ModuleSystem.
* edxnotes: Catches NoSuchServiceError just in case some XBlocks using notes don't have the user service.
* UserTagsService refactor: pass user and course_id on creation
This commit is contained in:
Jillian Vogel
2021-08-31 16:20:53 +09:30
parent c41e7fb93a
commit 753839276f
9 changed files with 85 additions and 46 deletions

View File

@@ -31,6 +31,11 @@ from capa.capa_problem import LoncapaProblem, LoncapaSystem
from capa.inputtypes import Status
from capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
from capa.util import convert_files_to_filenames, get_inner_html_from_xpath
from common.djangoapps.xblock_django.constants import (
ATTR_KEY_ANONYMOUS_USER_ID,
ATTR_KEY_USER_IS_STAFF,
ATTR_KEY_USER_ID,
)
from openedx.core.djangolib.markup import HTML, Text
from xmodule.contentstore.django import contentstore
from xmodule.editing_module import EditingMixin
@@ -113,7 +118,7 @@ class Randomization(String):
to_json = from_json
@XBlock.wants('user')
@XBlock.needs('user')
@XBlock.needs('i18n')
@XBlock.wants('call_to_action')
class ProblemBlock(
@@ -784,9 +789,10 @@ class ProblemBlock(
"""
if self.rerandomize == RANDOMIZATION.NEVER:
self.seed = 1
elif self.rerandomize == RANDOMIZATION.PER_STUDENT and hasattr(self.runtime, 'seed'):
elif self.rerandomize == RANDOMIZATION.PER_STUDENT:
user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_ID) or 0
# see comment on randomization_bin
self.seed = randomization_bin(self.runtime.seed, str(self.location).encode('utf-8'))
self.seed = randomization_bin(user_id, str(self.location).encode('utf-8'))
else:
self.seed = struct.unpack('i', os.urandom(4))[0]
@@ -801,9 +807,13 @@ class ProblemBlock(
if text is None:
text = self.data
user_service = self.runtime.service(self, 'user')
anonymous_student_id = user_service.get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
seed = user_service.get_current_user().opt_attrs.get(ATTR_KEY_USER_ID) or 0
capa_system = LoncapaSystem(
ajax_url=self.ajax_url,
anonymous_student_id=self.runtime.anonymous_student_id,
anonymous_student_id=anonymous_student_id,
cache=self.runtime.cache,
can_execute_unsafe_code=self.runtime.can_execute_unsafe_code,
get_python_lib_zip=self.runtime.get_python_lib_zip,
@@ -812,7 +822,7 @@ class ProblemBlock(
i18n=self.runtime.service(self, "i18n"),
node_path=self.runtime.node_path,
render_template=self.runtime.render_template,
seed=self.runtime.seed, # Why do we do this if we have self.seed?
seed=seed, # Why do we do this if we have self.seed?
STATIC_URL=self.runtime.STATIC_URL,
xqueue=self.runtime.xqueue,
matlab_api_key=self.matlab_api_key
@@ -1412,6 +1422,7 @@ class ProblemBlock(
"""
Is the user allowed to see an answer?
"""
user_is_staff = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF)
if not self.correctness_available():
# If correctness is being withheld, then don't show answers either.
return False
@@ -1419,7 +1430,7 @@ class ProblemBlock(
return False
elif self.showanswer == SHOWANSWER.NEVER:
return False
elif self.runtime.user_is_staff:
elif user_is_staff:
# This is after the 'never' check because admins can see the answer
# unless the problem explicitly prevents it
return True
@@ -1459,10 +1470,11 @@ class ProblemBlock(
Limits access to the correct/incorrect flags, messages, and problem score.
"""
user_is_staff = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF)
return ShowCorrectness.correctness_available(
show_correctness=self.show_correctness,
due_date=self.close_date,
has_staff_access=self.runtime.user_is_staff,
has_staff_access=user_is_staff,
)
def update_score(self, data):
@@ -1777,7 +1789,8 @@ class ProblemBlock(
# If the user is a staff member, include
# the full exception, including traceback,
# in the response
if self.runtime.user_is_staff:
user_is_staff = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF)
if user_is_staff:
msg = f"Staff debug info: {traceback.format_exc()}"
# Otherwise, display just an error message,

View File

@@ -17,6 +17,7 @@ from path import Path as path
from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Boolean, List, Scope, String
from common.djangoapps.xblock_django.constants import ATTR_KEY_ANONYMOUS_USER_ID
from xmodule.contentstore.content import StaticContent
from xmodule.editing_module import EditingMixin
from xmodule.edxnotes_utils import edxnotes
@@ -42,6 +43,7 @@ _ = lambda text: text
@XBlock.needs("i18n")
@XBlock.needs("user")
class HtmlBlockMixin( # lint-amnesty, pylint: disable=abstract-method
XmlMixin, EditingMixin,
XModuleDescriptorToXBlockMixin, XModuleToXBlockMixin, HTMLSnippet, ResourceTemplates, XModuleMixin,
@@ -117,8 +119,9 @@ class HtmlBlockMixin( # lint-amnesty, pylint: disable=abstract-method
""" Returns html required for rendering the block. """
if self.data:
data = self.data
if getattr(self.runtime, 'anonymous_student_id', None):
data = data.replace("%%USER_ID%%", self.runtime.anonymous_student_id)
user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
if user_id:
data = data.replace("%%USER_ID%%", user_id)
data = data.replace("%%COURSE_ID%%", str(self.scope_ids.usage_id.context_key))
return data
return self.data

View File

@@ -78,6 +78,7 @@ from xmodule.mako_module import MakoTemplateBlockBase
from openedx.core.djangolib.markup import HTML, Text
from xmodule.editing_module import EditingMixin
from common.djangoapps.xblock_django.constants import ATTR_KEY_ANONYMOUS_USER_ID
from xmodule.lti_2_util import LTI20BlockMixin, LTIError
from xmodule.raw_module import EmptyDataRawMixin
from xmodule.util.xmodule_django import add_webpack_to_fragment
@@ -269,6 +270,7 @@ class LTIFields:
@XBlock.needs("i18n")
@XBlock.needs("user")
class LTIBlock(
LTIFields,
LTI20BlockMixin,
@@ -529,7 +531,10 @@ class LTIBlock(
return Response(template, content_type='text/html')
def get_user_id(self):
user_id = self.runtime.anonymous_student_id
"""
Returns the current user ID, URL-escaped so it is safe to use as a URL component.
"""
user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
assert user_id is not None
return str(parse.quote(user_id))
@@ -671,7 +676,8 @@ class LTIBlock(
# To test functionality test in LMS
if callable(self.runtime.get_real_user):
real_user_object = self.runtime.get_real_user(self.runtime.anonymous_student_id)
user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
real_user_object = self.runtime.get_real_user(user_id)
try:
self.user_email = real_user_object.email # lint-amnesty, pylint: disable=attribute-defined-outside-init
except AttributeError:

View File

@@ -33,6 +33,7 @@ from xmodule.x_module import (
XModuleToXBlockMixin,
)
from common.djangoapps.xblock_django.constants import ATTR_KEY_USER_ID, ATTR_KEY_USER_IS_STAFF
from openedx.core.djangoapps.agreements.toggles import is_integrity_signature_enabled
from .exceptions import NotFoundError
@@ -378,7 +379,7 @@ class SequenceBlock(
is_hidden_after_due = False
if self._required_prereq():
if self.runtime.user_is_staff:
if self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF):
banner_text = _(
'This subsection is unlocked for learners when they meet the prerequisite requirements.'
)
@@ -459,7 +460,7 @@ class SequenceBlock(
prereq_met = True
prereq_meta_info = {}
if self._required_prereq():
if self.runtime.user_is_staff:
if self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF):
banner_text = _(
'This subsection is unlocked for learners when they meet the prerequisite requirements.'
)
@@ -553,7 +554,7 @@ class SequenceBlock(
"""
hidden_date = course.end if course.self_paced else self.due
return (
self.runtime.user_is_staff or
self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF) or
self.verify_current_content_visibility(hidden_date, self.hide_after_due)
)
@@ -643,8 +644,9 @@ class SequenceBlock(
"""
gating_service = self.runtime.service(self, 'gating')
if gating_service:
user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_ID)
fulfilled = gating_service.is_gate_fulfilled(
self.course_id, self.location, self.runtime.user_id
self.course_id, self.location, user_id
)
return fulfilled
@@ -692,7 +694,8 @@ class SequenceBlock(
comes to determining whether a student is allowed to access this,
with other checks being done in has_access calls.
"""
if self.runtime.user_is_staff or context.get('specific_masquerade', False):
user_is_staff = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_IS_STAFF)
if user_is_staff or context.get('specific_masquerade', False):
return False
# We're not allowed to see it because of pre-reqs that haven't been
@@ -723,7 +726,8 @@ class SequenceBlock(
"""
gating_service = self.runtime.service(self, 'gating')
if gating_service:
return gating_service.compute_is_prereq_met(self.location, self.runtime.user_id, recalc_on_unmet)
user_id = self.runtime.service(self, 'user').get_current_user().opt_attrs.get(ATTR_KEY_USER_ID)
return gating_service.compute_is_prereq_met(self.location, user_id, recalc_on_unmet)
return True, {}
@@ -915,8 +919,10 @@ class SequenceBlock(
self.is_time_limited
)
if feature_enabled:
user_id = self.runtime.user_id
user_role_in_course = 'staff' if self.runtime.user_is_staff else 'student'
current_user = self.runtime.service(self, 'user').get_current_user()
user_id = current_user.opt_attrs.get(ATTR_KEY_USER_ID)
user_is_staff = current_user.opt_attrs.get(ATTR_KEY_USER_IS_STAFF)
user_role_in_course = 'staff' if user_is_staff else 'student'
course_id = self.runtime.course_id
content_id = self.location