EDUCATOR 5065 - updates

EDUCATOR 5065 - CR comments 3
This commit is contained in:
atesker
2020-05-29 14:35:32 -04:00
committed by Andytr1
parent 7adb6dd9ac
commit de0e8524a2
2 changed files with 66 additions and 2 deletions

View File

@@ -7,7 +7,11 @@ from collections import Counter
from django.contrib.auth.models import User
from lms.djangoapps.teams.api import OrganizationProtectionStatus, user_organization_protection_status
from lms.djangoapps.teams.api import (
OrganizationProtectionStatus,
user_organization_protection_status,
ORGANIZATION_PROTECTED_MODES
)
from lms.djangoapps.teams.models import CourseTeam, CourseTeamMembership
from lms.djangoapps.program_enrollments.models import ProgramEnrollment
from student.models import CourseEnrollment
@@ -110,8 +114,10 @@ class TeamMembershipImportManager(object):
self.existing_course_team_memberships = {}
self.existing_course_teams = {}
self.user_count_by_team = Counter()
self.user_enrollment_by_team = {}
self.user_to_remove_by_team = Counter()
self.number_of_learners_assigned = 0
self.user_to_actual_enrollment_mode = {}
@property
def import_succeeded(self):
@@ -240,7 +246,7 @@ class TeamMembershipImportManager(object):
if actual_enrollment_mode != supplied_enrollment.strip():
self.validation_errors.append('User ' + user.username + ' enrollment mismatch.')
return False
self.user_to_actual_enrollment_mode[user.id] = actual_enrollment_mode
return True
def is_username_unique(self, username, usernames_found_so_far):
@@ -294,6 +300,8 @@ class TeamMembershipImportManager(object):
pass
continue
try:
if not self.validate_compatible_enrollment_modes(user, team_name, teamset_id):
return False
# checks for a team inside a specific team set. This way team names can be duplicated across
# teamsets
team = self.existing_course_teams[(team_name, teamset_id)]
@@ -306,6 +314,38 @@ class TeamMembershipImportManager(object):
return False
return True
def validate_compatible_enrollment_modes(self, user, team_name, teamset_id):
"""
Validates that only students enrolled in a masters track are on a single team. Disallows mixing of masters
with other enrollment modes on a single team.
"""
if(teamset_id, team_name) not in self.user_enrollment_by_team:
self.user_enrollment_by_team[teamset_id, team_name] = set()
self.user_enrollment_by_team[teamset_id, team_name].add(self.user_to_actual_enrollment_mode[user.id])
if self.is_FERPA_bubble_breached(teamset_id, team_name):
error_message = \
'Team {} cannot have Masters track users mixed with users in other tracks.'.format(team_name)
self.add_error_and_check_if_max_exceeded(error_message)
return False
return True
def is_FERPA_bubble_breached(self, teamset_id, team_name):
"""
Ensures that FERPA bubble is not breached.
Checks that we are not trying to violate FERPA proctection by mixing masters
track students with other enrollment tracks.
"""
team_enrollment_modes = self.user_enrollment_by_team[teamset_id, team_name]
protected_modes = set(ORGANIZATION_PROTECTED_MODES)
if team_enrollment_modes.isdisjoint(protected_modes):
return False
elif team_enrollment_modes.issubset(protected_modes):
return False
else:
return True
def validate_proposed_team_size_wont_exceed_maximum(self, team_name, teamset_id):
"""
Validates that the number of users we want to add to a team won't exceed maximum team size.

View File

@@ -2722,6 +2722,30 @@ class TestBulkMembershipManagement(TeamAPITestCase):
data={'csv': csv_file}, user='staff'
)
def test_upload_invalid_multiple_student_enrollment_mismatch(self):
audit_username = 'audit_user'
masters_username_a = 'masters_a'
masters_username_b = 'masters_b'
self.create_and_enroll_student(username=audit_username, mode=CourseMode.AUDIT)
self.create_and_enroll_student(username=masters_username_a, mode=CourseMode.MASTERS)
self.create_and_enroll_student(username=masters_username_b, mode=CourseMode.MASTERS)
csv_content = 'user,mode,topic_1' + '\n'
csv_content += '{},audit,team wind power'.format(audit_username) + '\n'
csv_content += '{},masters,team wind power'.format(masters_username_a) + '\n'
csv_content += '{},masters,team wind power'.format(masters_username_b) + '\n'
csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv')
self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password)
response = self.make_call(reverse(
'team_membership_bulk_management',
args=[self.good_course_id]),
400, method='post',
data={'csv': csv_file}, user='staff'
)
response_text = json.loads(response.content.decode('utf-8'))
expected_error = 'Team team wind power cannot have Masters track users mixed with users in other tracks.'
self.assertEqual(response_text['errors'][0], expected_error)
def test_upload_learners_exceed_max_team_size(self):
csv_content = 'user,mode,topic_0,topic_1' + '\n'
team1 = 'team wind power'