-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
fix: hide sequences & sections when access is restricted in units #33191
fix: hide sequences & sections when access is restricted in units #33191
Conversation
Thanks for the pull request, @CefBoud! Please note that it may take us up to several weeks or months to complete a review and merge your PR. Feel free to add as much of the following information to the ticket as you can:
All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here. Please let us know once your PR is ready for our review and all tests are green. |
98ebc97
to
9d64067
Compare
341a791
to
9c53194
Compare
3120317
to
e4912d9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few nits and one question related to tests, but 👍 from me. Good job!
- I tested this: sections without accessible content aren't visible when cohorts are enabled.
- I read through the code.
- Includes documentation
def __init__(self, course_key: CourseKey, user: types.User, at_time: datetime): | ||
super().__init__(course_key, user, at_time) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean but I tried to follow what was done in other processors : EnrollmentTrackPartitionGroupsOutlineProcessor, ContentGatingOutlineProcessor, ScheduleOutlineProcessor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think either way is fine, FWIW. Unless it's causing some kind of error in the linting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not causing any errors.
if user_cohort: | ||
self.user_cohort_group_id, _ = get_group_info_for_cohort(user_cohort) | ||
|
||
def _is_user_excluded_by_partition_group(self, user_partition_groups): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be typed too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitily!
@@ -1716,6 +1718,216 @@ def test_processor_only( | |||
removed_usage_keys = processor.usage_keys_to_remove(full_outline) | |||
assert len(removed_usage_keys) == expected_values_dict[learner_to_verify.username] | |||
|
|||
@ddt.ddt | |||
class CohortPartitionGroupsTestCase(OutlineProcessorTestCase): # lint-amnesty, pylint: disable=missing-class-docstring |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need these linter directives here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not! Removed.
def _add_course_mode( | ||
self, | ||
course_key, | ||
mode_slug=CourseMode.VERIFIED, | ||
mode_display_name='Verified Certificate' | ||
): | ||
""" | ||
Add a course mode to the test course_key. | ||
Args: | ||
course_key | ||
mode_slug (str): the slug of the mode to add | ||
mode_display_name (str): the display name of the mode to add | ||
upgrade_deadline_expired (bool): whether the upgrade deadline has passed | ||
""" | ||
signals.post_save.disconnect(update_masters_access_course, sender=CourseMode) | ||
try: | ||
CourseMode.objects.create( | ||
course_id=course_key, | ||
mode_slug=mode_slug, | ||
mode_display_name=mode_display_name, | ||
min_price=50 | ||
) | ||
finally: | ||
signals.post_save.connect(update_masters_access_course, sender=CourseMode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to set a course mode to test this? I succeeded to test this using just audit mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, well spotted! Corrected.
@ormsbee, could you help us with triggering the pipeline? |
e4912d9
to
475a313
Compare
def __init__(self, course_key: CourseKey, user: types.User, at_time: datetime): | ||
super().__init__(course_key, user, at_time) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean but I tried to follow what was done in other processors : EnrollmentTrackPartitionGroupsOutlineProcessor, ContentGatingOutlineProcessor, ScheduleOutlineProcessor.
course_blocks['children'] = [chapter_data | ||
for chapter_data in course_blocks['children'] | ||
if chapter_data['id'] in available_section_ids | ||
] if 'children' in course_blocks else [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please keep the old .get('children', [])
piece instead of adding the if 'children' in...
bit at the tail end of the list comprehension. Try to limit the use of the foo = bar if something else bar2
syntax to simple one-liners.
So something like:
course_blocks['children'] = [
chapter_data
for chapter_data in course_blocks.get('children', [])
if chapter_data['id'] in available_section_ids
]
FWIW, the linter might complain to you about the indentation here. I'm not sure if we have it in the rules for list comprehensions, but I tend to follow our long function call conventions when doing them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also fixed the CI pipeline errors.
16e9d3b
to
b1e377a
Compare
@CefBoud: We do have your CLA back, so hopefully we can get this cleared soon. I'll let you know as soon as that part is all set. Thank you. |
@mphilbrick211: Yeah, this is still in our court I think. I'll ping you with more details. |
d2ed435
to
3134903
Compare
@CefBoud: Thank you for your patience during this process. I'm sorry that you had to go through it right as we were messing with the DocuSign integration. I see your CLA all set in our system now, so please rebase and I'll merge this later today (or first thing tomorrow). |
3134903
to
b4a922a
Compare
@ormsbee Thank you! I am glad to hear it. I rebased and I see that the CLA is all set up. 😃 |
Re-running the tests now. I'll merge this as soon as tests pass. |
b4a922a
to
32bb24b
Compare
@CefBoud 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
2U Release Notice: This PR has been deployed to the edX staging environment in preparation for a release to production. |
2U Release Notice: This PR has been deployed to the edX production environment. |
1 similar comment
2U Release Notice: This PR has been deployed to the edX production environment. |
ISSUE #32892
Description
This PR addresses Issue#32892. The problem is that users who don't have access to any units in a sequence, because their cohort lacks the permission, can still see the sequence in their outline in the
frontend-app-learning
. The same applies to sections. If a user doesn't have access to all the section's sequences, the section should not be part of the outline.As the issue mentions, there is a function that bubbles up access groups from Units to the parent Sequence in case all Units have the same access. This PR generalizes the function and applies it to bubble up access groups from Sequences to the parent Section in case all Sequences have the same access.=> No bubbling to avoid performance issuesTo get the outline, we rely on a list of processors. From what I can tell, only EnrollmentTrackPartitionGroupsOutlineProcessor removes inaccessible Sections/Sequences by relying on
User Partitions
, but as the name implies, only in the case of Enrollment Track restrictions, not cohorts. That's why this PR introduces a newCohortPartitionGroupsOutlineProcessor
.Supporting information
get_cohorted_user_partition_id
inopenedx/core/djangoapps/course_groups/cohorts.py
because there is a need to retrieve the course's cohorted partition id, to check cohorted access. The function must solely rely on a Django Model (MySql) unlike other functions in the same file which in multiple cases lead to an interaction with themodulestore
, and this is prohibited in all OutlineProcessor.Testing instructions
user2
for example) and enroll in the Demo Course.and create a Content Group
group1
.cohort1
in Instructor Tab > Cohorts Tab in the LMS and link it togroup1
.cohort2
without assigning it to any group. Assignuser2
tocohort2
in the same tab.group2
for instance, Introduction: Video and Sequencesuser2
will be able to see the Section & Sequence even if he doesn't have access to the underlying Unit.The video below recreates the problem. At the end,
user2
should not be able to see the Introduction Section, nor the Demo Course Overview Sequence.demo_issue_edx-platform_32892.mp4
After applying this PR, the Sequences whose Units are inaccessible will not show in the outline. Neither will the Sections whose Sequences are inaccessible.