Skip to content

Commit

Permalink
Merge branch 'master' into viadanna/default-invitation-only-master
Browse files Browse the repository at this point in the history
  • Loading branch information
viadanna authored Sep 9, 2024
2 parents 8b28894 + f52c08a commit 7989fa4
Show file tree
Hide file tree
Showing 24 changed files with 590 additions and 544 deletions.
3 changes: 2 additions & 1 deletion cms/djangoapps/contentstore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,7 @@ def get_library_context(request, request_is_json=False):
)
from cms.djangoapps.contentstore.views.library import (
LIBRARIES_ENABLED,
user_can_view_create_library_button,
)

libraries = _accessible_libraries_iter(request.user) if LIBRARIES_ENABLED else []
Expand All @@ -1550,7 +1551,7 @@ def get_library_context(request, request_is_json=False):
'in_process_course_actions': [],
'courses': [],
'libraries_enabled': LIBRARIES_ENABLED,
'show_new_library_button': LIBRARIES_ENABLED and request.user.is_active,
'show_new_library_button': user_can_view_create_library_button(request.user) and request.user.is_active,
'user': request.user,
'request_course_creator_url': reverse('request_course_creator'),
'course_creator_status': _get_course_creator_status(request.user),
Expand Down
56 changes: 24 additions & 32 deletions cms/djangoapps/contentstore/views/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,31 +69,7 @@ def should_redirect_to_library_authoring_mfe():
)


def user_can_view_create_library_button(user):
"""
Helper method for displaying the visibilty of the create_library_button.
"""
if not LIBRARIES_ENABLED:
return False
elif user.is_staff:
return True
elif settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
is_course_creator = get_course_creator_status(user) == 'granted'
has_org_staff_role = OrgStaffRole().get_orgs_for_user(user).exists()
has_course_staff_role = UserBasedRole(user=user, role=CourseStaffRole.ROLE).courses_with_role().exists()
has_course_admin_role = UserBasedRole(user=user, role=CourseInstructorRole.ROLE).courses_with_role().exists()
return is_course_creator or has_org_staff_role or has_course_staff_role or has_course_admin_role
else:
# EDUCATOR-1924: DISABLE_LIBRARY_CREATION overrides DISABLE_COURSE_CREATION, if present.
disable_library_creation = settings.FEATURES.get('DISABLE_LIBRARY_CREATION', None)
disable_course_creation = settings.FEATURES.get('DISABLE_COURSE_CREATION', False)
if disable_library_creation is not None:
return not disable_library_creation
else:
return not disable_course_creation


def user_can_create_library(user, org):
def _user_can_create_library_for_org(user, org=None):
"""
Helper method for returning the library creation status for a particular user,
taking into account the value LIBRARIES_ENABLED.
Expand All @@ -109,29 +85,29 @@ def user_can_create_library(user, org):
Course Staff: Can make libraries in the organization which has courses of which they are staff.
Course Admin: Can make libraries in the organization which has courses of which they are Admin.
"""
if org is None:
return False
if not LIBRARIES_ENABLED:
return False
elif user.is_staff:
return True
if settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
elif settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
org_filter_params = {}
if org:
org_filter_params['org'] = org
is_course_creator = get_course_creator_status(user) == 'granted'
has_org_staff_role = org in OrgStaffRole().get_orgs_for_user(user)
has_org_staff_role = OrgStaffRole().get_orgs_for_user(user).filter(**org_filter_params).exists()
has_course_staff_role = (
UserBasedRole(user=user, role=CourseStaffRole.ROLE)
.courses_with_role()
.filter(org=org)
.filter(**org_filter_params)
.exists()
)
has_course_admin_role = (
UserBasedRole(user=user, role=CourseInstructorRole.ROLE)
.courses_with_role()
.filter(org=org)
.filter(**org_filter_params)
.exists()
)
return is_course_creator or has_org_staff_role or has_course_staff_role or has_course_admin_role

else:
# EDUCATOR-1924: DISABLE_LIBRARY_CREATION overrides DISABLE_COURSE_CREATION, if present.
disable_library_creation = settings.FEATURES.get('DISABLE_LIBRARY_CREATION', None)
Expand All @@ -142,6 +118,22 @@ def user_can_create_library(user, org):
return not disable_course_creation


def user_can_view_create_library_button(user):
"""
Helper method for displaying the visibilty of the create_library_button.
"""
return _user_can_create_library_for_org(user)


def user_can_create_library(user, org):
"""
Helper method for to check if user can create library for given org.
"""
if org is None:
return False
return _user_can_create_library_for_org(user, org)


@login_required
@ensure_csrf_cookie
@require_http_methods(('GET', 'POST'))
Expand Down
1 change: 0 additions & 1 deletion cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,6 @@
'openedx.core.djangoapps.cache_toolbox.middleware.CacheBackedAuthenticationMiddleware',

'common.djangoapps.student.middleware.UserStandingMiddleware',
'openedx.core.djangoapps.contentserver.middleware.StaticContentServerMiddleware',

'django.contrib.messages.middleware.MessageMiddleware',
'common.djangoapps.track.middleware.TrackMiddleware',
Expand Down
4 changes: 0 additions & 4 deletions common/djangoapps/util/tests/test_db.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Tests for util.db module."""

import unittest
from io import StringIO

import ddt
Expand Down Expand Up @@ -121,9 +120,6 @@ class MigrationTests(TestCase):
Tests for migrations.
"""

@unittest.skip(
"Temporary skip for ENT-8972 while the char field decrypted client secret columns in SAP is removed."
)
@override_settings(MIGRATION_MODULES={})
def test_migrations_are_in_sync(self):
"""
Expand Down
18 changes: 11 additions & 7 deletions lms/djangoapps/bulk_email/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,16 @@ def opt_out_email_updates(request, token, course_id):
course_id,
)

tracker.emit(
'edx.bulk_email.opt_out',
{
'course_id': course_id,
'user_id': user.id,
}
)
event_name = 'edx.bulk_email.opt_out'
event_data = {
"username": user.username,
"user_id": user.id,
"course_id": course_id,
}
with tracker.get_tracker().context(event_name, event_data):
tracker.emit(
event_name,
event_data
)

return render_to_response('bulk_email/unsubscribe_success.html', context)
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class CourseHomeMetadataSerializer(VerifiedModeSerializer):
"""
celebrations = serializers.DictField()
course_access = serializers.DictField()
studio_access = serializers.BooleanField()
course_id = serializers.CharField()
is_enrolled = serializers.BooleanField()
is_self_paced = serializers.BooleanField()
Expand Down
3 changes: 2 additions & 1 deletion lms/djangoapps/course_home_api/course_metadata/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from lms.djangoapps.course_api.api import course_detail
from lms.djangoapps.course_goals.models import UserActivity
from lms.djangoapps.course_home_api.course_metadata.serializers import CourseHomeMetadataSerializer
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.access import has_access, has_cms_access
from lms.djangoapps.courseware.context_processor import user_timezone_locale_prefs
from lms.djangoapps.courseware.courses import check_course_access
from lms.djangoapps.courseware.masquerade import setup_masquerade
Expand Down Expand Up @@ -124,6 +124,7 @@ def get(self, request, *args, **kwargs):
data = {
'course_id': course.id,
'username': username,
'studio_access': has_cms_access(request.user, course_key),
'is_staff': has_access(request.user, 'staff', course_key).has_access,
'original_user_is_staff': original_user_is_staff,
'number': course.display_number_with_default,
Expand Down
28 changes: 27 additions & 1 deletion lms/djangoapps/courseware/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
GlobalStaff,
OrgInstructorRole,
OrgStaffRole,
SupportStaffRole
SupportStaffRole,
CourseLimitedStaffRole,
)
from common.djangoapps.util import milestones_helpers as milestones_helpers # lint-amnesty, pylint: disable=useless-import-alias
from common.djangoapps.util.milestones_helpers import (
Expand Down Expand Up @@ -97,6 +98,31 @@ def has_ccx_coach_role(user, course_key):
return False


def has_cms_access(user, course_key):
"""
Check if user has access to the CMS. When requesting from the LMS, a user with the
limited staff access role needs access to the CMS APIs, but not the CMS site. This
function accounts for this edge case when determining if a user has access to the CMS
site.
Arguments:
user (User): the user whose course access we are checking.
course_key: Key to course.
Returns:
bool: whether user has access to the CMS site.
"""
has_course_author_access = auth.has_course_author_access(user, course_key)
is_limited_staff = auth.user_has_role(
user, CourseLimitedStaffRole(course_key)
) and not GlobalStaff().has_user(user)

if is_limited_staff and has_course_author_access:
return False

return has_course_author_access


@function_trace('has_access')
def has_access(user, action, obj, course_key=None):
"""
Expand Down
10 changes: 8 additions & 2 deletions lms/djangoapps/courseware/tests/test_about.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ def test_pre_requisite_course(self):
assert resp.status_code == 200
pre_requisite_courses = get_prerequisite_courses_display(course)
pre_requisite_course_about_url = reverse('about_course', args=[str(pre_requisite_courses[0]['key'])])
assert '<span class="important-dates-item-text pre-requisite"><a href="{}">{}</a></span>'.format(pre_requisite_course_about_url, pre_requisite_courses[0]['display']) in resp.content.decode(resp.charset).strip('\n') # pylint: disable=line-too-long
assert (
f'You must successfully complete <a href="{pre_requisite_course_about_url}">'
f'{pre_requisite_courses[0]["display"]}</a> before you begin this course.'
) in resp.content.decode(resp.charset).strip('\n')

@patch.dict(settings.FEATURES, {'ENABLE_PREREQUISITE_COURSES': True})
def test_about_page_unfulfilled_prereqs(self):
Expand Down Expand Up @@ -190,7 +193,10 @@ def test_about_page_unfulfilled_prereqs(self):
assert resp.status_code == 200
pre_requisite_courses = get_prerequisite_courses_display(course)
pre_requisite_course_about_url = reverse('about_course', args=[str(pre_requisite_courses[0]['key'])])
assert '<span class="important-dates-item-text pre-requisite"><a href="{}">{}</a></span>'.format(pre_requisite_course_about_url, pre_requisite_courses[0]['display']) in resp.content.decode(resp.charset).strip('\n') # pylint: disable=line-too-long
assert (
f'You must successfully complete <a href="{pre_requisite_course_about_url}">'
f'{pre_requisite_courses[0]["display"]}</a> before you begin this course.'
) in resp.content.decode(resp.charset).strip('\n')

url = reverse('about_course', args=[str(pre_requisite_course.id)])
resp = self.client.get(url)
Expand Down
9 changes: 9 additions & 0 deletions lms/djangoapps/instructor/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3515,6 +3515,14 @@ def test_send_email_but_not_logged_in(self):
self.client.logout()
url = reverse('send_email', kwargs={'course_id': str(self.course.id)})
response = self.client.post(url, self.full_test_message)
assert response.status_code == 401

def test_send_email_logged_in_but_no_perms(self):
self.client.logout()
user = UserFactory()
self.client.login(username=user.username, password=self.TEST_PASSWORD)
url = reverse('send_email', kwargs={'course_id': str(self.course.id)})
response = self.client.post(url, self.full_test_message)
assert response.status_code == 403

def test_send_email_but_not_staff(self):
Expand Down Expand Up @@ -3635,6 +3643,7 @@ def test_send_email_with_lapsed_date_expect_error(self):

url = reverse('send_email', kwargs={'course_id': str(self.course.id)})
with LogCapture() as log:

response = self.client.post(url, self.full_test_message)

assert response.status_code == 400
Expand Down
Loading

0 comments on commit 7989fa4

Please sign in to comment.