diff --git a/lms/djangoapps/course_home_api/outline/views.py b/lms/djangoapps/course_home_api/outline/views.py index df031e259a..703d55211b 100644 --- a/lms/djangoapps/course_home_api/outline/views.py +++ b/lms/djangoapps/course_home_api/outline/views.py @@ -2,7 +2,6 @@ Outline Tab Views """ from datetime import datetime, timezone -from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory from completion.exceptions import UnavailableCompletionData # lint-amnesty, pylint: disable=wrong-import-order from completion.utilities import get_key_to_last_completed_block # lint-amnesty, pylint: disable=wrong-import-order @@ -38,7 +37,9 @@ from lms.djangoapps.courseware.context_processor import user_timezone_locale_pre from lms.djangoapps.courseware.courses import get_course_date_blocks, get_course_info_section, get_course_with_access from lms.djangoapps.courseware.date_summary import TodaysDate from lms.djangoapps.courseware.masquerade import is_masquerading, setup_masquerade +from lms.djangoapps.courseware.toggles import course_is_invitation_only from lms.djangoapps.courseware.views.views import get_cert_data +from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory from openedx.core.djangoapps.content.learning_sequences.api import ( get_user_course_outline, public_api_available as learning_sequences_api_available, @@ -275,14 +276,14 @@ class OutlineTabView(RetrieveAPIView): if allow_public or user_is_masquerading: handouts_html = get_course_info_section(request, request.user, course, 'handouts') - if not show_enrolled: + if not is_enrolled: if CourseMode.is_masters_only(course_key): enroll_alert['can_enroll'] = False enroll_alert['extra_text'] = _( 'Please contact your degree administrator or ' '{platform_name} Support if you have questions.' ).format(platform_name=settings.PLATFORM_NAME) - elif course.invitation_only: + elif course_is_invitation_only(course): enroll_alert['can_enroll'] = False # Sometimes there are sequences returned by Course Blocks that we diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py index a3ef809614..b03144888f 100644 --- a/lms/djangoapps/courseware/access.py +++ b/lms/djangoapps/courseware/access.py @@ -42,7 +42,7 @@ from lms.djangoapps.courseware.masquerade import get_masquerade_role, is_masquer from lms.djangoapps.ccx.custom_exception import CCXLocatorValidationException from lms.djangoapps.ccx.models import CustomCourseForEdX from lms.djangoapps.mobile_api.models import IgnoreMobileAvailableFlagConfig -from lms.djangoapps.courseware.toggles import is_courses_default_invite_only_enabled +from lms.djangoapps.courseware.toggles import course_is_invitation_only from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.features.course_duration_limits.access import check_course_expired from common.djangoapps.student import auth @@ -272,8 +272,8 @@ def _can_enroll_courselike(user, courselike): if _has_staff_access_to_descriptor(user, courselike, course_key): return ACCESS_GRANTED - # Access denied when default value of COURSES_INVITE_ONLY set to True - if is_courses_default_invite_only_enabled() or courselike.invitation_only: + # Access denied when the course requires an invitation + if course_is_invitation_only(courselike): debug("Deny: invitation only") return ACCESS_DENIED diff --git a/lms/djangoapps/courseware/toggles.py b/lms/djangoapps/courseware/toggles.py index ad2964a845..faa010731d 100644 --- a/lms/djangoapps/courseware/toggles.py +++ b/lms/djangoapps/courseware/toggles.py @@ -114,6 +114,19 @@ COURSEWARE_OPTIMIZED_RENDER_XBLOCK = CourseWaffleFlag( WAFFLE_FLAG_NAMESPACE, 'optimized_render_xblock', __name__ ) +# .. toggle_name: COURSES_INVITE_ONLY +# .. toggle_implementation: SettingToggle +# .. toggle_type: feature_flag +# .. toggle_default: False +# .. toggle_description: Setting this sets the default value of INVITE_ONLY across all courses in a given deployment +# .. toggle_category: admin +# .. toggle_use_cases: open_edx +# .. toggle_creation_date: 2019-05-16 +# .. toggle_expiration_date: None +# .. toggle_tickets: https://github.com/mitodl/edx-platform/issues/123 +# .. toggle_status: unsupported +COURSES_INVITE_ONLY = SettingToggle('COURSES_INVITE_ONLY', default=False) + def courseware_mfe_is_active(course_key: CourseKey) -> bool: """ @@ -238,16 +251,6 @@ def streak_celebration_is_active(course_key): ) -# .. toggle_name: COURSES_INVITE_ONLY -# .. toggle_implementation: SettingToggle -# .. toggle_type: feature_flag -# .. toggle_default: False -# .. toggle_description: Setting this sets the default value of INVITE_ONLY across all courses in a given deployment -# .. toggle_category: admin -# .. toggle_use_cases: open_edx -# .. toggle_creation_date: 2019-05-16 -# .. toggle_expiration_date: None -# .. toggle_tickets: https://github.com/mitodl/edx-platform/issues/123 -# .. toggle_status: unsupported -def is_courses_default_invite_only_enabled(): - return SettingToggle("COURSES_INVITE_ONLY", default=False).is_enabled() +def course_is_invitation_only(courselike) -> bool: + """Returns whether the course is invitation only or not.""" + return COURSES_INVITE_ONLY.is_enabled() or courselike.invitation_only diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index c73f8c7e23..0ea4121819 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -97,7 +97,7 @@ from lms.djangoapps.courseware.permissions import ( VIEW_COURSE_HOME, VIEW_COURSEWARE, ) -from lms.djangoapps.courseware.toggles import is_courses_default_invite_only_enabled +from lms.djangoapps.courseware.toggles import course_is_invitation_only from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient from lms.djangoapps.edxnotes.helpers import is_feature_enabled from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context @@ -733,7 +733,7 @@ class CourseTabView(EdxFragmentView): @staticmethod def course_open_for_learner_enrollment(course): return (course_open_for_self_enrollment(course.id) - and not course.invitation_only + and not course_is_invitation_only(course) and not CourseMode.is_masters_only(course.id)) @staticmethod @@ -976,7 +976,7 @@ def course_about(request, course_id): # Used to provide context to message to student if enrollment not allowed can_enroll = bool(request.user.has_perm(ENROLL_IN_COURSE, course)) - invitation_only = is_courses_default_invite_only_enabled() or course.invitation_only + invitation_only = course_is_invitation_only(course) is_course_full = CourseEnrollment.objects.is_course_full(course) # Register button should be disabled if one of the following is true: diff --git a/lms/templates/courseware/course_about.html b/lms/templates/courseware/course_about.html index fbabfe0d36..629bd3fc2e 100644 --- a/lms/templates/courseware/course_about.html +++ b/lms/templates/courseware/course_about.html @@ -5,7 +5,6 @@ from django.utils.translation import gettext as _ from django.utils.translation import pgettext from django.urls import reverse from lms.djangoapps.courseware.courses import get_course_about_section -from lms.djangoapps.courseware.toggles import is_courses_default_invite_only_enabled from django.conf import settings from six import text_type from common.djangoapps.edxmako.shortcuts import marketing_link @@ -90,7 +89,7 @@ from six import string_types ${_("Course is full")} - % elif (is_courses_default_invite_only_enabled() or invitation_only) and not can_enroll: + % elif invitation_only and not can_enroll: ${_("Enrollment in this course is by invitation only")} ## Shib courses need the enrollment button to be displayed even when can_enroll is False, ## because AnonymousUsers cause can_enroll for shib courses to be False, but we need them to be able to click diff --git a/openedx/features/course_experience/views/course_home_messages.py b/openedx/features/course_experience/views/course_home_messages.py index dd8c2e5824..de6e5afd18 100644 --- a/openedx/features/course_experience/views/course_home_messages.py +++ b/openedx/features/course_experience/views/course_home_messages.py @@ -27,6 +27,7 @@ from lms.djangoapps.course_goals.api import ( ) from lms.djangoapps.course_goals.models import GOAL_KEY_CHOICES from lms.djangoapps.courseware.access_utils import check_public_access +from lms.djangoapps.courseware.toggles import course_is_invitation_only from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.core.djangolib.markup import HTML, Text from openedx.features.course_experience import CourseHomeMessages @@ -149,7 +150,7 @@ def _register_course_home_messages(request, course, user_access, course_start_da )).format(platform_name=settings.PLATFORM_NAME), title=title ) - elif not course.invitation_only: + elif not course_is_invitation_only(course): CourseHomeMessages.register_info_message( request, Text(_(