fix: Account level preference visibility WRT roles (#36391)

fix: Account level preference visibility WRT roles
This commit is contained in:
Ahtisham Shahid
2025-03-21 14:19:33 +05:00
committed by GitHub
parent 2009e8972c
commit 9775ceff2b
3 changed files with 84 additions and 2 deletions

View File

@@ -1,9 +1,15 @@
"""
Test cases for the notification utility functions.
"""
import copy
import unittest
from openedx.core.djangoapps.notifications.utils import aggregate_notification_configs
import pytest
from common.djangoapps.student.tests.factories import UserFactory
from openedx.core.djangoapps.django_comment_common.models import assign_role, FORUM_ROLE_MODERATOR
from openedx.core.djangoapps.notifications.utils import aggregate_notification_configs, \
filter_out_visible_preferences_by_course_ids
class TestAggregateNotificationConfigs(unittest.TestCase):
@@ -286,3 +292,55 @@ class TestAggregateNotificationConfigs(unittest.TestCase):
result = aggregate_notification_configs(config_list)
assert result["grading"]["notification_types"]["core"]["email_cadence"] == "Mixed"
@pytest.mark.django_db
class TestVisibilityFilter(unittest.TestCase):
"""
Test cases for the filter_out_visible_preferences_by_course_ids function.
"""
def setUp(self):
self.user = UserFactory()
self.course_key = "course-v1:edX+DemoX+Demo_Course"
self.mock_preferences = {
'discussion': {
'enabled': True,
'non_editable': {'core': ['web']},
'notification_types': {
'core': {'web': True, 'push': True, 'email': True, 'email_cadence': 'Daily'},
'content_reported': {'web': True, 'push': True, 'email': True, 'email_cadence': 'Daily'},
'new_question_post': {'web': False, 'push': False, 'email': False, 'email_cadence': 'Daily'},
'new_discussion_post': {'web': False, 'push': False, 'email': False, 'email_cadence': 'Daily'}
},
'core_notification_types': [
'new_response', 'comment_on_followed_post',
'response_endorsed_on_thread', 'new_comment_on_response',
'new_comment', 'response_on_followed_post', 'response_endorsed'
]
}
}
def test_visibility_filter_with_no_role(self):
"""
Test that the preferences are filtered out correctly when the user has no role.
"""
updated_preferences = filter_out_visible_preferences_by_course_ids(
self.user,
copy.deepcopy(self.mock_preferences),
[self.course_key]
)
assert updated_preferences != self.mock_preferences
assert not updated_preferences["discussion"]["notification_types"].get("content_reported", False)
def test_visibility_filter_with_instructor_role(self):
"""
Instructors should see all preferences.
"""
updated_preferences = filter_out_visible_preferences_by_course_ids(
self.user,
self.mock_preferences,
[self.course_key]
)
assign_role(self.course_key, self.user, FORUM_ROLE_MODERATOR)
assert updated_preferences == self.mock_preferences

View File

@@ -269,3 +269,21 @@ def aggregate_notification_configs(existing_user_configs: List[Dict]) -> Dict:
result_config[app]["notification_types"][type_key]["email_cadence"] = (
result_config[app]["notification_types"][type_key]["email_cadence"].pop())
return result_config
def filter_out_visible_preferences_by_course_ids(user, preferences: Dict, course_ids: List) -> Dict:
"""
Filter out notifications visible to forum roles from user preferences.
"""
forum_roles = Role.objects.filter(users__id=user.id).values_list('name', flat=True)
course_roles = CourseAccessRole.objects.filter(
user=user,
course_id__in=course_ids
).values_list('role', flat=True)
notification_types_with_visibility = get_notification_types_with_visibility_settings()
return filter_out_visible_notifications(
preferences,
notification_types_with_visibility,
forum_roles,
course_roles
)

View File

@@ -39,7 +39,8 @@ from .serializers import (
UserNotificationPreferenceUpdateAllSerializer,
UserNotificationPreferenceUpdateSerializer
)
from .utils import get_is_new_notification_view_enabled, get_show_notifications_tray, aggregate_notification_configs
from .utils import get_is_new_notification_view_enabled, get_show_notifications_tray, aggregate_notification_configs, \
filter_out_visible_preferences_by_course_ids
@allow_any_authenticated_user()
@@ -588,6 +589,11 @@ class AggregatedNotificationPreferences(APIView):
notification_configs = aggregate_notification_configs(
notification_configs
)
filter_out_visible_preferences_by_course_ids(
request.user,
notification_configs,
notification_preferences.values_list('course_id', flat=True),
)
notification_preferences_viewed_event(request)
return Response({
'status': 'success',