diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c01501a..4b89d31 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,9 +14,15 @@ Change Log Unreleased ********** -feat: [ACADEMIC-16207] Added models to summaryhook_aside (Has migrations) -feat: [ACADEMIC-16177] Catch exceptions in a couple of locations so the aside cannot crash content. +3.0.0 – 2023-07-16 +********************************************** + +Features +========= +* Summary content handler now requires a staff user identity, otherwise returns 403. This is a breaking change. +* Added models to summaryhook_aside (Has migrations) +* Catch exceptions in a couple of locations so the aside cannot crash content. 2.0.2 – 2023-07-05 ********************************************** diff --git a/ai_aside/__init__.py b/ai_aside/__init__.py index ce374e3..8f230c2 100644 --- a/ai_aside/__init__.py +++ b/ai_aside/__init__.py @@ -2,4 +2,4 @@ A plugin containing xblocks and apps supporting GPT and other LLM use on edX. """ -__version__ = '2.0.2' +__version__ = '3.0.0' diff --git a/ai_aside/block.py b/ai_aside/block.py index 6bea180..1cf5b71 100644 --- a/ai_aside/block.py +++ b/ai_aside/block.py @@ -43,6 +43,10 @@ def _format_date(date): return date.strftime('%Y-%m-%d %H:%M:%S') if isinstance(date, datetime) else None +def _staff_user(block): + return getattr(block.runtime, 'user_is_staff', False) + + def _render_summary(context): template = Template(summary_fragment) return template.render(Context(context)) @@ -135,7 +139,13 @@ class SummaryHookAside(XBlockAside): def summary_handler(self, request=None, suffix=None): # pylint: disable=unused-argument """ Extract and return summarizable text from unit children. + + Only services and staff users are allowed to fetch summary text, everyone else + gets an unhelpful 403. """ + if not _staff_user(self): + return Response(status=403) + block = get_block(self.scope_ids.usage_id.usage_key) valid = self.should_apply_to_block(block) @@ -199,14 +209,7 @@ def _student_view_can_throw(self, block): if length < settings.SUMMARY_HOOK_MIN_SIZE: return fragment - # thirdparty=true connects to the unauthenticated handler for now, - # we will secure it in ACADEMIC-16187 - handler_url = self.runtime.handler_url(self, 'summary_handler', thirdparty=True) - - # enable ai-spot to see the LMS when they are installed together in devstack - aispot_lms_name = settings.AISPOT_LMS_NAME - if aispot_lms_name != '': - handler_url = handler_url.replace('localhost', aispot_lms_name) + handler_url = self._summary_handler_url() fragment.add_content( _render_summary( @@ -221,6 +224,24 @@ def _student_view_can_throw(self, block): ) return fragment + def _summary_handler_url(self): + """ + Generate the summary handler URL for this block. + + A separate function to handle overrides required + for the unusual use of the handler (non-edx codebase edx service) + and to override the URL for use in devstack. + """ + # thirdparty=true gives the full host name and unauthenticated handler + handler_url = self.runtime.handler_url(self, 'summary_handler', thirdparty=True) + # but we want the authenticated handler + handler_url = handler_url.replace('handler_noauth', 'handler') + # enable ai-spot to see the LMS when they are installed together in devstack + aispot_lms_name = settings.AISPOT_LMS_NAME + if aispot_lms_name != '': + handler_url = handler_url.replace('localhost', aispot_lms_name) + return handler_url + @classmethod def should_apply_to_block(cls, block): """ @@ -245,7 +266,6 @@ def _should_apply_can_throw(cls, block): if getattr(block, 'category', None) != 'vertical': return False course_key = block.scope_ids.usage_id.course_key - if (getattr(block.runtime, 'user_is_staff', False) - and summary_staff_only(course_key)): + if _staff_user(block) and summary_staff_only(course_key): return True return summary_enabled(course_key)