Skip to content

Commit d149e34

Browse files
BryanttVsandroscosta
authored andcommitted
feat: add feature toggle for private fields in profile information report
1 parent 624d563 commit d149e34

File tree

3 files changed

+66
-33
lines changed

3 files changed

+66
-33
lines changed

lms/djangoapps/instructor/tests/test_api.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from django.http import HttpRequest, HttpResponse
2323
from django.test import RequestFactory, TestCase
2424
from django.test.client import MULTIPART_CONTENT
25+
from django.test.utils import override_settings
2526
from django.urls import reverse as django_reverse
2627
from django.utils.translation import gettext as _
2728
from edx_when.api import get_dates_for_course, get_overrides_for_user, set_date_for_block
@@ -2626,6 +2627,23 @@ def test_get_students_features(self):
26262627
assert student_json['city'] == student.profile.city
26272628
assert student_json['country'] == ''
26282629

2630+
@ddt.data(True, False)
2631+
def test_get_students_features_private_fields(self, show_private_fields):
2632+
"""
2633+
Test that the get_students_features returns the expected private fields
2634+
"""
2635+
with override_settings(FEATURES={'SHOW_PRIVATE_FIELDS_IN_PROFILE_INFORMATION_REPORT': show_private_fields}):
2636+
url = reverse('get_students_features', kwargs={'course_id': str(self.course.id)})
2637+
response = self.client.post(url, {})
2638+
res_json = json.loads(response.content.decode('utf-8'))
2639+
2640+
assert 'students' in res_json
2641+
for student in res_json['students']:
2642+
if show_private_fields:
2643+
assert 'year_of_birth' in student
2644+
else:
2645+
assert 'year_of_birth' not in student
2646+
26292647
@ddt.data(True, False)
26302648
def test_get_students_features_cohorted(self, is_cohorted):
26312649
"""

lms/djangoapps/instructor/views/api.py

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,40 +1485,45 @@ def post(self, request, course_id, csv=False): # pylint: disable=redefined-oute
14851485
# We need to clone the list because we modify it below
14861486
query_features = list(configuration_helpers.get_value('student_profile_download_fields', []))
14871487

1488-
if not query_features:
1489-
query_features = [
1490-
'id', 'username', 'name', 'email', 'language', 'location',
1491-
'year_of_birth', 'gender', 'level_of_education', 'mailing_address',
1492-
'goals', 'enrollment_mode', 'last_login', 'date_joined', 'external_user_key'
1493-
]
1494-
keep_field_private(query_features, 'year_of_birth') # protected information
1495-
1496-
# Provide human-friendly and translatable names for these features. These names
1497-
# will be displayed in the table generated in data_download.js. It is not (yet)
1498-
# used as the header row in the CSV, but could be in the future.
1499-
query_features_names = {
1500-
'id': _('User ID'),
1501-
'username': _('Username'),
1502-
'name': _('Name'),
1503-
'email': _('Email'),
1504-
'language': _('Language'),
1505-
'location': _('Location'),
1506-
# 'year_of_birth': _('Birth Year'), treated as privileged information as of TNL-10683,
1507-
# not to go in reports
1508-
'gender': _('Gender'),
1509-
'level_of_education': _('Level of Education'),
1510-
'mailing_address': _('Mailing Address'),
1511-
'goals': _('Goals'),
1512-
'enrollment_mode': _('Enrollment Mode'),
1513-
'last_login': _('Last Login'),
1514-
'date_joined': _('Date Joined'),
1515-
'external_user_key': _('External User Key'),
1516-
}
1488+
if not query_features:
1489+
query_features = [
1490+
'id', 'username', 'name', 'email', 'language', 'location',
1491+
'year_of_birth', 'gender', 'level_of_education', 'mailing_address',
1492+
'goals', 'enrollment_mode', 'verification_status',
1493+
'last_login', 'date_joined', 'external_user_key',
1494+
'enrollment_date'
1495+
]
1496+
1497+
# Provide human-friendly and translatable names for these features. These names
1498+
# will be displayed in the table generated in data_download.js. It is not (yet)
1499+
# used as the header row in the CSV, but could be in the future.
1500+
query_features_names = {
1501+
'id': _('User ID'),
1502+
'username': _('Username'),
1503+
'name': _('Name'),
1504+
'email': _('Email'),
1505+
'language': _('Language'),
1506+
'location': _('Location'),
1507+
'year_of_birth': _('Birth Year'),
1508+
'gender': _('Gender'),
1509+
'level_of_education': _('Level of Education'),
1510+
'mailing_address': _('Mailing Address'),
1511+
'goals': _('Goals'),
1512+
'enrollment_mode': _('Enrollment Mode'),
1513+
'last_login': _('Last Login'),
1514+
'date_joined': _('Date Joined'),
1515+
'external_user_key': _('External User Key'),
1516+
'enrollment_date': _('Enrollment Date'),
1517+
}
1518+
1519+
if not settings.FEATURES.get('SHOW_PRIVATE_FIELDS_IN_PROFILE_INFORMATION_REPORT', False):
1520+
keep_field_private(query_features, 'year_of_birth')
1521+
query_features_names.pop('year_of_birth', None)
15171522

1518-
if is_course_cohorted(course.id):
1519-
# Translators: 'Cohort' refers to a group of students within a course.
1520-
query_features.append('cohort')
1521-
query_features_names['cohort'] = _('Cohort')
1523+
if is_course_cohorted(course.id):
1524+
# Translators: 'Cohort' refers to a group of students within a course.
1525+
query_features.append('cohort')
1526+
query_features_names['cohort'] = _('Cohort')
15221527

15231528
if course.teams_enabled:
15241529
query_features.append('team')

lms/envs/common.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,16 @@
10671067
# .. toggle_creation_date: 2024-04-02
10681068
# .. toggle_target_removal_date: None
10691069
'BADGES_ENABLED': False,
1070+
1071+
# .. toggle_name: FEATURES['SHOW_PRIVATE_FIELDS_IN_PROFILE_INFORMATION_REPORT']
1072+
# .. toggle_implementation: DjangoSetting
1073+
# .. toggle_default: False
1074+
# .. toggle_description: Adds private fields to the profile information report.
1075+
# .. toggle_use_cases: open_edx
1076+
# .. toggle_creation_date: 2025-05-12
1077+
# .. toggle_target_removal_date: None
1078+
# .. toggle_tickets: https://github.com/openedx/edx-platform/pull/36688
1079+
'SHOW_PRIVATE_FIELDS_IN_PROFILE_INFORMATION_REPORT': False,
10701080
}
10711081

10721082
# Specifies extra XBlock fields that should available when requested via the Course Blocks API

0 commit comments

Comments
 (0)