fix: missing advance_settings_access template variable

Co-authored-by: Farhaan Bukhsh <farhaan.bukhsh@gmail.com>
This commit is contained in:
0x29a
2023-04-19 15:29:06 +02:00
committed by Farhaan Bukhsh
parent 6307961ff6
commit 065f894d1b
6 changed files with 77 additions and 24 deletions

View File

@@ -106,7 +106,12 @@ class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin):
super().setUp()
self.fullcourse = CourseFactory.create()
self.course_setting_url = get_url(self.course.id, 'advanced_settings_handler')
self.non_staff_client, _ = self.create_non_staff_authed_user_client()
self.non_staff_client, self.nonstaff = self.create_non_staff_authed_user_client()
# "nonstaff" means "non Django staff" here. We assign this user to course staff
# role to check that even so they won't have advanced settings access when explicitly
# restricted.
CourseStaffRole(self.course.id).add_users(self.nonstaff)
@override_settings(FEATURES={'DISABLE_MOBILE_COURSE_AVAILABLE': True})
def test_mobile_field_available(self):
@@ -145,16 +150,50 @@ class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin):
self.assertEqual('discussion_blackouts' in response, fields_visible)
self.assertEqual('discussion_topics' in response, fields_visible)
@override_settings(FEATURES={'DISABLE_ADVANCED_SETTINGS': True})
def test_disable_advanced_settings_feature(self):
@ddt.data(False, True)
def test_disable_advanced_settings_feature(self, disable_advanced_settings):
"""
If this feature is enabled, only staff should be able to access the advanced settings page.
If this feature is enabled, only Django Staff/Superuser should be able to access the "Advanced Settings" page.
For non-staff users the "Advanced Settings" tab link should not be visible.
"""
response = self.non_staff_client.get_html(self.course_setting_url)
self.assertEqual(response.status_code, 403)
advanced_settings_link_html = f"<a href=\"{self.course_setting_url}\">Advanced Settings</a>".encode('utf-8')
response = self.client.get_html(self.course_setting_url)
self.assertEqual(response.status_code, 200)
with override_settings(FEATURES={'DISABLE_ADVANCED_SETTINGS': disable_advanced_settings}):
for handler in (
'import_handler',
'export_handler',
'course_team_handler',
'course_info_handler',
'assets_handler',
'tabs_handler',
'settings_handler',
'grading_handler',
'textbooks_list_handler',
):
# Test that non-staff users don't see the "Advanced Settings" tab link.
response = self.non_staff_client.get_html(
get_url(self.course.id, handler)
)
self.assertEqual(response.status_code, 200)
if disable_advanced_settings:
self.assertNotIn(advanced_settings_link_html, response.content)
else:
self.assertIn(advanced_settings_link_html, response.content)
# Test that staff users see the "Advanced Settings" tab link.
response = self.client.get_html(
get_url(self.course.id, handler)
)
self.assertEqual(response.status_code, 200)
self.assertIn(advanced_settings_link_html, response.content)
# Test that non-staff users can't access the "Advanced Settings" page.
response = self.non_staff_client.get_html(self.course_setting_url)
self.assertEqual(response.status_code, 403 if disable_advanced_settings else 200)
# Test that staff users can access the "Advanced Settings" page.
response = self.client.get_html(self.course_setting_url)
self.assertEqual(response.status_code, 200)
@ddt.ddt

View File

@@ -43,7 +43,12 @@ from common.djangoapps.course_action_state.managers import CourseActionStateItem
from common.djangoapps.course_action_state.models import CourseRerunState, CourseRerunUIStateManager
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.edxmako.shortcuts import render_to_response
from common.djangoapps.student.auth import has_course_author_access, has_studio_read_access, has_studio_write_access
from common.djangoapps.student.auth import (
has_course_author_access,
has_studio_read_access,
has_studio_write_access,
has_studio_advanced_settings_access
)
from common.djangoapps.student.roles import (
CourseInstructorRole,
CourseStaffRole,
@@ -149,17 +154,6 @@ class AccessListFallback(Exception):
pass # lint-amnesty, pylint: disable=unnecessary-pass
def has_advanced_settings_access(user):
"""
If DISABLE_ADVANCED_SETTINGS feature is enabled, only global staff can access "Advanced Settings".
"""
return (
not settings.FEATURES.get('DISABLE_ADVANCED_SETTINGS', False)
or user.is_staff
or user.is_superuser
)
def get_course_and_check_access(course_key, user, depth=0):
"""
Function used to calculate and return the locator and course block
@@ -765,7 +759,6 @@ def course_index(request, course_key):
'frontend_app_publisher_url': frontend_app_publisher_url,
'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course_block.id),
'advance_settings_url': reverse_course_url('advanced_settings_handler', course_block.id),
'advance_settings_access': has_advanced_settings_access(request.user),
'proctoring_errors': proctoring_errors,
})
@@ -1437,7 +1430,7 @@ def advanced_settings_handler(request, course_key_string):
json: update the Course's settings. The payload is a json rep of the
metadata dicts.
"""
if not has_advanced_settings_access(request.user):
if not has_studio_advanced_settings_access(request.user):
raise PermissionDenied()
course_key = CourseKey.from_string(course_key_string)

View File

@@ -7,6 +7,7 @@
<%namespace name='static' file='static_content.html'/>
<%!
from django.utils.translation import gettext as _
from common.djangoapps.student.auth import has_studio_advanced_settings_access
from cms.djangoapps.contentstore import utils
from lms.djangoapps.certificates.api import can_show_certificate_available_date_field
from openedx.core.djangolib.js_utils import (
@@ -721,7 +722,9 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url | n, js_escaped_string}'
<li class="nav-item"><a href="${grading_config_url}">${_("Grading")}</a></li>
<li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li>
<li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li>
% if has_studio_advanced_settings_access(request.user):
<li class="nav-item"><a href="${advanced_config_url}">${_("Advanced Settings")}</a></li>
% endif
% if mfe_proctored_exam_settings_url:
<li class="nav-item"><a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a></li>
% endif

View File

@@ -11,6 +11,7 @@
import json
from cms.djangoapps.contentstore import utils
from django.utils.translation import gettext as _
from common.djangoapps.student.auth import has_studio_advanced_settings_access
from cms.djangoapps.models.settings.encoder import CourseSettingsEncoder
from openedx.core.djangolib.js_utils import (
dump_js_escaped_json, js_escaped_string
@@ -168,7 +169,9 @@
<li class="nav-item"><a href="${detailed_settings_url}">${_("Details & Schedule")}</a></li>
<li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li>
<li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li>
% if has_studio_advanced_settings_access(request.user):
<li class="nav-item"><a href="${advanced_settings_url}">${_("Advanced Settings")}</a></li>
% endif
% if mfe_proctored_exam_settings_url:
<li class="nav-item"><a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a></li>
% endif

View File

@@ -7,6 +7,7 @@
from django.urls import reverse
from django.utils.translation import gettext as _
from urllib.parse import quote_plus
from common.djangoapps.student.auth import has_studio_advanced_settings_access
from cms.djangoapps.contentstore import toggles
from cms.djangoapps.contentstore.utils import get_pages_and_resources_url
from openedx.core.djangoapps.discussions.config.waffle import ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND
@@ -120,7 +121,7 @@
<a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a>
</li>
% endif
% if advance_settings_access:
% if has_studio_advanced_settings_access(request.user):
<li class="nav-item nav-course-settings-advanced">
<a href="${advanced_settings_url}">${_("Advanced Settings")}</a>
</li>

View File

@@ -125,9 +125,23 @@ def has_course_author_access(user, course_key):
return has_studio_write_access(user, course_key)
def has_studio_advanced_settings_access(user):
"""
If DISABLE_ADVANCED_SETTINGS feature is enabled, only Django Superuser
or Django Staff can access "Advanced Settings".
By default, this feature is disabled.
"""
return (
not settings.FEATURES.get('DISABLE_ADVANCED_SETTINGS', False)
or user.is_staff
or user.is_superuser
)
def has_studio_read_access(user, course_key):
"""
Return True iff user is allowed to view this course/library in studio.
Return True if user is allowed to view this course/library in studio.
Will also return True if user has write access in studio (has_course_author_access)
There is currently no such thing as read-only course access in studio, but