Bszabo/tnl 10683 birth year (#32200)

* fix: TNL-10683 birthyear protected 


No unit tests yet

* fix: TNL-10683 add unit tests

* fix: TNL-10683 fix lint errors

* fix: TNL-10683 add required docstrings

* fix: TNL-10683 hide year-of-birth feature name

---------

Co-authored-by: Bernard Szabo <bszabo@edx.org>
This commit is contained in:
bszabo
2023-05-09 12:36:22 -04:00
committed by GitHub
parent 93e3ed9418
commit dc4a54060c
3 changed files with 53 additions and 1 deletions

View File

@@ -458,3 +458,39 @@ class TestStudentFromIdentifier(TestCase):
"""Test with invalid identifier"""
with pytest.raises(User.DoesNotExist):
assert tools.get_student_from_identifier("invalid")
class TestProfilePrivacy(TestCase):
'''
Tests utility function for stripping a feature from the list of features to be reported on
'''
def test_no_feature_list_supplied(self):
'''
Missing first argument raises an exception
'''
with pytest.raises(tools.DashboardError):
assert tools.keep_field_private(None, "bogus_field_name")
def test_no_privacy_feature_supplied(self):
'''
Missing second argument raises an exception
'''
with pytest.raises(tools.DashboardError):
assert tools.keep_field_private(["bogus_field1", "bogus_field2"], None)
def test_feature_supplied_and_stripped(self):
'''
Request to strip a feature in feature list succeeds
'''
query_fields = ['Name', 'Address', 'Secret']
assert 'Secret' in query_fields
tools.keep_field_private(query_fields, 'Secret')
assert 'Secret' not in query_fields
def test_feature_absent_and_exception_consumed(self):
'''
Request to strip a feature not in feature list is a silent no-op
'''
query_fields = ['Name', 'Address']
tools.keep_field_private(query_fields, 'Secret')
assert len(query_fields) == 2

View File

@@ -129,6 +129,7 @@ from .tools import (
find_unit,
get_student_from_identifier,
handle_dashboard_error,
keep_field_private,
parse_datetime,
require_student_from_identifier,
set_due_date_extension,
@@ -1430,6 +1431,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
'year_of_birth', 'gender', 'level_of_education', 'mailing_address',
'goals', 'enrollment_mode', 'last_login', 'date_joined', 'external_user_key'
]
keep_field_private(query_features, 'year_of_birth') # protected information
# Provide human-friendly and translatable names for these features. These names
# will be displayed in the table generated in data_download.js. It is not (yet)
@@ -1441,7 +1443,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
'email': _('Email'),
'language': _('Language'),
'location': _('Location'),
'year_of_birth': _('Birth Year'),
# 'year_of_birth': _('Birth Year'), treated as privileged information as of TNL-10683, not to go in reports
'gender': _('Gender'),
'level_of_education': _('Level of Education'),
'mailing_address': _('Mailing Address'),

View File

@@ -256,3 +256,17 @@ def dump_student_extensions(course, student):
"title": _("Due date extensions for {0} {1} ({2})").format(
student.first_name, student.last_name, student.username),
"data": data}
def keep_field_private(query_features, field_name):
'''
Utility to remove a field from a list of field names requested of a report
Keeps the specified field_name private (excluded from report)
'''
if (query_features is None) or (field_name is None):
raise DashboardError("Missing private field specification")
try:
query_features.remove(field_name)
except ValueError:
pass